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: Review code changes for injection, XSS, authentication, authorization, cryptography, and other security defects with evidence-based severity.4license: Apache-2.05---6
7<!--
8Reference material based on OWASP Cheat Sheet Series (CC BY-SA 4.0)
9https://cheatsheetseries.owasp.org/
10-->
11
12# Security Review Skill
13
14Identify exploitable security vulnerabilities in code. Report only **HIGH CONFIDENCE** findings—clear vulnerable patterns with attacker-controlled input.
15
16## Scope: Research vs. Reporting
17
18**CRITICAL DISTINCTION:**
19
20- **Report on**: Only the specific file, diff, or code provided by the user
21- **Research**: The ENTIRE codebase to build confidence before reporting
22
23Before 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?
28
29**Do NOT report issues based solely on pattern matching.** Investigate first, then report only what you're confident is exploitable.
30
31## Confidence Levels
32
33| 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** |
38
39## Do Not Flag
40
41### General Rules
42- Test files (unless explicitly reviewing test security)
43- Dead code, commented code, documentation strings
44- Patterns using **constants** or **server-controlled configuration**
45- Code paths that require prior authentication to reach (note the auth requirement instead)
46
47### Server-Controlled Values (NOT Attacker-Controlled)
48
49These are configured by operators, not controlled by attackers:
50
51| 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 |
58
59**SSRF Example - NOT a vulnerability:**
60```python
61# SAFE: URL comes from Django settings (server-controlled)
62response = requests.get(f"{settings.SEER_AUTOFIX_URL}{path}")
63```
64
65**SSRF Example - IS a vulnerability:**
66```python
67# VULNERABLE: URL comes from request (attacker-controlled)
68response = requests.get(request.GET.get('url'))
69```
70
71### Framework-Mitigated Patterns
72Check language guides before flagging. Common false positives:
73
74| 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 |
82
83**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 interpolation
88
89## Review Process
90
91### 1. Detect Context
92
93What type of code am I reviewing?
94
95| 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` |
109
110### 2. Load Language Guide
111
112Based on file extension or imports:
113
114| 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` |
121
122### 3. Load Infrastructure Guide (if applicable)
123
124| 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` |
131
132### 4. Research Before Flagging
133
134**For each potential issue, research the codebase to build confidence:**
135
136- 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?
140
141Only report issues where you have HIGH confidence after understanding the broader context.
142
143### 5. Verify Exploitability
144
145For each potential finding, confirm:
146
147**Is the input attacker-controlled?**
148
149| 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 | |
159
160**Does the framework mitigate this?**
161- Check language guide for auto-escaping, parameterization
162- Check for middleware/decorators that sanitize
163
164**Is there validation upstream?**
165- Input validation before this code
166- Sanitization libraries (DOMPurify, bleach, etc.)
167
168### 6. Report HIGH Confidence Only
169
170Skip theoretical issues. Report only what you've confirmed is exploitable after research.
171
172---
173
174## Severity Classification
175
176| 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 |
182
183---
184
185## Quick Patterns Reference
186
187### Always Flag (Critical)
188```
189eval(user_input) # Any language
190exec(user_input) # Any language
191pickle.loads(user_data) # Python
192yaml.load(user_data) # Python (not safe_load)
193unserialize($user_data) # PHP
194deserialize(user_data) # Java ObjectInputStream
195shell=True + user_input # Python subprocess
196child_process.exec(user) # Node.js
197```
198
199### Always Flag (High)
200```
201innerHTML = userInput # DOM XSS
202dangerouslySetInnerHTML={user} # React XSS
203v-html="userInput" # Vue XSS
204f"SELECT * FROM x WHERE {user}" # SQL injection
205`SELECT * FROM x WHERE ${user}` # SQL injection
206os.system(f"cmd {user_input}") # Command injection
207```
208
209### Always Flag (Secrets)
210```
211password = "hardcoded"
212api_key = "sk-..."
213AWS_SECRET_ACCESS_KEY = "..."
214private_key = "-----BEGIN"
215```
216
217### Check Context First (MUST Investigate Before Flagging)
218```
219# SSRF - ONLY if URL is from user input, NOT from settings/config
220requests.get(request.GET['url']) # FLAG: User-controlled URL
221requests.get(settings.API_URL) # SAFE: Server-controlled config
222requests.get(f"{settings.BASE}/{x}") # CHECK: Is 'x' user input?
223
224# Path traversal - ONLY if path is from user input
225open(request.GET['file']) # FLAG: User-controlled path
226open(settings.LOG_PATH) # SAFE: Server-controlled config
227open(f"{BASE_DIR}/{filename}") # CHECK: Is 'filename' user input?
228
229# Open redirect - ONLY if URL is from user input
230redirect(request.GET['next']) # FLAG: User-controlled redirect
231redirect(settings.LOGIN_URL) # SAFE: Server-controlled config
232
233# Weak crypto - ONLY if used for security purposes
234hashlib.md5(file_content) # SAFE: File checksums, caching
235hashlib.md5(password) # FLAG: Password hashing
236random.random() # SAFE: Non-security uses (UI, sampling)
237random.random() for token # FLAG: Security tokens need secrets module
238```
239
240---
241
242## Output Format
243
244```markdown
245## Security Review: [File/Component Name]
246
247### Summary
248- **Findings**: X (Y Critical, Z High, ...)
249- **Risk Level**: Critical/High/Medium/Low
250- **Confidence**: High/Mixed
251
252### Findings
253
254#### [VULN-001] [Vulnerability Type] (Severity)
255- **Location**: `file.py:123`
256- **Confidence**: High
257- **Issue**: [What the vulnerability is]
258- **Impact**: [What an attacker could do]
259- **Evidence**:
260 ```python
261 [Vulnerable code snippet]
262 ```
263- **Fix**: [How to remediate]
264
265### Needs Verification
266
267#### [VERIFY-001] [Potential Issue]
268- **Location**: `file.py:456`
269- **Question**: [What needs to be verified]
270```
271
272If no vulnerabilities found, state: "No high-confidence vulnerabilities identified."
273
274---
275
276## Reference Files
277
278### 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 |
298
299### Language Guides (`languages/`)
300- `python.md` - Django, Flask, FastAPI patterns
301- `javascript.md` - Node, Express, React, Vue, Next.js
302- `go.md` - Go-specific security patterns
303- `rust.md` - Rust unsafe blocks, FFI security
304- `java.md` - Spring, Java EE patterns
305
306### Infrastructure (`infrastructure/`)
307- `docker.md` - Container security
308- `kubernetes.md` - K8s RBAC, secrets, policies
309- `terraform.md` - IaC security
310- `ci-cd.md` - Pipeline security
311- `cloud.md` - AWS/GCP/Azure security