| name | ds-security-review |
| description | Run a strict security review of code changes — find exploitable weaknesses. Language-agnostic. Reports a findings list by default; `--fix` applies the mechanical, unambiguous fixes (logic-changing or uncertain ones stay reported). |
| disable-model-invocation | true |
When invoked, audit the code in scope against one question: how would an attacker abuse this? Look for the weaknesses that lead to real compromise — injection, broken access control, leaked secrets, untrusted input trusted too far. This is the portable, cross-language pass; for deeper language specifics, /ds-go-review, /ds-ts-review, and /ds-rust-review carry their own Security sections. Every finding names the attack that exploits it. Report-only by default — no edits unless --fix is passed.
Arguments
- Treat positional args as scope (files, directories, globs). With no scope, review the code changed on the current branch.
--full → review the entire codebase instead of just the branch's changes. Explicit positional scope still wins; --full only replaces the no-scope default.
- Freeform scope ("the auth handler", "the upload path") is interpreted reasonably.
--fix → after reporting, apply only the findings whose fix is mechanical and unambiguous — a single obvious edit, no design judgment (e.g. removing a secret committed to source, tightening over-permissive file modes). A wrong fix to a security finding is worse than none, so anything that changes behavior or rests on an assumption you couldn't verify stays report-only. After applying, re-run any build/test/lint check already in the loop and revert any fix that breaks it — or that touched more than the intended mechanical edit. Close with a summary of what was applied and what was left.
ast-grep structural pass (when available — experimental)
When ast-grep is installed (command -v ast-grep), read the companion ast-grep.md (same directory as this file) and run a structural pass. It's an additive aid: it mechanically enumerates known-dangerous patterns — injection sinks, risky-API call sites, untrusted-type flows — that a skim of a large diff can miss, turning each match into one more branch to trace in full context. It never narrows what you read, and a match is a lead, not a verdict. If ast-grep isn't installed, review normally — the full read is the baseline.
What to check
Trace untrusted data from where it enters to where it's used. Most vulnerabilities are an input that reaches a dangerous sink without validation in between.
1. Injection. Untrusted input reaching an interpreter — SQL/NoSQL, OS commands, file paths (traversal), URLs (SSRF), templates, eval-like calls, LDAP. Look for string-built queries or commands instead of parameterized/escaped APIs.
2. Output handling. Untrusted data rendered without context-correct encoding (XSS), unsafe deserialization of attacker-controlled data, content-type confusion.
3. Access control. Missing or wrong authorization on an action; object-level checks absent (IDOR — can user A reach user B's record?); privilege escalation; trusting a client-supplied role or id; an auth check bypassable by ordering or a missing branch.
4. Secrets & crypto. Hardcoded credentials, keys, or tokens; secrets in logs, errors, or responses; rolled-own or weak crypto; predictable randomness used for security (tokens, IDs, salts); missing encryption for sensitive data in transit or at rest.
5. Sensitive-data exposure. PII or secrets in logs, stack traces, or verbose errors returned to the caller; over-broad API responses; debug endpoints or stack traces reachable in production paths.
6. Untrusted input trusted too far. Mass assignment / binding attacker-controlled fields; unvalidated redirects; unsafe file upload (type, size, path); unbounded input enabling resource exhaustion (DoS) — allocation, recursion, regex backtracking.
7. Configuration & transport. Missing TLS or certificate validation, permissive CORS, missing security headers, default credentials, overly broad permissions or IAM.
8. Dependencies. Known-vulnerable or untrusted dependencies introduced by the change. (The language reviews run the deeper audit tooling — flag the obvious here.)
Output
A prioritized findings list, ordered by exploitability × impact:
- Critical — directly exploitable for code execution, data breach, or auth bypass
- High — exploitable under realistic conditions, or a clear data-exposure path
- Hardening — defense-in-depth gap, not directly exploitable on its own
For each finding:
- Anchor to
file:line.
- State the weakness in one line, describe the attack that exploits it (the input and the sink), then the fix — prefer the standard safe API over hand-rolled escaping.
- Note your confidence and any assumption about what's trusted.
Rules:
- Exploitable findings over theoretical ones. Name a path from attacker-controlled input to impact; a "weakness" on a fully-trusted internal path is hardening at most.
- A short, high-confidence list beats a long speculative one.
- With
--fix, additionally summarize what was applied vs. left (mechanics in Arguments).