When to use
- Reviewing a change that touches user input, auth, or data storage
- A feature accepts untrusted data, manages sessions, or integrates with external services
- Adding file uploads, webhooks, callbacks, or payment/PII handling
- Before merge on any security-sensitive change
- Triggers on "security review", "check for vulnerabilities", "安全审查", "安全审计", "漏洞检查"
Not for: general code quality review (use code-review); performance profiling (use performance).
Steps
1. Threat model first
Controls bolted on without a threat model are guesses. Before reviewing hardening, spend five minutes thinking like an attacker:
- Map trust boundaries — HTTP requests, form fields, file uploads, webhooks, third-party APIs, message queues, LLM output. Every boundary is attack surface.
- Name the assets — credentials, PII, payment data, admin actions, money movement.
- Run STRIDE per boundary — Spoofing (auth, signature verification), Tampering (integrity, parameterized queries, HTTPS), Repudiation (audit logging), Information disclosure (encryption, field allowlists, generic errors), Denial of service (rate limiting, size caps, timeouts), Elevation of privilege (authorization checks, least privilege).
- Write abuse cases next to use cases — "how would I misuse this?" is your first test.
If you can't name the trust boundaries for a feature, it's not ready to secure (OWASP A04: Insecure Design — most breaches begin in design, not code).
2. Check the three-tier boundary system
Always do (no exceptions):
- Validate all external input at the system boundary (API routes, form handlers)
- Parameterize all database queries — never concatenate user input into SQL
- Encode output to prevent XSS (use framework auto-escaping, don't bypass it)
- HTTPS for all external communication
- Hash passwords with bcrypt/scrypt/argon2 (salt rounds ≥ 12, never plaintext)
- Security headers: CSP, HSTS, X-Frame-Options, X-Content-Type-Options
- httpOnly, secure, sameSite cookies for sessions
- Run the package manager's native audit against the committed lockfile before every release
Ask first (human approval): new auth flows or auth-logic changes; new sensitive-data categories (PII, payment); new external service integrations; CORS config changes; file upload handlers; rate-limiting/throttling changes; elevated permissions or roles.
Never do: commit secrets to version control; log sensitive data (passwords, tokens, full card numbers); trust client-side validation as a security boundary; disable security headers for convenience; eval() or innerHTML with user-provided data; store sessions in client-accessible storage (localStorage for auth tokens); expose stack traces or internal error details to users.
3. Walk the OWASP Top 10 (2021) prevention patterns
For each, check the diff for the bad pattern and confirm the good one is in place. (2021 IDs.
XSS was folded into A03 Injection in 2021 but is kept as a sub-point here since its prevention —
output encoding — differs from query/shell injection.)
- A01: Broken Access Control — check authorization, not just authentication. Verify resource ownership (
task.ownerId !== req.user.id → 403). Admin actions require admin role verification. Users can only access their own resources.
- A02: Cryptographic Failures (was "Sensitive Data Exposure") — field allowlist in API responses (strip
passwordHash, resetToken); secrets from environment variables; PII encrypted at rest; TLS in transit; bcrypt/scrypt/argon2 for passwords.
- A03: Injection (SQL/NoSQL/OS command, now incl. XSS) — parameterized queries or ORM with parameterized input; no string concatenation of user input into queries or shell commands. For XSS: framework auto-escaping (React escapes by default); sanitize before rendering HTML (DOMPurify); no
innerHTML with user data.
- A04: Insecure Design — the threat model in Step 1 is the control. If you can't name the trust boundaries for a feature, it's not ready to secure. Most breaches begin in design, not code.
- A05: Security Misconfiguration — helmet for headers; CSP with tight directives (
defaultSrc 'self'); CORS restricted to known origins (never wildcard * with credentials). No default credentials.
- A06: Vulnerable and Outdated Components — Step 6 covers this: run the native audit against the lockfile, triage by reachability, block unreviewed install scripts.
- A07: Identification and Authentication Failures (was "Broken Authentication") — bcrypt/scrypt/argon2 hash and compare; session secret from environment (not code); httpOnly + secure + sameSite cookies with explicit maxAge; password reset tokens expire.
- A08: Software and Data Integrity Failures — verify CI/CD pipeline integrity; sign and verify dependencies (provenance); treat untrusted dependencies and plugin update channels as adversarial (Step 6 supply-chain hygiene).
- A09: Security Logging and Monitoring Failures — audit-log security-relevant events (auth, access denials, admin actions) with enough context to investigate; the STRIDE Repudiation check in Step 1 surfaces what must be logged.
- A10: Server-Side Request Forgery (SSRF) — for server-side URL fetches (webhooks, import-from-URL, image proxies, link previews): allowlist scheme + host, reject if any resolved IP is private/reserved (covers loopback, link-local
169.254.169.254 cloud metadata, private, unique-local across IPv4/IPv6), forbid redirects. TOCTOU gap remains — for high-risk surfaces, pin the resolved IP or use a filtering agent (request-filtering-agent).
4. Input validation + file uploads
Schema validation at boundaries (e.g. zod): validate at the route handler, return 422 with VALIDATION_ERROR on failure. File uploads: restrict MIME types and size; don't trust the file extension — check magic bytes if critical.
5. Rate limiting
General API rate limit (e.g. 100 req / 15 min). Stricter limit on auth endpoints (e.g. 10 attempts / 15 min). standardHeaders: true, legacyHeaders: false.
6. Dependency + supply-chain hygiene
Find the installation boundary first: use the workspace root that owns the lockfile; corroborate packageManager (when present), the lockfile, and CI; stop on disagreement or competing lockfiles.
Triage audit findings by reachability and fix risk, not just severity:
- Critical/high + reachable in runtime/build/deploy → fix immediately (update, patch, or replace).
- Critical/high + confirmed unused across all paths → fix soon, not a blocker.
- Moderate + reachable in prod → next release cycle. Dev-only → backlog.
- Low → track and fix during regular dependency updates.
Never npm audit fix --force (or equivalent) — preview the remediation, read changelogs, test each upgrade; forced fixes may cross declared dependency ranges. Verify registry signatures/provenance where supported (npm audit signatures); treat absence as a signal to investigate. Review new dependencies, lockfile diffs, and script-policy changes together — ownership, maintenance, release age, provenance, transitive graph, typosquats (cross-env vs crossenv, OWASP A06, LLM03). Block dependency install scripts unless explicitly approved; bootstrap with scripts disabled.
7. Secrets management
.env.example committed (template with placeholders); .env / .env.local NOT committed and in .gitignore (*.pem, *.key too). Before committing, check staged diff for password|secret|api_key|token. If a secret is ever committed, rotate it — deleting the line or rewriting history is not enough. Revoke and reissue the key first, then purge it from history. Assume it's compromised the moment it reaches a remote.
8. AI / LLM features (if present)
Map to the OWASP Top 10 for LLM Applications:
- LLM05 (Improper Output Handling) — treat all model output as untrusted input. No
eval, SQL, shell, innerHTML, or file path from model output without validation and encoding. Parse defensively, validate against a schema, then encode.
- LLM01 (Prompt Injection) — assume prompts can be hijacked. Untrusted text in the context window can carry instructions. The system prompt is not a security boundary; enforce permissions in code.
- LLM02 / LLM07 — keep secrets and other users' data out of prompts. Anything in the context can be echoed back.
- LLM06 (Excessive Agency) — scope tool/agent permissions to the minimum; require confirmation for destructive or irreversible actions; validate every tool argument.
- LLM10 (Unbounded Consumption) — cap tokens, request rate, and loop/recursion depth.
- LLM08 (Vector and Embedding Weaknesses) — in RAG, partition embeddings per tenant so one user can't retrieve another's data; validate documents before indexing.
Red flags
- User input passed directly to database queries, shell commands, or HTML rendering
- Secrets in source code or commit history
- API endpoints without authentication or authorization checks
- Missing CORS configuration or wildcard (
*) origins with credentials
- No rate limiting on authentication endpoints
- Stack traces or internal errors exposed to users
- Dependencies with known critical vulnerabilities; competing lockfiles at one installation boundary; non-reproducible installs; blanket-approved install scripts
- Server fetches user-supplied URLs without an allowlist (SSRF)
- LLM/model output passed into a query, the DOM, a shell, or
eval
- Secrets, PII, or the full system prompt placed inside an LLM context window
Output: docs/security-report.md — findings by severity, with runtime/build/deploy reachability and the fix or accept rationale per finding.
Verify
References
- ${CLAUDE_PLUGIN_ROOT}/references/engineering-principles.md — discipline every skill shares
- references/owasp-patterns.md — OWASP Top 10 prevention code examples (injection, auth, XSS, access control, SSRF, validation, rate limiting, LLM output).
- references/compliance-process.md — load when PII/payment assets appear in the threat model; GDPR/CCPA process layer: data inventory, DSR fulfillment, retention, right-to-erasure, privacy-by-design, audit readiness
1---2name: security-review3description: Use when reviewing changes for security — secrets, auth, injection, access control, and hardening. Triggers on "security review", "check for vulnerabilities", "安全审查", "安全审计", "漏洞检查".4---56## When to use78- Reviewing a change that touches user input, auth, or data storage9- A feature accepts untrusted data, manages sessions, or integrates with external services10- Adding file uploads, webhooks, callbacks, or payment/PII handling11- Before merge on any security-sensitive change12- Triggers on "security review", "check for vulnerabilities", "安全审查", "安全审计", "漏洞检查"1314**Not for:** general code quality review (use `code-review`); performance profiling (use `performance`).1516## Steps1718### 1. Threat model first1920Controls bolted on without a threat model are guesses. Before reviewing hardening, spend five minutes thinking like an attacker:21221. **Map trust boundaries** — HTTP requests, form fields, file uploads, webhooks, third-party APIs, message queues, **LLM output**. Every boundary is attack surface.232. **Name the assets** — credentials, PII, payment data, admin actions, money movement.243. **Run STRIDE** per boundary — Spoofing (auth, signature verification), Tampering (integrity, parameterized queries, HTTPS), Repudiation (audit logging), Information disclosure (encryption, field allowlists, generic errors), Denial of service (rate limiting, size caps, timeouts), Elevation of privilege (authorization checks, least privilege).254. **Write abuse cases next to use cases** — "how would I misuse this?" is your first test.2627If you can't name the trust boundaries for a feature, it's not ready to secure (OWASP A04: Insecure Design — most breaches begin in design, not code).2829### 2. Check the three-tier boundary system3031**Always do (no exceptions):**32- Validate all external input at the system boundary (API routes, form handlers)33- Parameterize all database queries — never concatenate user input into SQL34- Encode output to prevent XSS (use framework auto-escaping, don't bypass it)35- HTTPS for all external communication36- Hash passwords with bcrypt/scrypt/argon2 (salt rounds ≥ 12, never plaintext)37- Security headers: CSP, HSTS, X-Frame-Options, X-Content-Type-Options38- httpOnly, secure, sameSite cookies for sessions39- Run the package manager's native audit against the committed lockfile before every release4041**Ask first (human approval):** new auth flows or auth-logic changes; new sensitive-data categories (PII, payment); new external service integrations; CORS config changes; file upload handlers; rate-limiting/throttling changes; elevated permissions or roles.4243**Never do:** commit secrets to version control; log sensitive data (passwords, tokens, full card numbers); trust client-side validation as a security boundary; disable security headers for convenience; `eval()` or `innerHTML` with user-provided data; store sessions in client-accessible storage (localStorage for auth tokens); expose stack traces or internal error details to users.4445### 3. Walk the OWASP Top 10 (2021) prevention patterns4647For each, check the diff for the bad pattern and confirm the good one is in place. (2021 IDs.48XSS was folded into A03 Injection in 2021 but is kept as a sub-point here since its prevention —49output encoding — differs from query/shell injection.)5051- **A01: Broken Access Control** — check authorization, not just authentication. Verify resource ownership (`task.ownerId !== req.user.id` → 403). Admin actions require admin role verification. Users can only access their own resources.52- **A02: Cryptographic Failures** (was "Sensitive Data Exposure") — field allowlist in API responses (strip `passwordHash`, `resetToken`); secrets from environment variables; PII encrypted at rest; TLS in transit; bcrypt/scrypt/argon2 for passwords.53- **A03: Injection** (SQL/NoSQL/OS command, now incl. XSS) — parameterized queries or ORM with parameterized input; no string concatenation of user input into queries or shell commands. For XSS: framework auto-escaping (React escapes by default); sanitize before rendering HTML (DOMPurify); no `innerHTML` with user data.54- **A04: Insecure Design** — the threat model in Step 1 is the control. If you can't name the trust boundaries for a feature, it's not ready to secure. Most breaches begin in design, not code.55- **A05: Security Misconfiguration** — helmet for headers; CSP with tight directives (`defaultSrc 'self'`); CORS restricted to known origins (never wildcard `*` with credentials). No default credentials.56- **A06: Vulnerable and Outdated Components** — Step 6 covers this: run the native audit against the lockfile, triage by reachability, block unreviewed install scripts.57- **A07: Identification and Authentication Failures** (was "Broken Authentication") — bcrypt/scrypt/argon2 hash and compare; session secret from environment (not code); httpOnly + secure + sameSite cookies with explicit maxAge; password reset tokens expire.58- **A08: Software and Data Integrity Failures** — verify CI/CD pipeline integrity; sign and verify dependencies (provenance); treat untrusted dependencies and plugin update channels as adversarial (Step 6 supply-chain hygiene).59- **A09: Security Logging and Monitoring Failures** — audit-log security-relevant events (auth, access denials, admin actions) with enough context to investigate; the STRIDE Repudiation check in Step 1 surfaces what must be logged.60- **A10: Server-Side Request Forgery (SSRF)** — for server-side URL fetches (webhooks, import-from-URL, image proxies, link previews): allowlist scheme + host, reject if any resolved IP is private/reserved (covers loopback, link-local `169.254.169.254` cloud metadata, private, unique-local across IPv4/IPv6), forbid redirects. TOCTOU gap remains — for high-risk surfaces, pin the resolved IP or use a filtering agent (`request-filtering-agent`).6162### 4. Input validation + file uploads6364Schema validation at boundaries (e.g. zod): validate at the route handler, return 422 with `VALIDATION_ERROR` on failure. File uploads: restrict MIME types and size; don't trust the file extension — check magic bytes if critical.6566### 5. Rate limiting6768General API rate limit (e.g. 100 req / 15 min). Stricter limit on auth endpoints (e.g. 10 attempts / 15 min). `standardHeaders: true`, `legacyHeaders: false`.6970### 6. Dependency + supply-chain hygiene7172Find the installation boundary first: use the workspace root that owns the lockfile; corroborate `packageManager` (when present), the lockfile, and CI; stop on disagreement or competing lockfiles.7374Triage audit findings by **reachability** and **fix risk**, not just severity:7576- Critical/high + reachable in runtime/build/deploy → fix immediately (update, patch, or replace).77- Critical/high + confirmed unused across all paths → fix soon, not a blocker.78- Moderate + reachable in prod → next release cycle. Dev-only → backlog.79- Low → track and fix during regular dependency updates.8081Never `npm audit fix --force` (or equivalent) — preview the remediation, read changelogs, test each upgrade; forced fixes may cross declared dependency ranges. Verify registry signatures/provenance where supported (`npm audit signatures`); treat absence as a signal to investigate. Review new dependencies, lockfile diffs, and script-policy changes together — ownership, maintenance, release age, provenance, transitive graph, typosquats (`cross-env` vs `crossenv`, OWASP A06, LLM03). Block dependency install scripts unless explicitly approved; bootstrap with scripts disabled.8283### 7. Secrets management8485`.env.example` committed (template with placeholders); `.env` / `.env.local` NOT committed and in `.gitignore` (`*.pem`, `*.key` too). Before committing, check staged diff for `password|secret|api_key|token`. **If a secret is ever committed, rotate it** — deleting the line or rewriting history is not enough. Revoke and reissue the key first, then purge it from history. Assume it's compromised the moment it reaches a remote.8687### 8. AI / LLM features (if present)8889Map to the OWASP Top 10 for LLM Applications:9091- **LLM05** (Improper Output Handling) — treat all model output as untrusted input. No `eval`, SQL, shell, `innerHTML`, or file path from model output without validation and encoding. Parse defensively, validate against a schema, then encode.92- **LLM01** (Prompt Injection) — assume prompts can be hijacked. Untrusted text in the context window can carry instructions. The system prompt is not a security boundary; enforce permissions in code.93- **LLM02 / LLM07** — keep secrets and other users' data out of prompts. Anything in the context can be echoed back.94- **LLM06** (Excessive Agency) — scope tool/agent permissions to the minimum; require confirmation for destructive or irreversible actions; validate every tool argument.95- **LLM10** (Unbounded Consumption) — cap tokens, request rate, and loop/recursion depth.96- **LLM08** (Vector and Embedding Weaknesses) — in RAG, partition embeddings per tenant so one user can't retrieve another's data; validate documents before indexing.9798## Red flags99100- User input passed directly to database queries, shell commands, or HTML rendering101- Secrets in source code or commit history102- API endpoints without authentication or authorization checks103- Missing CORS configuration or wildcard (`*`) origins with credentials104- No rate limiting on authentication endpoints105- Stack traces or internal errors exposed to users106- Dependencies with known critical vulnerabilities; competing lockfiles at one installation boundary; non-reproducible installs; blanket-approved install scripts107- Server fetches user-supplied URLs without an allowlist (SSRF)108- LLM/model output passed into a query, the DOM, a shell, or `eval`109- Secrets, PII, or the full system prompt placed inside an LLM context window110111**Output:** `docs/security-report.md` — findings by severity, with runtime/build/deploy reachability and the fix or accept rationale per finding.112113## Verify114115- [ ] Native audit has no unmitigated reachable critical/high findings; CI preserves the authoritative lockfile and blocks unreviewed dependency scripts116- [ ] No secrets in source code or git history117- [ ] All user input validated at system boundaries118- [ ] Authentication and authorization checked on every protected endpoint119- [ ] Security headers present in response (CSP, HSTS, X-Frame-Options, X-Content-Type-Options)120- [ ] Error responses don't expose internal details / stack traces121- [ ] Rate limiting active on auth endpoints122- [ ] Server-side URL fetches validated against an allowlist (no SSRF)123- [ ] LLM/model output validated and encoded before use (if AI features present)124125## References126127- [${CLAUDE_PLUGIN_ROOT}/references/engineering-principles.md](${CLAUDE_PLUGIN_ROOT}/references/engineering-principles.md) — discipline every skill shares128- [references/owasp-patterns.md](references/owasp-patterns.md) — OWASP Top 10 prevention code examples (injection, auth, XSS, access control, SSRF, validation, rate limiting, LLM output).129- [references/compliance-process.md](references/compliance-process.md) — load when PII/payment assets appear in the threat model; GDPR/CCPA process layer: data inventory, DSR fulfillment, retention, right-to-erasure, privacy-by-design, audit readiness