scan-security -- OWASP-Based Security Vulnerability Detection
Corresponding rule: security.md
Purpose
Detect security vulnerabilities in code via static pattern matching based on OWASP Top 10. Does not auto-fix; reports only suspected items.
Input -- Dynamic Target Resolution
Resolve target directories in this order:
- CLAUDE.md "Project Structure" section -- extract source code directories
- If CLAUDE.md is missing or has no structure info: Glob source files (
**/*.{ts,tsx,js,jsx,py,java,go,rs}) -- use the top-level directory containing matched files - If no source files are found: report status as SHALLOW and state the reason
Default exclusions: node_modules/, .git/, dist/, build/, coverage/
Skill-specific exclusions: *.test.*, *.spec.*, test_*, *_test.* (security test code excluded)
Mandatory Output: Target Resolution Result
Output the following before proceeding with validation. Do not advance until resolution is complete.
| Step | Result |
|---|---|
| CLAUDE.md check | Found/Not found |
| Resolved directories | {list or "none"} |
| Source file count | {count} |
| Resolution method | CLAUDE.md / Glob fallback / SHALLOW |
Validation Categories
1. Hardcoded Secrets
Detect passwords, API keys, and tokens embedded directly in code.
Search patterns:
API_KEY\s*=\s*["']password\s*=\s*["']secret\s*=\s*["']token\s*=\s*["']PRIVATE_KEY\s*=\s*["']aws_access_key_id\s*=\s*["']aws_secret_access_key\s*=\s*["']
Severity: CRITICAL
2. SQL Injection
Detect patterns that build SQL queries via string interpolation.
Search patterns:
f"SELECTf"INSERTf"UPDATEf"DELETEf"DROP`SELECT.*\$\{`(SQL in template literals)"SELECT.*" \+(SQL via string concatenation)
Severity: CRITICAL
3. XSS (Cross-Site Scripting)
Detect patterns that inject user input into HTML without escaping.
Search patterns:
innerHTML\s*=dangerouslySetInnerHTMLv-html=\{!!.*!!\}(Blade unescaped output)\|safe(Django/Jinja safe filter)
Severity: HIGH
4. Command Injection
Detect patterns that pass external input directly to shell commands.
Search patterns:
os.system(f"subprocess.*shell=Trueexec((dynamic code execution)eval((dynamic code execution)child_process.exec(`.*(Node.js)
Severity: CRITICAL
5. Error Information Exposure
Detect patterns that include internal system information in user responses.
Search patterns:
traceback.format_exc()-- near return/responsestr(e)-- included directly in the response objectstack.*trace-- included in the responseexc_info=True-- inside a user-response function
Severity: MEDIUM
6. .gitignore Check
Verify that secret files are included in .gitignore.
Required patterns (must exist in .gitignore):
.envrelated:.env,.env.*,.env.local- Credential files:
credentials,credentials.* - Key files:
*.pem,*.key,*.p12,*.pfx - Secret directories:
secrets/,.secrets/
Severity: HIGH when missing
Execution Logic
Globto collect target source files (excluding test files)- Categories 1-5:
Grepeach category's patterns across all source files - Category 6:
Readthe.gitignorefile and check for required patterns - Sort detected items by severity and output as a table
Mandatory Output: Security Scan Verification Matrix
Output the matrix below before generating the final report. Do not proceed until every category has been scanned.
| Category | Status | Items Checked | Findings | Severity | Evidence |
|---|---|---|---|---|---|
| Hardcoded Secrets | ? | ? | ? | CRITICAL | {tool, files, pattern} |
| SQL Injection | ? | ? | ? | CRITICAL | {tool, files, pattern} |
| XSS | ? | ? | ? | HIGH | {tool, files, pattern} |
| Command Injection | ? | ? | ? | CRITICAL | {tool, files, pattern} |
| Error Information Exposure | ? | ? | ? | MEDIUM | {tool, files, pattern} |
| .gitignore | ? | ? | ? | HIGH | {tool, files, pattern} |
Status values: PASS (verification complete, no issues), NOT_APPLICABLE (no source files), SKIPPED (plugin issue), SHALLOW (target resolution failed)
Pre-Output Checklist (Mandatory Before Final Output)
Check every item before writing the report. If any item is unchecked, go back and complete it.
- Every validation category has a Status value (no empty Status cells)
- Every category with Status != SKIPPED has an Evidence value
- Every finding includes file path, line number (where applicable), and matched pattern
- The .gitignore check has verified all required patterns
- Report language matches the user's conversation language
Schema Compliance Check (Mandatory Before Saving to .ww-w-ai/)
Before writing to .ww-w-ai/devtools/scan-security/, verify the JSON output:
- Every "required" field in schema.json is present and non-empty
- The findings[] array contains every detected item
- severitySummary counts match the actual finding counts per severity
Output
Generate the scan report in the user's conversation language.
Output detection results as a Markdown table in this format:
===== Security Scan Report =====
| File:Line | Type | Severity | Pattern |
|-----------|------|----------|---------|
| `src/config/db.ts:15` | Hardcoded Secret | CRITICAL | `password = "admin123"` |
| `src/api/users.ts:42` | SQL Injection | CRITICAL | `f"SELECT * FROM users WHERE id = {id}"` |
| `src/components/Post.tsx:18` | XSS | HIGH | `dangerouslySetInnerHTML` |
| `.gitignore` | Unprotected Secret | HIGH | `.env` pattern missing |
| `src/handlers/error.ts:30` | Error Information Exposure | MEDIUM | `str(e)` returned directly |
Total suspected items: {N}
CRITICAL: {C}
HIGH: {H}
MEDIUM: {M}
==============================
When there are no suspected items:
===== Security Scan Report =====
No suspected items.
==============================
Output Persistence
After generating the security scan report, save results to .ww-w-ai/devtools/scan-security/:
- Create
.ww-w-ai/devtools/scan-security/if missing - Write
latest.json-- structured result followingtemplates/schema.json - Write
latest.md-- human-readable report followingtemplates/report.template.md - Archive to
history/-- copy latest.json to.ww-w-ai/devtools/scan-security/history/{timestamp}.json
latest.md is generated in the user's conversation language. JSON field names stay in English regardless of language.
The JSON output enables machine-parseable history tracking and cross-run comparison.
The history/ directory preserves previous executions for trend analysis.
Permission Rationale
- Write: Exclusively for .ww-w-ai/ output persistence. No project source modification.
- Bash: Exclusively for read-only git/system queries. No file modifications.
Notes
- Bash is permitted for directory creation (
mkdir -p .ww-w-ai/devtools/scan-security/history). The scan itself is read-only and does not modify project files. - Based on static pattern matching, so false positives are possible. Results are presented as "suspected items"; developers must confirm whether real vulnerabilities exist.
- Environment variable assignments (
os.environ["API_KEY"]) are not hardcoding and are excluded from detection. - Security test code (code bearing a
SECURITYprefix comment) is treated as intentionally vulnerable per security.md exceptions.
Spec Reference
For detailed validation criteria, evidence tables, and examples:
- Corresponding rule spec:
../../docs/specs/security.md