Imported from kaiohenricunha/dotbabel (
skills/security-review/SKILL.md). Install upstream withnpx skills add kaiohenricunha/dotbabel --skill security-review. Copyright stays with the author.
Analyze a diff or set of changed files for common security vulnerabilities.
Arguments: $ARGUMENTS (optional: a PR number, file path, or staged for staged changes. Default: staged changes.)
Stack detection
Detect what's in the repo before applying checks (run once at the start):
HAS_NODE=$([ -f package.json ] && echo 1)
HAS_GO=$([ -f go.mod ] && echo 1)
HAS_PY=$([ -f pyproject.toml ] || [ -f requirements.txt ] && echo 1)
HAS_RUST=$([ -f Cargo.toml ] && echo 1)
HAS_DOCKER=$([ -f Dockerfile ] || [ -f compose.yml ] || [ -f docker-compose.yml ] && echo 1)
HAS_K8S=$(ls k8s/*.yaml charts/ 2>/dev/null | head -1)
Apply only the relevant checklists below.
What this checks
OWASP Top 10 adapted per detected stack. Each category lists the globs to target and the class of issue to flag.
Frontend (if HAS_NODE and source looks like a web app)
Common frontend globs: src/**/*.{js,jsx,ts,tsx,vue,svelte}, app/**/*.{js,jsx,ts,tsx}, pages/**/*.{js,jsx,ts,tsx}, components/**/*.
- XSS: React's raw-HTML injection prop (
dangerously*), Vue'sv-html, Svelte's{@html ...}, unescaped URL params rendered into the DOM, template-literal injection into DOM sinks. - Open redirect: Unvalidated
window.location/router.pushassignments from user input or URL params. - Sensitive data in client: API keys, tokens, or secrets hardcoded in source files. Anything prefixed
NEXT_PUBLIC_,VITE_,REACT_APP_holding a secret-shaped value is a leak. - localStorage / sessionStorage abuse: Storing auth tokens or sensitive data without namespacing; reading without validation.
- Dependency risk: New npm dependencies added. Run
npm audit(orpnpm audit/yarn audit) and flag known CVEs at moderate+ severity. - CSP / headers: Regressions in
Content-Security-Policy,X-Frame-Options,Referrer-Policy,Permissions-Policy.
Backend (Go, if HAS_GO)
Globs: **/*.go (excluding **/*_test.go unless the test introduces real endpoints).
- SQL injection: String concatenation in queries instead of parameterized statements (
$1,$2, or driver-specific placeholders). - Auth bypass: New routes without the project's auth middleware; protected endpoints that don't call a
RequireAuth/RequireAdminwrapper. - CORS misconfiguration: Wildcard
*origins combined withcredentials: true; reflectedOriginheader without allowlist. - Secret exposure: Hardcoded secrets, API keys, database URLs in Go source or config files.
- Path traversal: User-controlled file paths without
filepath.Clean+ containment checks. - SSRF:
http.Get/http.NewRequeston URLs derived from user input without an allowlist. - Deserialization:
json.Unmarshalintointerface{}combined with type assertions on unvalidated input.
Backend (Node/TS, if HAS_NODE and there's server code)
Globs: api/**/*.{ts,js}, server/**/*.{ts,js}, app/api/**/*.{ts,js} (Next.js route handlers), middleware.{ts,js}.
- NoSQL/SQL injection via unparameterized queries.
- Prototype pollution: unsafe
Object.assign/ spread into user-provided JSON. - Auth bypass, CORS, secret exposure, path traversal, SSRF: same as Go section above.
- Weak crypto:
crypto.createHash('md5')orsha1for anything security-relevant.
Backend (Python, if HAS_PY)
Globs: **/*.py (excluding tests).
- SQL injection: f-string / %-format SQL instead of parameterized cursors.
- Shell injection:
subprocess.*(shell=True)with user-controlled args;os.system. - Unsafe deserialization: Python's binary object-serialization module (flag imports and
loadscalls against untrusted input — prefer JSON); YAML withoutSafeLoader. - Auth, CORS, secrets, path traversal, SSRF: same mental model as above.
Data / config files
Globs: any tracked data file (data/**, content/**, project-specific generated files), plus .env*, config/**, infra/**.
- Credential leakage: Database URLs, API keys, tokens accidentally committed.
- SQL injection via migration: Dynamic SQL or unsanitized interpolation in migration files (
migrations/**.sql,db/migrate/**).
Docker / Kubernetes (if detected)
- Privileged containers:
privileged: true,allowPrivilegeEscalation: true. - Hostpath mounts that expose the host filesystem.
- Secrets in env blocks: plaintext values in
env:whereenvFrom: secretRefis the right pattern. latestimage tags in production manifests.
Steps
-
Determine the diff to review:
- If a PR number was given:
gh pr diff <number> - If a file path was given:
git diff HEAD -- <path> - If
stagedor no argument:git diff --cached(fall back togit diffif nothing staged)
- If a PR number was given:
-
For each changed file, map to the applicable checklists above based on path and file extension.
-
Classify each finding:
- CRITICAL: Exploitable vulnerability (XSS, SQL/NoSQL injection, auth bypass, credential exposure, SSRF with internal network reachable).
- WARNING: Potential issue needing review (new dependency with unclear provenance, broad CORS, missing input validation, weak crypto).
- INFO: Best practice suggestion (namespace localStorage keys, add rate limiting, tighten CSP, prefer typed query helpers).
-
Report as a table:
| Severity | File | Line | Finding | Recommendation |
|---|
- If no issues found, report "Security review: clean."
Do NOT auto-fix. Report findings for the user or the calling workflow to act on.