pattern-engineer-security
Skill0 starsChanged 5 months agoMITView on GitHub
Engineer-facing security guardrails for production code. The non-negotiables — env-only secrets, schema-validated input at the boundary, parameterized queries, HttpOnly+Secure+SameSite cookies, authorize-before-act + ownership checks, sanitized output + security headers, CSRF + per-route rate limits, redacted logs, locked dependencies, SSRF allowlists, locked-down CORS, HMAC webhook verification, OAuth state + PKCE. A quick-lookup catalogue keyed by the surface touched. Activate on code.
- Reads credentials
In this repository74 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- create-bug-issueSkill
- create-enhancement-issueSkill
- create-feature-issuesSkill
- dream-summary-memorySkill
- memory-conventionSkill
- operation-gitSkill
- pattern-architect-api-endpointSkill
- pattern-architect-data-modelSkill
- pattern-architect-deep-moduleSkill
- pattern-e2e-coding-standardSkill
- pattern-engineer-apiSkill
- pattern-engineer-backend-standardSkill
- pattern-engineer-coding-standardSkill
- pattern-engineer-containerSkill
- pattern-engineer-databaseSkill
- pattern-engineer-fastapiSkill
- pattern-engineer-frontend-standardSkill
- pattern-engineer-goSkill
- pattern-engineer-javaSkill
- pattern-engineer-kotlinSkill
- pattern-engineer-nodeSkill
- pattern-engineer-non-functionalSkill
- pattern-engineer-observabilitySkill
- pattern-engineer-pythonSkill
- pattern-engineer-rustSkill
- pattern-engineer-ssrSkill
- pattern-engineer-swiftSkill
- pattern-engineer-typescriptSkill
- pattern-engineer-viteSkill
- pattern-exploratory-testingSkill
- pattern-reviewer-apiSkill
- pattern-reviewer-backend-standardSkill
- pattern-reviewer-coding-standardSkill
- pattern-reviewer-containerSkill
- pattern-reviewer-contractSkill
- pattern-reviewer-databaseSkill
- pattern-reviewer-fastapiSkill
- pattern-reviewer-frontend-standardSkill
- pattern-reviewer-goSkill
- pattern-reviewer-javaSkill
- pattern-reviewer-kotlinSkill
- pattern-reviewer-nodeSkill
- pattern-reviewer-non-functionalSkill
- pattern-reviewer-observabilitySkill
- pattern-reviewer-pythonSkill
- pattern-reviewer-rustSkill
- pattern-reviewer-securitySkill
- pattern-reviewer-ssrSkill
- pattern-reviewer-swiftSkill
- pattern-reviewer-test-coverageSkill
- pattern-reviewer-typescriptSkill
- pattern-reviewer-viteSkill
- pattern-test-coverageSkill
- principle-engineer-tddSkill
- scaffold-projectSkill
- workflow-architect-interviewSkill
- workflow-designer-sample-pagesSkill
- workflow-design-interviewSkill
- workflow-e2e-authorSkill
- The first 60 shown.
The file
We split this skill into the rules it gives an agent
10 rules. About 0 are common, 4 are distinctive, and 6 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈4
Distinctive · estimate
This author's own choices. Worth a look.
6
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 13
Do NOT activate for purely cosmetic changes (formatting, renaming an internal-only variable, comment edits) or conceptual questions that …
- Very specific: line 17
After loading this skill, also check $MAIN_ROOT/.claude/memory/patterns/pattern-engineer-security.md in the consuming project (resolve …
- Distinctive: line 26
Authorize before acting: Every handler that mutates state checks identity AND ownership/role server-side — authentication answers "who is …
- Very specific: line 27
Encode output / sanitize HTML: before render. React escapes by default.
- Very specific: line 32
Lock dependencies: Commit package-lock.json / uv.lock / poetry.lock.
- Very specific: line 37
CORS origin is an explicit env-driven list: Never * in production; especially never * with credentials: true.
- Distinctive: line 45
Commit secrets — API keys, tokens, passwords, signing keys, connection strings.
- Very specific: line 50
Use eval() / innerHTML / dangerouslySetInnerHTML / v-html with raw user input.
- Distinctive: line 59
Use SHA-256 / MD5 for password hashing (those are checksums, not password hashes).
- Very specific: line 82
Every rule above is binding regardless of project stage — "internal tool", "prototype", and "we'll add it later" do not waive a row.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
pattern-engineer-security
Security guardrails for production-code authoring. This skill is a quiet reference catalogue — the agent reads it to know which patterns to follow, not a checklist to walk through with the user. Reviewer feedback is the user-facing channel for security findings; this skill exists so most findings never happen.
When to activate
- Writing or editing any production code that touches secrets, user input, queries, auth / sessions, output rendering, CSRF, rate limits, logging, errors, dependencies, outbound HTTP, webhooks, CORS, file uploads, or balance / quota / token mutations.
- Do NOT activate for purely cosmetic changes (formatting, renaming an internal-only variable, comment edits) or conceptual questions that don't touch code.
Project memory overlay
After loading this skill, also check $MAIN_ROOT/.claude/memory/patterns/pattern-engineer-security.md in the consuming project (resolve MAIN_ROOT="$(dirname "$(git rev-parse --path-format=absolute --git-common-dir)")"). If present, load it as an additive overlay to the rules below; if absent, skip silently. See memory-convention for the full contract (additivity, severity floor, conflict surfacing).
Always do (no exceptions)
- Validate every external input with a schema at the boundary (Zod / Pydantic). Bound string lengths, numeric ranges, enum values. Trust internal callers; never trust the network.
- Parameterize every database query — ORM or bound parameters. Never concatenate / f-string user input into SQL, shell commands, file paths, or
eval. Dynamic table / column names come from a hardcoded whitelist. - Hash passwords with argon2id (preferred) / bcrypt(≥12) / scrypt. Never store plaintext. Use the library's constant-time verify — never
==orbcrypt.comparewithoutawait. - Run constant-time on auth enumeration paths. Login / forgot-password verify against a sentinel hash when the account doesn't exist so timing leaks
existsvsdoesn't exist. Pin the floor with a regression test. - Set session cookies
HttpOnly; Secure; SameSite=Strict(orLaxif cross-site nav is required). TheSecure/SameSiteattributes come from an env knob (SECURE_COOKIES, defaulttrue) read at the call site — not from a fully-populatedSettings()that test fixtures can't satisfy. Store auth tokens in cookies, neverlocalStorage. - Authorize before acting. Every handler that mutates state checks identity AND ownership/role server-side — authentication answers "who is this?", authorization answers "are they allowed to do this to this resource?" (skipping the second produces IDOR). Multi-tenant tables get RLS where the DB supports it.
- Encode output / sanitize HTML before render. React escapes by default; reach for
dangerouslySetInnerHTMLonly after a sanitizer (DOMPurify / bleach) with an allowlist of tags + attributes. - Set the full security-header set at the edge: CSP (
default-src 'self',frame-ancestors 'none'), HSTS (max-age=31536000; includeSubDomains), X-Frame-Options DENY, X-Content-Type-Options nosniff, Referrer-Policystrict-origin-when-cross-origin, Permissions-Policy disabling unused capabilities. - CSRF token on every cookie-authed state-changing request. Pair with
SameSitecookies as defense-in-depth. - Rate-limit every public endpoint — per-IP at minimum, per-user on authenticated routes. Stricter limits on auth-adjacent routes (login, signup, forgot-password, token-refresh). Rate-limit responses use 429 +
Retry-After. - Read secrets from env vars (or a typed Settings that does).
.env*,*.pem,*.keyin.gitignore; only.env.example(placeholder values) committed. If a secret leaked, rotate it — purging git history is not enough. - Lock dependencies. Commit
package-lock.json/uv.lock/poetry.lock; CI usesnpm ci/uv sync --locked/poetry install --no-update. - Atomic mutations for balance / quota / token redemption.
UPDATE … SET balance = balance - :a WHERE … AND balance >= :a(check rowcount), orSELECT … FOR UPDATEinside a transaction. Token redemption (reset, MFA, OTP, magic-link) marks-then-checks atomically so second attempt returns rowcount=0. - Validate JWTs when used. Signature + algorithm (reject
alg: none) +exp+iss+audwhere relevant. - Sessions can be revoked. Server-side session store, or short-lived JWT + refresh-token rotation with a revocation list — never a long-lived bearer JWT with no revocation path.
- Reset tokens are time-limited (≤1 hour) and single-use. Password-reset completion does NOT issue a session and does NOT auto-navigate to authed routes — the server returns 204 and the SPA navigates to
/login. - CORS origin is an explicit env-driven list. Never
*in production; especially never*withcredentials: true.methodsandallowedHeadersare explicit, not*. - SSRF guard on user-controlled outbound URLs. Host allowlist + scheme allowlist (
https:) + block private/link-local/loopback ranges (resolve the hostname; don't trust the literal) +redirect: "manual"+ timeouts. - Verify webhook signatures (HMAC) before parsing the body. Constant-time compare (
timingSafeEqual/hmac.compare_digest). Replay protection by event-ID dedupe or timestamp window. - OAuth public clients use PKCE; every OAuth callback validates
state. Third-party CDN<script>tags carry SRI hashes (integrity="sha384-..."+crossorigin="anonymous"). - Container images scanned before they ship. Trivy / Docker Scout / Grype against the slug-tagged image; CRITICAL/HIGH count must be 0; MEDIUM/LOW counts reported.
Never do
- Commit secrets — API keys, tokens, passwords, signing keys, connection strings.
- Log passwords, tokens, full PANs, CVVs, full SSNs, session IDs, raw user-supplied emails on failure paths. Log identifiers (user_id, request_id), not secrets.
- Log the same sensitive value at two layers — pick one (usually the outermost where the value is still in scope) and log there only.
- Trust client-side validation as a security boundary.
- Disable security headers, CSRF, rate limits, or CSP rules to make a feature work — if they're in the way, satisfy them.
- Use
eval()/innerHTML/dangerouslySetInnerHTML/v-htmlwith raw user input. - Store sessions in
localStorage,sessionStorage, or any JS-accessible storage. - Expose stack traces, internal exception messages, schema names, or table names in 5xx (or 4xx) responses — generic message + correlation ID.
- Auto-login on password-reset completion. Consume the token, update the hash, return 204; the SPA navigates to
/login. - Wildcard CORS with credentials.
origin: '*'+credentials: trueis an exfiltration channel. fetch(userProvidedUrl)server-side without a host allowlist + private-IP-range block.- Compare HMAC / MAC / signatures with
==. Use a constant-time compare. - Concatenate / interpolate user input into SQL, shell commands, file paths, or
eval. - Pre-create extensions / fixtures in shared session-scope test setup that the migration is supposed to install — the migration must own its own lifecycle.
- Use SHA-256 / MD5 for password hashing (those are checksums, not password hashes).
- Reveal in error bodies or timing whether a user / email exists — for auth flows, prefer "if an account exists, we sent an email".
Quick lookup — patterns by surface
| Surface being touched | Patterns to follow |
| New POST/PUT/PATCH/DELETE endpoint | input schema at the boundary • authorize-before-act + ownership check • CSRF if cookie-auth • rate limit • redacted error path • request-id on all responses |
| New DB query | parameterized • LIMIT on user-facing reads • FOR UPDATE / atomic UPDATE on balance / quota / counter writes • whitelist for dynamic identifiers |
| Auth path (login / reset / OAuth / MFA) | constant-time vs hit/miss via sentinel hash • no auto-login on reset • token expiry + single-use + atomic consumption • OAuth state + PKCE • JWT sig/exp/iss/aud validated • sessions revocable |
| Password / credential storage | argon2id / bcrypt(≥12) / scrypt • library verify, never == • sentinel hash for missing-user branch |
| Rendering user-provided content | sanitize (DOMPurify / bleach) with tag+attr allowlist • CSP allows it without unsafe-inline in script-src • no dangerouslySetInnerHTML / v-html / innerHTML on raw input |
| Edge / response headers | CSP • HSTS • X-Frame-Options DENY • X-Content-Type-Options nosniff • Referrer-Policy • Permissions-Policy |
| Adding a dependency | npm audit / pip-audit clean of HIGH/CRITICAL • lock file committed • CI uses reproducible install • new dep evaluated for maintenance / transitive footprint / advisories |
| Building a container image | trivy scan: CRITICAL/HIGH = 0 • MEDIUM/LOW reported • slug-tagged image, not :latest |
| Touching logs or error responses | no secrets / tokens / PII in logs • structured-log redaction key matches emitted key exactly (case-sensitive) • log a sensitive value at exactly one layer • request-id middleware registered last so it runs first on rejection paths • generic 5xx + correlation id • 4xx hides schema/table/column names |
| Touching API response serializers | sensitive fields (passwordHash, resetToken, mfaSecret, …) stripped at the serializer — unit test fails if a new sensitive field appears without entering the strip list |
| Outbound HTTP from server (SSRF risk) | host allowlist • scheme allowlist (https:) • block private / link-local / loopback ranges (resolve before fetching) • timeouts • redirect: "manual" |
| Webhook receiver | HMAC verified before parsing the body • constant-time compare • dedupe / replay window |
| Cross-origin browser access | CORS origin is an explicit env-driven list (never * with credentials) • methods and allowedHeaders explicit • maxAge reasonable |
| File upload | size + MIME + extension whitelist • magic-byte check on high-trust uploads (avatars, payment attachments) |
| Migrations / DB extensions | migration owns extension lifecycle (CREATE EXTENSION in upgrade, DROP EXTENSION in downgrade) — never pre-warm in conftest.py |
Every rule above is binding regardless of project stage — "internal tool", "prototype", and "we'll add it later" do not waive a row. pattern-reviewer-security audits against this same catalogue; close the gap while authoring rather than in a fix cycle.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

