Security Review Skill
Identify exploitable security vulnerabilities in code. Report only HIGH CONFIDENCE findings—clear vulnerable patterns with attacker-controlled input.
Scope: Research vs. Reporting
CRITICAL DISTINCTION:
- Report on: Only the specific file, diff, or code provided by the user
- Research: The ENTIRE codebase to build confidence before reporting
Before flagging any issue, you MUST research the codebase to understand:
- Where does this input actually come from? (Trace data flow)
- Is there validation/sanitization elsewhere?
- How is this configured? (Check settings, config files, middleware)
- What framework protections exist?
Do NOT report issues based solely on pattern matching. Investigate first, then report only what you're confident is exploitable.
Confidence Levels
| Level |
Criteria |
Action |
| HIGH |
Vulnerable pattern + attacker-controlled input confirmed |
Report with severity |
| MEDIUM |
Vulnerable pattern, input source unclear |
Note as "Needs verification" |
| LOW |
Theoretical, best practice, defense-in-depth |
Do not report |
Do Not Flag
General Rules
- Test files (unless explicitly reviewing test security)
- Dead code, commented code, documentation strings
- Patterns using constants or server-controlled configuration
- Code paths that require prior authentication to reach (note the auth requirement instead)
Server-Controlled Values (NOT Attacker-Controlled)
These are configured by operators, not controlled by attackers:
| Source |
Example |
Why It's Safe |
| Django settings |
settings.API_URL, settings.ALLOWED_HOSTS |
Set via config/env at deployment |
| Environment variables |
os.environ.get('DATABASE_URL') |
Deployment configuration |
| Config files |
config.yaml, app.config['KEY'] |
Server-side files |
| Framework constants |
django.conf.settings.* |
Not user-modifiable |
| Hardcoded values |
BASE_URL = "https://api.internal" |
Compile-time constants |
SSRF Example - NOT a vulnerability:
# SAFE: URL comes from Django settings (server-controlled)
response = requests.get(f"{settings.SEER_AUTOFIX_URL}{path}")
SSRF Example - IS a vulnerability:
# VULNERABLE: URL comes from request (attacker-controlled)
response = requests.get(request.GET.get('url'))
Framework-Mitigated Patterns
Check language guides before flagging. Common false positives:
| Pattern |
Why It's Usually Safe |
Django {{ variable }} |
Auto-escaped by default |
React {variable} |
Auto-escaped by default |
Vue {{ variable }} |
Auto-escaped by default |
User.objects.filter(id=input) |
ORM parameterizes queries |
cursor.execute("...%s", (input,)) |
Parameterized query |
innerHTML = "<b>Loading...</b>" |
Constant string, no user input |
Only flag these when:
- Django:
{{ var|safe }}, {% autoescape off %}, mark_safe(user_input)
- React:
dangerouslySetInnerHTML={{__html: userInput}}
- Vue:
v-html="userInput"
- ORM:
.raw(), .extra(), RawSQL() with string interpolation
Review Process
1. Detect Context
What type of code am I reviewing?
| Code Type |
Load These References |
| API endpoints, routes |
authorization.md, authentication.md, injection.md |
| Frontend, templates |
xss.md, csrf.md |
| File handling, uploads |
file-security.md |
| Crypto, secrets, tokens |
cryptography.md, data-protection.md |
| Data serialization |
deserialization.md |
| External requests |
ssrf.md |
| Business workflows |
business-logic.md |
| GraphQL, REST design |
api-security.md |
| Config, headers, CORS |
misconfiguration.md |
| CI/CD, dependencies |
supply-chain.md |
| Error handling |
error-handling.md |
| Audit, logging |
logging.md |
2. Load Language Guide
Based on file extension or imports:
| Indicators |
Guide |
.py, django, flask, fastapi |
languages/python.md |
.js, .ts, express, react, vue, next |
languages/javascript.md |
.go, go.mod |
languages/go.md |
.rs, Cargo.toml |
languages/rust.md |
.java, spring, @Controller |
languages/java.md |
3. Load Infrastructure Guide (if applicable)
| File Type |
Guide |
Dockerfile, .dockerignore |
infrastructure/docker.md |
| K8s manifests, Helm charts |
infrastructure/kubernetes.md |
.tf, Terraform |
infrastructure/terraform.md |
GitHub Actions, .gitlab-ci.yml |
infrastructure/ci-cd.md |
| AWS/GCP/Azure configs, IAM |
infrastructure/cloud.md |
4. Research Before Flagging
For each potential issue, research the codebase to build confidence:
- Where does this value actually come from? Trace the data flow.
- Is it configured at deployment (settings, env vars) or from user input?
- Is there validation, sanitization, or allowlisting elsewhere?
- What framework protections apply?
Only report issues where you have HIGH confidence after understanding the broader context.
5. Verify Exploitability
For each potential finding, confirm:
Is the input attacker-controlled?
| Attacker-Controlled (Investigate) |
Server-Controlled (Usually Safe) |
request.GET, request.POST, request.args |
settings.X, app.config['X'] |
request.json, request.data, request.body |
os.environ.get('X') |
request.headers (most headers) |
Hardcoded constants |
request.cookies (unsigned) |
Internal service URLs from config |
URL path segments: /users/<id>/ |
Database content from admin/system |
| File uploads (content and names) |
Signed session data |
| Database content from other users |
Framework settings |
| WebSocket messages |
|
Does the framework mitigate this?
- Check language guide for auto-escaping, parameterization
- Check for middleware/decorators that sanitize
Is there validation upstream?
- Input validation before this code
- Sanitization libraries (DOMPurify, bleach, etc.)
6. Report HIGH Confidence Only
Skip theoretical issues. Report only what you've confirmed is exploitable after research.
Severity Classification
| Severity |
Impact |
Examples |
| Critical |
Direct exploit, severe impact, no auth required |
RCE, SQL injection to data, auth bypass, hardcoded secrets |
| High |
Exploitable with conditions, significant impact |
Stored XSS, SSRF to metadata, IDOR to sensitive data |
| Medium |
Specific conditions required, moderate impact |
Reflected XSS, CSRF on state-changing actions, path traversal |
| Low |
Defense-in-depth, minimal direct impact |
Missing headers, verbose errors, weak algorithms in non-critical context |
Quick Patterns Reference
Always Flag (Critical)
eval(user_input) # Any language
exec(user_input) # Any language
pickle.loads(user_data) # Python
yaml.load(user_data) # Python (not safe_load)
unserialize($user_data) # PHP
deserialize(user_data) # Java ObjectInputStream
shell=True + user_input # Python subprocess
child_process.exec(user) # Node.js
Always Flag (High)
innerHTML = userInput # DOM XSS
dangerouslySetInnerHTML={user} # React XSS
v-html="userInput" # Vue XSS
f"SELECT * FROM x WHERE {user}" # SQL injection
`SELECT * FROM x WHERE ${user}` # SQL injection
os.system(f"cmd {user_input}") # Command injection
Always Flag (Secrets)
password = "hardcoded"
api_key = "sk-..."
AWS_SECRET_ACCESS_KEY = "..."
private_key = "-----BEGIN"
Check Context First (MUST Investigate Before Flagging)
# SSRF - ONLY if URL is from user input, NOT from settings/config
requests.get(request.GET['url']) # FLAG: User-controlled URL
requests.get(settings.API_URL) # SAFE: Server-controlled config
requests.get(f"{settings.BASE}/{x}") # CHECK: Is 'x' user input?
# Path traversal - ONLY if path is from user input
open(request.GET['file']) # FLAG: User-controlled path
open(settings.LOG_PATH) # SAFE: Server-controlled config
open(f"{BASE_DIR}/{filename}") # CHECK: Is 'filename' user input?
# Open redirect - ONLY if URL is from user input
redirect(request.GET['next']) # FLAG: User-controlled redirect
redirect(settings.LOGIN_URL) # SAFE: Server-controlled config
# Weak crypto - ONLY if used for security purposes
hashlib.md5(file_content) # SAFE: File checksums, caching
hashlib.md5(password) # FLAG: Password hashing
random.random() # SAFE: Non-security uses (UI, sampling)
random.random() for token # FLAG: Security tokens need secrets module
Output Format
## Security Review: [File/Component Name]
### Summary
- **Findings**: X (Y Critical, Z High, ...)
- **Risk Level**: Critical/High/Medium/Low
- **Confidence**: High/Mixed
### Findings
#### [VULN-001] [Vulnerability Type] (Severity)
- **Location**: `file.py:123`
- **Confidence**: High
- **Issue**: [What the vulnerability is]
- **Impact**: [What an attacker could do]
- **Evidence**:
```python
[Vulnerable code snippet]
Needs Verification
[VERIFY-001] [Potential Issue]
- Location:
file.py:456
- Question: [What needs to be verified]
If no vulnerabilities found, state: "No high-confidence vulnerabilities identified."
---
## Reference Files
### Core Vulnerabilities (`references/`)
| File | Covers |
|------|--------|
| `injection.md` | SQL, NoSQL, OS command, LDAP, template injection |
| `xss.md` | Reflected, stored, DOM-based XSS |
| `authorization.md` | Authorization, IDOR, privilege escalation |
| `authentication.md` | Sessions, credentials, password storage |
| `cryptography.md` | Algorithms, key management, randomness |
| `deserialization.md` | Pickle, YAML, Java, PHP deserialization |
| `file-security.md` | Path traversal, uploads, XXE |
| `ssrf.md` | Server-side request forgery |
| `csrf.md` | Cross-site request forgery |
| `data-protection.md` | Secrets exposure, PII, logging |
| `api-security.md` | REST, GraphQL, mass assignment |
| `business-logic.md` | Race conditions, workflow bypass |
| `modern-threats.md` | Prototype pollution, LLM injection, WebSocket |
| `misconfiguration.md` | Headers, CORS, debug mode, defaults |
| `error-handling.md` | Fail-open, information disclosure |
| `supply-chain.md` | Dependencies, build security |
| `logging.md` | Audit failures, log injection |
### Language Guides (`languages/`)
- `python.md` - Django, Flask, FastAPI patterns
- `javascript.md` - Node, Express, React, Vue, Next.js
- `go.md` - Go-specific security patterns
- `rust.md` - Rust unsafe blocks, FFI security
- `java.md` - Spring, Java EE patterns
### Infrastructure (`infrastructure/`)
- `docker.md` - Container security
- `kubernetes.md` - K8s RBAC, secrets, policies
- `terraform.md` - IaC security
- `ci-cd.md` - Pipeline security
- `cloud.md` - AWS/GCP/Azure security
1---2name: security-review3description: Conducts systematic security code reviews to identify exploitable vulnerabilities, reporting only high-confidence findings after researching the codebase.4license: LICENSE5---67<!--8Reference material based on OWASP Cheat Sheet Series (CC BY-SA 4.0)9https://cheatsheetseries.owasp.org/10-->1112# Security Review Skill1314Identify exploitable security vulnerabilities in code. Report only **HIGH CONFIDENCE** findings—clear vulnerable patterns with attacker-controlled input.1516## Scope: Research vs. Reporting1718**CRITICAL DISTINCTION:**1920- **Report on**: Only the specific file, diff, or code provided by the user21- **Research**: The ENTIRE codebase to build confidence before reporting2223Before flagging any issue, you MUST research the codebase to understand:24- Where does this input actually come from? (Trace data flow)25- Is there validation/sanitization elsewhere?26- How is this configured? (Check settings, config files, middleware)27- What framework protections exist?2829**Do NOT report issues based solely on pattern matching.** Investigate first, then report only what you're confident is exploitable.3031## Confidence Levels3233| Level | Criteria | Action |34|-------|----------|--------|35| **HIGH** | Vulnerable pattern + attacker-controlled input confirmed | **Report** with severity |36| **MEDIUM** | Vulnerable pattern, input source unclear | **Note** as "Needs verification" |37| **LOW** | Theoretical, best practice, defense-in-depth | **Do not report** |3839## Do Not Flag4041### General Rules42- Test files (unless explicitly reviewing test security)43- Dead code, commented code, documentation strings44- Patterns using **constants** or **server-controlled configuration**45- Code paths that require prior authentication to reach (note the auth requirement instead)4647### Server-Controlled Values (NOT Attacker-Controlled)4849These are configured by operators, not controlled by attackers:5051| Source | Example | Why It's Safe |52|--------|---------|---------------|53| Django settings | `settings.API_URL`, `settings.ALLOWED_HOSTS` | Set via config/env at deployment |54| Environment variables | `os.environ.get('DATABASE_URL')` | Deployment configuration |55| Config files | `config.yaml`, `app.config['KEY']` | Server-side files |56| Framework constants | `django.conf.settings.*` | Not user-modifiable |57| Hardcoded values | `BASE_URL = "https://api.internal"` | Compile-time constants |5859**SSRF Example - NOT a vulnerability:**60```python61# SAFE: URL comes from Django settings (server-controlled)62response = requests.get(f"{settings.SEER_AUTOFIX_URL}{path}")63```6465**SSRF Example - IS a vulnerability:**66```python67# VULNERABLE: URL comes from request (attacker-controlled)68response = requests.get(request.GET.get('url'))69```7071### Framework-Mitigated Patterns72Check language guides before flagging. Common false positives:7374| Pattern | Why It's Usually Safe |75|---------|----------------------|76| Django `{{ variable }}` | Auto-escaped by default |77| React `{variable}` | Auto-escaped by default |78| Vue `{{ variable }}` | Auto-escaped by default |79| `User.objects.filter(id=input)` | ORM parameterizes queries |80| `cursor.execute("...%s", (input,))` | Parameterized query |81| `innerHTML = "<b>Loading...</b>"` | Constant string, no user input |8283**Only flag these when:**84- Django: `{{ var|safe }}`, `{% autoescape off %}`, `mark_safe(user_input)`85- React: `dangerouslySetInnerHTML={{__html: userInput}}`86- Vue: `v-html="userInput"`87- ORM: `.raw()`, `.extra()`, `RawSQL()` with string interpolation8889## Review Process9091### 1. Detect Context9293What type of code am I reviewing?9495| Code Type | Load These References |96|-----------|----------------------|97| API endpoints, routes | `authorization.md`, `authentication.md`, `injection.md` |98| Frontend, templates | `xss.md`, `csrf.md` |99| File handling, uploads | `file-security.md` |100| Crypto, secrets, tokens | `cryptography.md`, `data-protection.md` |101| Data serialization | `deserialization.md` |102| External requests | `ssrf.md` |103| Business workflows | `business-logic.md` |104| GraphQL, REST design | `api-security.md` |105| Config, headers, CORS | `misconfiguration.md` |106| CI/CD, dependencies | `supply-chain.md` |107| Error handling | `error-handling.md` |108| Audit, logging | `logging.md` |109110### 2. Load Language Guide111112Based on file extension or imports:113114| Indicators | Guide |115|------------|-------|116| `.py`, `django`, `flask`, `fastapi` | `languages/python.md` |117| `.js`, `.ts`, `express`, `react`, `vue`, `next` | `languages/javascript.md` |118| `.go`, `go.mod` | `languages/go.md` |119| `.rs`, `Cargo.toml` | `languages/rust.md` |120| `.java`, `spring`, `@Controller` | `languages/java.md` |121122### 3. Load Infrastructure Guide (if applicable)123124| File Type | Guide |125|-----------|-------|126| `Dockerfile`, `.dockerignore` | `infrastructure/docker.md` |127| K8s manifests, Helm charts | `infrastructure/kubernetes.md` |128| `.tf`, Terraform | `infrastructure/terraform.md` |129| GitHub Actions, `.gitlab-ci.yml` | `infrastructure/ci-cd.md` |130| AWS/GCP/Azure configs, IAM | `infrastructure/cloud.md` |131132### 4. Research Before Flagging133134**For each potential issue, research the codebase to build confidence:**135136- Where does this value actually come from? Trace the data flow.137- Is it configured at deployment (settings, env vars) or from user input?138- Is there validation, sanitization, or allowlisting elsewhere?139- What framework protections apply?140141Only report issues where you have HIGH confidence after understanding the broader context.142143### 5. Verify Exploitability144145For each potential finding, confirm:146147**Is the input attacker-controlled?**148149| Attacker-Controlled (Investigate) | Server-Controlled (Usually Safe) |150|-----------------------------------|----------------------------------|151| `request.GET`, `request.POST`, `request.args` | `settings.X`, `app.config['X']` |152| `request.json`, `request.data`, `request.body` | `os.environ.get('X')` |153| `request.headers` (most headers) | Hardcoded constants |154| `request.cookies` (unsigned) | Internal service URLs from config |155| URL path segments: `/users/<id>/` | Database content from admin/system |156| File uploads (content and names) | Signed session data |157| Database content from other users | Framework settings |158| WebSocket messages | |159160**Does the framework mitigate this?**161- Check language guide for auto-escaping, parameterization162- Check for middleware/decorators that sanitize163164**Is there validation upstream?**165- Input validation before this code166- Sanitization libraries (DOMPurify, bleach, etc.)167168### 6. Report HIGH Confidence Only169170Skip theoretical issues. Report only what you've confirmed is exploitable after research.171172---173174## Severity Classification175176| Severity | Impact | Examples |177|----------|--------|----------|178| **Critical** | Direct exploit, severe impact, no auth required | RCE, SQL injection to data, auth bypass, hardcoded secrets |179| **High** | Exploitable with conditions, significant impact | Stored XSS, SSRF to metadata, IDOR to sensitive data |180| **Medium** | Specific conditions required, moderate impact | Reflected XSS, CSRF on state-changing actions, path traversal |181| **Low** | Defense-in-depth, minimal direct impact | Missing headers, verbose errors, weak algorithms in non-critical context |182183---184185## Quick Patterns Reference186187### Always Flag (Critical)188```189eval(user_input) # Any language190exec(user_input) # Any language191pickle.loads(user_data) # Python192yaml.load(user_data) # Python (not safe_load)193unserialize($user_data) # PHP194deserialize(user_data) # Java ObjectInputStream195shell=True + user_input # Python subprocess196child_process.exec(user) # Node.js197```198199### Always Flag (High)200```201innerHTML = userInput # DOM XSS202dangerouslySetInnerHTML={user} # React XSS203v-html="userInput" # Vue XSS204f"SELECT * FROM x WHERE {user}" # SQL injection205`SELECT * FROM x WHERE ${user}` # SQL injection206os.system(f"cmd {user_input}") # Command injection207```208209### Always Flag (Secrets)210```211password = "hardcoded"212api_key = "sk-..."213AWS_SECRET_ACCESS_KEY = "..."214private_key = "-----BEGIN"215```216217### Check Context First (MUST Investigate Before Flagging)218```219# SSRF - ONLY if URL is from user input, NOT from settings/config220requests.get(request.GET['url']) # FLAG: User-controlled URL221requests.get(settings.API_URL) # SAFE: Server-controlled config222requests.get(f"{settings.BASE}/{x}") # CHECK: Is 'x' user input?223224# Path traversal - ONLY if path is from user input225open(request.GET['file']) # FLAG: User-controlled path226open(settings.LOG_PATH) # SAFE: Server-controlled config227open(f"{BASE_DIR}/{filename}") # CHECK: Is 'filename' user input?228229# Open redirect - ONLY if URL is from user input230redirect(request.GET['next']) # FLAG: User-controlled redirect231redirect(settings.LOGIN_URL) # SAFE: Server-controlled config232233# Weak crypto - ONLY if used for security purposes234hashlib.md5(file_content) # SAFE: File checksums, caching235hashlib.md5(password) # FLAG: Password hashing236random.random() # SAFE: Non-security uses (UI, sampling)237random.random() for token # FLAG: Security tokens need secrets module238```239240---241242## Output Format243244```markdown245## Security Review: [File/Component Name]246247### Summary248- **Findings**: X (Y Critical, Z High, ...)249- **Risk Level**: Critical/High/Medium/Low250- **Confidence**: High/Mixed251252### Findings253254#### [VULN-001] [Vulnerability Type] (Severity)255- **Location**: `file.py:123`256- **Confidence**: High257- **Issue**: [What the vulnerability is]258- **Impact**: [What an attacker could do]259- **Evidence**:260 ```python261 [Vulnerable code snippet]262 ```263- **Fix**: [How to remediate]264265### Needs Verification266267#### [VERIFY-001] [Potential Issue]268- **Location**: `file.py:456`269- **Question**: [What needs to be verified]270```271272If no vulnerabilities found, state: "No high-confidence vulnerabilities identified."273274---275276## Reference Files277278### Core Vulnerabilities (`references/`)279| File | Covers |280|------|--------|281| `injection.md` | SQL, NoSQL, OS command, LDAP, template injection |282| `xss.md` | Reflected, stored, DOM-based XSS |283| `authorization.md` | Authorization, IDOR, privilege escalation |284| `authentication.md` | Sessions, credentials, password storage |285| `cryptography.md` | Algorithms, key management, randomness |286| `deserialization.md` | Pickle, YAML, Java, PHP deserialization |287| `file-security.md` | Path traversal, uploads, XXE |288| `ssrf.md` | Server-side request forgery |289| `csrf.md` | Cross-site request forgery |290| `data-protection.md` | Secrets exposure, PII, logging |291| `api-security.md` | REST, GraphQL, mass assignment |292| `business-logic.md` | Race conditions, workflow bypass |293| `modern-threats.md` | Prototype pollution, LLM injection, WebSocket |294| `misconfiguration.md` | Headers, CORS, debug mode, defaults |295| `error-handling.md` | Fail-open, information disclosure |296| `supply-chain.md` | Dependencies, build security |297| `logging.md` | Audit failures, log injection |298299### Language Guides (`languages/`)300- `python.md` - Django, Flask, FastAPI patterns301- `javascript.md` - Node, Express, React, Vue, Next.js302- `go.md` - Go-specific security patterns303- `rust.md` - Rust unsafe blocks, FFI security304- `java.md` - Spring, Java EE patterns305306### Infrastructure (`infrastructure/`)307- `docker.md` - Container security308- `kubernetes.md` - K8s RBAC, secrets, policies309- `terraform.md` - IaC security310- `ci-cd.md` - Pipeline security311- `cloud.md` - AWS/GCP/Azure security