Security Patterns
Comprehensive security patterns for building hardened applications. Each category has individual rule files in rules/ loaded on-demand.
Quick Reference
| Category |
Rules |
Impact |
When to Use |
| Authentication |
3 |
CRITICAL |
JWT tokens, OAuth 2.1/PKCE, RBAC/permissions |
| Defense-in-Depth |
2 |
CRITICAL |
Multi-layer security, zero-trust architecture |
| Input Validation |
3 |
HIGH |
Schema validation (Zod/Pydantic), output encoding, file uploads |
| OWASP Top 10 |
2 |
CRITICAL |
Injection prevention, broken authentication fixes |
| LLM Safety |
3 |
HIGH |
Prompt injection defense, output guardrails, content filtering |
| PII Masking |
2 |
HIGH |
PII detection/redaction with Presidio, Langfuse, LLM Guard |
| Scanning |
3 |
HIGH |
Dependency audit, SAST (Semgrep/Bandit), secret detection |
| Advanced Guardrails |
2 |
CRITICAL |
NeMo/Guardrails AI validators, red-teaming, OWASP LLM |
Total: 20 rules across 8 categories
Quick Start
from argon2 import PasswordHasher
ph = PasswordHasher()
password_hash = ph.hash(password)
ph.verify(password_hash, password)
import jwt
from datetime import datetime, timedelta, timezone
payload = {
'sub': user_id, 'type': 'access',
'exp': datetime.now(timezone.utc) + timedelta(minutes=15),
}
token = jwt.encode(payload, SECRET_KEY, algorithm='HS256')
import { z } from 'zod';
const UserSchema = z.object({
email: z.string().email(),
name: z.string().min(2).max(100),
role: z.enum(['user', 'admin']).default('user'),
});
const result = UserSchema.safeParse(req.body);
import re
from langfuse import Langfuse
def mask_pii(data, **kwargs):
if isinstance(data, str):
data = re.sub(r'\b[\w.-]+@[\w.-]+\.\w+\b', '[REDACTED_EMAIL]', data)
data = re.sub(r'\b\d{3}-\d{2}-\d{4}\b', '[REDACTED_SSN]', data)
return data
langfuse = Langfuse(mask=mask_pii)
Authentication
Secure authentication with OAuth 2.1, Passkeys/WebAuthn, JWT tokens, and role-based access control.
| Rule |
Description |
auth-jwt.md |
JWT creation, verification, expiry, refresh token rotation |
auth-oauth.md |
OAuth 2.1 with PKCE, DPoP, Passkeys/WebAuthn |
auth-rbac.md |
Role-based access control, permission decorators, MFA |
Key Decisions: Argon2id > bcrypt | Access tokens 15 min | PKCE required | Passkeys > TOTP > SMS
Defense-in-Depth
Multi-layer security architecture with no single point of failure.
| Rule |
Description |
defense-layers.md |
8-layer security architecture (edge to observability) |
defense-zero-trust.md |
Immutable request context, tenant isolation, audit logging |
Key Decisions: Immutable dataclass context | Query-level tenant filtering | No IDs in LLM prompts
Input Validation
Validate and sanitize all untrusted input using Zod v4 and Pydantic.
| Rule |
Description |
validation-input.md |
Schema validation with Zod v4 and Pydantic, type coercion |
validation-output.md |
HTML sanitization, output encoding, XSS prevention |
validation-schemas.md |
Discriminated unions, file upload validation, URL allowlists |
Key Decisions: Allowlist over blocklist | Server-side always | Validate magic bytes not extensions
OWASP Top 10
Protection against the most critical web application security risks.
| Rule |
Description |
owasp-injection.md |
SQL/command injection, parameterized queries, SSRF prevention |
owasp-broken-auth.md |
JWT algorithm confusion, CSRF protection, timing attacks |
Key Decisions: Parameterized queries only | Hardcode JWT algorithm | SameSite=Strict cookies
LLM Safety
Security patterns for LLM integrations including context separation and output validation.
| Rule |
Description |
llm-prompt-injection.md |
Context separation, prompt auditing, forbidden patterns |
llm-guardrails.md |
Output validation pipeline: schema, grounding, safety, size |
llm-content-filtering.md |
Pre-LLM filtering, post-LLM attribution, three-phase pattern |
Key Decisions: IDs flow around LLM, never through | Attribution is deterministic | Audit every prompt
Context Separation (CRITICAL)
Sensitive IDs and data flow AROUND the LLM, never through it. The LLM sees only content β mapping back to entities happens deterministically after.
context = {"user_id": user_id, "tenant_id": tenant_id}
llm_input = f"Summarize this document:\n{doc_text}"
llm_output = call_llm(llm_input)
result = {"summary": llm_output, **context}
Output Validation Pipeline
Every LLM response MUST pass a 4-stage guardrail pipeline before reaching the user:
def validate_llm_output(raw_output: str, schema, sources: list[str]) -> str:
parsed = schema.parse(raw_output)
assert_grounded(parsed, sources)
assert_safe(parsed, max_toxicity=0.5)
assert len(parsed.text) < MAX_OUTPUT_CHARS
return parsed.text
PII Masking
PII detection and masking for LLM observability pipelines and logging.
| Rule |
Description |
pii-detection.md |
Microsoft Presidio, regex patterns, LLM Guard Anonymize |
pii-redaction.md |
Langfuse mask callback, structlog/loguru processors, Vault deanonymization |
Key Decisions: Presidio for enterprise | Replace with type tokens | Use mask callback at init
Scanning
Automated security scanning for dependencies, code, and secrets.
| Rule |
Description |
scanning-dependency.md |
npm audit, pip-audit, Trivy container scanning, CI gating |
scanning-sast.md |
Semgrep and Bandit static analysis, custom rules, pre-commit |
scanning-secrets.md |
Gitleaks, TruffleHog, detect-secrets with baseline management |
Key Decisions: Pre-commit hooks for shift-left | Block on critical/high | Gitleaks + detect-secrets baseline
Advanced Guardrails
Production LLM safety with NeMo Guardrails, Guardrails AI validators, and DeepTeam red-teaming.
| Rule |
Description |
guardrails-nemo.md |
NeMo Guardrails, Colang 2.0 flows, Guardrails AI validators, layered validation |
guardrails-llm-validation.md |
DeepTeam red-teaming (40+ vulnerabilities), OWASP LLM Top 10 compliance |
Key Decisions: NeMo for flows, Guardrails AI for validators | Toxicity 0.5 threshold | Red-team pre-release + quarterly
Managed Hook Hierarchy (CC 2.1.49)
Plugin settings follow a 3-tier precedence:
| Tier |
Source |
Overridable? |
1. Managed (plugin settings.json) |
Plugin author ships defaults |
Yes, by user |
2. Project (.claude/settings.json) |
Repository config |
Yes, by user |
3. User (~/.claude/settings.json) |
Personal preferences |
Final authority |
Security hooks shipped by OrchestKit are managed defaults β users can disable them but are warned. Enterprise admins can lock settings via managed profiles.
Anti-Patterns (FORBIDDEN)
user.password = request.form['password']
response_type=token
return "Email not found"
"SELECT * FROM users WHERE name = '" + name + "'"
if (file.type === 'image/png') {...}
prompt = f"Analyze for user {user_id}"
artifact.user_id = llm_output["user_id"]
logger.info(f"User email: {user.email}")
langfuse.trace(