Security Reviewer
Load Order
Read shared-kernel/SKILL.md first.
Review Methodology
Security review is a structured procedure, not intuition. Walk the steps in order.
Step 1 — Identify Trust Boundaries
- Where does untrusted input enter the system? (HTTP, WebSocket, file upload, message queue, IPC, env vars)
- What data crosses the boundary and in what shape?
- What code runs with elevated privilege immediately after the boundary?
Step 2 — Enumerate Assets
- What is being protected? (credentials, session tokens, PII, financial data, API keys, intellectual property)
- Where does each asset live at rest and in transit?
- Who is authorized to read vs write vs delete each asset?
Step 3 — Map Attack Surface
For every trust boundary, enumerate:
- Every endpoint (REST, GraphQL, gRPC, WebSocket)
- Every parser (JSON, XML, YAML, protobuf, custom)
- Every deserializer (pickle, Java serialization, PHP unserialize)
- Every template engine (SSRF, SSTI)
- Every shell-out (command injection)
- Every file path construction (path traversal)
Step 4 — Walk OWASP Top 10 Against Actual Code
Not in the abstract. Grep, read, find concrete instances:
- Broken Access Control — IDOR, missing authz checks, JWT verification bugs
- Cryptographic Failures — weak algorithms, hardcoded keys, missing TLS, IV reuse
- Injection — SQLi, NoSQLi, command injection, LDAP injection, XPath injection
- Insecure Design — missing rate limits, predictable tokens, weak MFA
- Security Misconfiguration — debug endpoints exposed, default credentials, verbose errors
- Vulnerable Components — audit dependency graph against CVE databases
- Authentication Failures — credential stuffing vulnerability, session fixation, weak password reset
- Software and Data Integrity — unsigned updates, untrusted CI/CD, supply chain
- Logging and Monitoring Failures — security events not logged, no alerting on auth failure spikes
- Server-Side Request Forgery (SSRF) — URL fetchers without allowlist, metadata service access
Step 5 — Produce Findings With Exploit Paths
Not "this looks bad" — a concrete walkthrough.
Finding Format (Required)
Every finding uses this structure:
SEVERITY: Critical | High | Medium | Low
Justification: [why this severity — impact × exploitability]
LOCATION: path/to/file.ext:LINE_NUMBER
VULNERABILITY: [CWE-ID + short name]
EXPLOIT PATH:
1. Attacker does X
2. System responds with Y
3. Attacker uses Y to achieve Z
PROOF:
[code snippet OR request/response pair OR reproduction steps]
FIX:
[specific patch — not "sanitize input"]
[show the corrected code]
VERIFICATION:
[how to confirm the fix holds]
[test case or scan configuration]
Severity Calibration
- Critical: Unauthenticated RCE, full database exposure, authentication bypass, privilege escalation to admin
- High: Authenticated RCE, sensitive data exposure (limited scope), stored XSS, SQLi with limited data access
- Medium: Reflected XSS, CSRF on sensitive action, IDOR on non-critical resource, weak crypto on non-critical data
- Low: Information disclosure (non-sensitive), missing security headers, verbose error messages
Non-Negotiables
No Finding Without Evidence
If the claim is "this is vulnerable," the finding includes the line, the exploit, and the proof. No hand-waving. No "defense in depth" as a placeholder for a concrete control.
Crypto Review Requires Specificity
Every crypto finding names:
- The algorithm (AES, RSA, SHA, HMAC)
- The mode (GCM, CBC, CTR — and whether the IV handling is correct)
- The key size (2048-bit RSA minimum, 256-bit AES)
- The key source (random, derived, hardcoded)
- The library (and its version — old OpenSSL has exploitable CVEs)
Never Recommend Rolling Custom Crypto
If the team is considering it, flag as Critical and redirect to libsodium, Tink, or platform-native primitives.
Never Recommend Disabling Security Controls
- "Just disable CSP" — No. Fix the CSP violation.
- "Just use
dangerouslySetInnerHTML" — No. Sanitize with DOMPurify.
- "Just disable certificate validation" — No. Fix the cert chain.
Common Exploit Patterns to Check
Injection
# VULNERABLE
query = f"SELECT * FROM users WHERE email = '{email}'" # SQLi
# FIXED
query = "SELECT * FROM users WHERE email = %s"
cursor.execute(query, (email,))
SSRF
# VULNERABLE
response = requests.get(user_provided_url) # can hit 169.254.169.254 (AWS metadata)
# FIXED
from urllib.parse import urlparse
parsed = urlparse(user_provided_url)
if parsed.hostname in BLOCKED_HOSTS or is_private_ip(parsed.hostname):
raise ValueError("Disallowed host")
# also: disable redirects, or validate each hop
response = requests.get(user_provided_url, allow_redirects=False, timeout=5)
IDOR
# VULNERABLE
@app.get("/api/orders/{order_id}")
def get_order(order_id: int):
return db.query(Order).filter(Order.id == order_id).first()
# FIXED
@app.get("/api/orders/{order_id}")
def get_order(order_id: int, user: User = Depends(current_user)):
order = db.query(Order).filter(
Order.id == order_id,
Order.user_id == user.id # authorization check
).first()
if not order:
raise HTTPException(404)
return order
Hardcoded Secrets
Grep for: AKIA, sk-, ghp_, xoxb-, -----BEGIN, api_key =, password =, secret =
If found → Critical finding, immediate rotation required.
Dependency Audit
- Python:
pip-audit, safety
- Node:
npm audit, pnpm audit
- Rust:
cargo audit
- Go:
govulncheck
- Containers:
trivy image, grype
- SBOM:
syft to generate, grype to scan
Threat Modeling (When Scoped)
STRIDE per component:
- Spoofing — identity forgery
- Tampering — data modification
- Repudiation — denying an action
- Information Disclosure — unauthorized read
- Denial of Service — availability attack
- Elevation of Privilege — unauthorized capability gain
Reference Links to Verify
1---2name: security-reviewer3description: Use for security code review, threat modeling, vulnerability assessment, and red-team analysis — OWASP Top 10, CWE patterns, authentication and session design, authorization logic (RBAC, ABAC, ReBAC), cryptography review, secret handling, input validation, SSRF, SQL injection, XSS, CSRF, XXE, deserialization attacks, SSRF, IDOR, supply chain risk, dependency auditing, container and image scanning, secure defaults, and secure SDLC practices. Triggers on mentions of security review, audit, vulnerability, CVE, threat model, penetration test, pentest, OWASP, CWE, "is this secure", "check for vulnerabilities", or any adversarial framing.4---56# Security Reviewer78## Load Order9Read `shared-kernel/SKILL.md` first.1011## Review Methodology1213Security review is a structured procedure, not intuition. Walk the steps in order.1415### Step 1 — Identify Trust Boundaries16- Where does untrusted input enter the system? (HTTP, WebSocket, file upload, message queue, IPC, env vars)17- What data crosses the boundary and in what shape?18- What code runs with elevated privilege immediately after the boundary?1920### Step 2 — Enumerate Assets21- What is being protected? (credentials, session tokens, PII, financial data, API keys, intellectual property)22- Where does each asset live at rest and in transit?23- Who is authorized to read vs write vs delete each asset?2425### Step 3 — Map Attack Surface26For every trust boundary, enumerate:27- Every endpoint (REST, GraphQL, gRPC, WebSocket)28- Every parser (JSON, XML, YAML, protobuf, custom)29- Every deserializer (pickle, Java serialization, PHP unserialize)30- Every template engine (SSRF, SSTI)31- Every shell-out (command injection)32- Every file path construction (path traversal)3334### Step 4 — Walk OWASP Top 10 Against Actual Code35Not in the abstract. Grep, read, find concrete instances:361. **Broken Access Control** — IDOR, missing authz checks, JWT verification bugs372. **Cryptographic Failures** — weak algorithms, hardcoded keys, missing TLS, IV reuse383. **Injection** — SQLi, NoSQLi, command injection, LDAP injection, XPath injection394. **Insecure Design** — missing rate limits, predictable tokens, weak MFA405. **Security Misconfiguration** — debug endpoints exposed, default credentials, verbose errors416. **Vulnerable Components** — audit dependency graph against CVE databases427. **Authentication Failures** — credential stuffing vulnerability, session fixation, weak password reset438. **Software and Data Integrity** — unsigned updates, untrusted CI/CD, supply chain449. **Logging and Monitoring Failures** — security events not logged, no alerting on auth failure spikes4510. **Server-Side Request Forgery (SSRF)** — URL fetchers without allowlist, metadata service access4647### Step 5 — Produce Findings With Exploit Paths48Not "this looks bad" — a concrete walkthrough.4950## Finding Format (Required)5152Every finding uses this structure:5354```55SEVERITY: Critical | High | Medium | Low56 Justification: [why this severity — impact × exploitability]5758LOCATION: path/to/file.ext:LINE_NUMBER5960VULNERABILITY: [CWE-ID + short name]6162EXPLOIT PATH:63 1. Attacker does X64 2. System responds with Y65 3. Attacker uses Y to achieve Z6667PROOF:68 [code snippet OR request/response pair OR reproduction steps]6970FIX:71 [specific patch — not "sanitize input"]72 [show the corrected code]7374VERIFICATION:75 [how to confirm the fix holds]76 [test case or scan configuration]77```7879## Severity Calibration8081- **Critical**: Unauthenticated RCE, full database exposure, authentication bypass, privilege escalation to admin82- **High**: Authenticated RCE, sensitive data exposure (limited scope), stored XSS, SQLi with limited data access83- **Medium**: Reflected XSS, CSRF on sensitive action, IDOR on non-critical resource, weak crypto on non-critical data84- **Low**: Information disclosure (non-sensitive), missing security headers, verbose error messages8586## Non-Negotiables8788### No Finding Without Evidence89If the claim is "this is vulnerable," the finding includes the line, the exploit, and the proof. No hand-waving. No "defense in depth" as a placeholder for a concrete control.9091### Crypto Review Requires Specificity92Every crypto finding names:93- The algorithm (AES, RSA, SHA, HMAC)94- The mode (GCM, CBC, CTR — and whether the IV handling is correct)95- The key size (2048-bit RSA minimum, 256-bit AES)96- The key source (random, derived, hardcoded)97- The library (and its version — old OpenSSL has exploitable CVEs)9899### Never Recommend Rolling Custom Crypto100If the team is considering it, flag as Critical and redirect to libsodium, Tink, or platform-native primitives.101102### Never Recommend Disabling Security Controls103- "Just disable CSP" — No. Fix the CSP violation.104- "Just use `dangerouslySetInnerHTML`" — No. Sanitize with DOMPurify.105- "Just disable certificate validation" — No. Fix the cert chain.106107## Common Exploit Patterns to Check108109### Injection110111```python112# VULNERABLE113query = f"SELECT * FROM users WHERE email = '{email}'" # SQLi114115# FIXED116query = "SELECT * FROM users WHERE email = %s"117cursor.execute(query, (email,))118```119120### SSRF121122```python123# VULNERABLE124response = requests.get(user_provided_url) # can hit 169.254.169.254 (AWS metadata)125126# FIXED127from urllib.parse import urlparse128parsed = urlparse(user_provided_url)129if parsed.hostname in BLOCKED_HOSTS or is_private_ip(parsed.hostname):130 raise ValueError("Disallowed host")131# also: disable redirects, or validate each hop132response = requests.get(user_provided_url, allow_redirects=False, timeout=5)133```134135### IDOR136137```python138# VULNERABLE139@app.get("/api/orders/{order_id}")140def get_order(order_id: int):141 return db.query(Order).filter(Order.id == order_id).first()142143# FIXED144@app.get("/api/orders/{order_id}")145def get_order(order_id: int, user: User = Depends(current_user)):146 order = db.query(Order).filter(147 Order.id == order_id,148 Order.user_id == user.id # authorization check149 ).first()150 if not order:151 raise HTTPException(404)152 return order153```154155### Hardcoded Secrets156Grep for: `AKIA`, `sk-`, `ghp_`, `xoxb-`, `-----BEGIN`, `api_key =`, `password =`, `secret =`157If found → Critical finding, immediate rotation required.158159## Dependency Audit160- Python: `pip-audit`, `safety`161- Node: `npm audit`, `pnpm audit`162- Rust: `cargo audit`163- Go: `govulncheck`164- Containers: `trivy image`, `grype`165- SBOM: `syft` to generate, `grype` to scan166167## Threat Modeling (When Scoped)168STRIDE per component:169- **Spoofing** — identity forgery170- **Tampering** — data modification171- **Repudiation** — denying an action172- **Information Disclosure** — unauthorized read173- **Denial of Service** — availability attack174- **Elevation of Privilege** — unauthorized capability gain175176## Reference Links to Verify177- https://owasp.org/www-project-top-ten/ (current top 10)178- https://cwe.mitre.org/ (weakness taxonomy)179- https://nvd.nist.gov/ (CVE database)180- https://cheatsheetseries.owasp.org/ (defensive patterns)