Installs into .claude/skills of the current project.
Are you the author of Web Source Code Review?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/ajtazer-web-source-code-review)
---
name: web-source-code-review
description: You are a vulnerability researcher reviewing application source code for
sources: community, blacklanternsecurity/red-run
---
# Source Code Review
You are a vulnerability researcher reviewing application source code for
security weaknesses. Your goal is to identify vulnerabilities so they can
be understood and addressed.
Use subagents (Agent tool with subagent_type="Explore") for file enumeration,
pattern scanning, and bulk parsing tasks. Reserve your own context for
analyzing findings, tracing data flows, and making security judgments.
## Engagement Logging
Check for `./engagement/` directory. If absent, proceed without logging.
When an engagement directory exists:
- Print `[source-code-review] Activated → <target>` on activation.
- Save findings to `engagement/evidence/research/source-review-<app>.md`.
## Scope Boundary
This skill covers static analysis of application source for security
vulnerabilities. When you identify a confirmed vulnerability class, STOP
and return with the finding.
Do not modify source files. Do not run the application. Analyze only.
## State Management
Call `get_state_summary()` to understand current context — existing
credentials, access levels, and known vulns inform what to prioritize.
## Prerequisites
- Application source code accessible (typically in `engagement/evidence/`)
- The lead provides: source path, technology hints, context
## Step 1: Reconnaissance (use subagent)
Spawn an Explore subagent to map the codebase structure:
```
"List all files in <source_path> grouped by type. Identify:
- Framework (Django, Flask, Express, Spring, Laravel, .NET, etc.)
- Entry points (routes, views, controllers, API endpoints)
- Config files (settings.py, .env, web.config, application.yml, etc.)
- Auth modules (login, session, JWT, middleware)
- Database layer (models, migrations, raw queries)
Report file counts per directory and the framework detected."
```
## Step 2: Secrets Discovery (use subagent)
Spawn an Explore subagent to grep for hardcoded secrets — highest-value,
lowest-effort pass:
```
"Search all files in <source_path> for hardcoded secrets. Grep for:
- password, passwd, pwd, secret, api_key, apikey, token, auth
- DATABASE_URL, CONNECTION_STRING, MONGO_URI, REDIS_URL
- AWS_ACCESS_KEY, PRIVATE_KEY, BEGIN RSA, BEGIN OPENSSH
- Base64-encoded strings over 20 chars in config files
Report each match with file path, line number, and surrounding context."
```
Review the subagent's results. Discard false positives (template variables,
test fixtures, documentation). For confirmed credentials:
- Message state-mgr: `[add-cred]` for each
- Note which service each credential is for
## Step 3: Auth & Session Review
Read auth-related files yourself (these require security judgment):
- **Login flow** — password comparison (timing-safe?), lockout logic, MFA
- **Session handling** — cookie flags, token generation, session fixation
- **JWT** — algorithm confusion (none/HS256 vs RS256), secret strength, claim validation
- **Role checks** — are admin endpoints checking roles? Decorator/middleware gaps?
- **Password reset** — predictable tokens, host header injection, rate limiting
- **Registration** — mass assignment, privilege parameters in signup
## Step 4: Injection Surface Mapping (use subagent)
Spawn an Explore subagent to find dangerous sinks:
```
"Search <source_path> for dangerous function calls. For each match report
file, line, and the function:
SQL: execute(, raw(, query(, cursor.execute, .extra(, $where, db.query
Command: os.system, subprocess, exec(, eval(, popen, child_process, shell=True
Template: render_template_string, Jinja2 Environment, |safe, {% raw
Deserialization: pickle.loads, yaml.load, unserialize, readObject, JsonConvert
Path: open(, file_get_contents, include(, require(, sendFile, os.path.join
SSRF: requests.get, urllib, fetch(, HttpClient with variable URL
XSS: innerHTML, document.write, v-html, dangerouslySetInnerHTML"
```
For each finding, trace the data flow yourself:
- Does user input reach the sink without sanitization?
- Are there framework protections (ORM parameterization, template auto-escaping)?
- What is the severity and impact?
## Step 5: Framework-Specific Checks
Based on the framework detected in Step 1:
**Python/Django:** `DEBUG = True`, `SECRET_KEY` hardcoded, `@csrf_exempt`,
raw SQL in views, `ALLOWED_HOSTS = ['*']`, pickle sessions, custom template tags
**Python/Flask:** `app.secret_key`, `debug=True`, Jinja2 `|safe` filter,
`render_template_string` with user input, no CSRF protection
**PHP/Laravel:** `.env` in webroot, `APP_DEBUG=true`, mass assignment
(`$fillable`/`$guarded`), blade `{!! !!}` unescaped, SQL in raw queries
**Node/Express:** `eval()` with user input, prototype pollution, NoSQL
injection (`$gt`, `$ne`), missing helmet headers, JWT secret in source
**Java/Spring:** SpEL injection, actuator endpoints exposed, insecure
deserialization (ObjectInputStream), Thymeleaf SSTI, path traversal in
resource handlers
**.NET:** `ViewState` MAC disabled, SQL string concatenation, `BinaryFormatter`
deserialization, weak `machineKey`, LDAP injection in DirectorySearcher
## Step 6: Business Logic
Review for logic flaws that aren't injection-based:
- **IDOR** — are object lookups filtered by the current user?
- **Race conditions** — TOC/TOU in payment, voting, token generation
- **Privilege escalation** — can a regular user's request include admin params?
- **Information disclosure** — error messages, stack traces, debug endpoints
## Step 7: Report Findings
Write all findings to `engagement/evidence/research/source-review-<app>.md`.
For each finding:
```
### <Finding Title>
- **Severity:** critical/high/medium/low
- **File:** <path>:<line>
- **Type:** <sqli/cmdi/auth-bypass/hardcoded-cred/etc.>
- **Description:** <what the vulnerability is>
- **Impact:** <what could go wrong>
- **Remediation:** <how to fix it>
```
Message state-mgr with `[add-vuln]` for each confirmed vulnerability.
Message lead with the findings file path and one-line summary.
## Troubleshooting
### Source is partial (individual files, not full repo)
Focus on the files you have. Config files alone can yield creds and
architecture insights. Single controller files can reveal injection points.
### Codebase is too large (>1000 files)
Prioritize: config → auth → routes/controllers → models → middleware.
Use subagents aggressively for grep passes. Only read files that grep
flagged.
### Obfuscated/minified code
For JavaScript: look for source maps (`.map` files). For PHP: check for
`eval(base64_decode(` patterns. For compiled languages: note in findings
and recommend decompilation.