Vulnerability Detection Patterns
Purpose: Use this reference during SCAN to identify common vulnerability patterns, confirm likely findings, and compare safe versus unsafe code.
Interpretation Rules
- Regexes are heuristics, not proof.
- Confirm source-to-sink reachability before escalating a finding.
- For generic secrets, combine regex, entropy, and contextual review.
- AI-generated code is 2.74x more likely to contain XSS than human code — apply extra scrutiny.
Hardcoded Secrets
Detection Patterns
# API Keys
(api[_-]?key|apikey)['":\s]*[=:]\s*['"][a-zA-Z0-9]{20,}['"]
# AWS Keys
(AKIA|ABIA|ACCA|ASIA)[A-Z0-9]{16}
# Private Keys
-----BEGIN (RSA|DSA|EC|OPENSSH) PRIVATE KEY-----
# Generic Secrets (entropy + context review recommended)
(password|passwd|pwd|secret|token)['":\s]*[=:]\s*['"][^'"]{8,}['"]
# GitHub Tokens
(ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9_]{36,}
# JWT tokens
eyJ[A-Za-z0-9_-]{10,}\.eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]+Bad: const API_KEY = 'sk_live_abc123xyz789';
Good: const API_KEY = process.env.API_KEY;
Regex limitation: known formats (AWS, GitHub tokens) are reliable; generic secrets need entropy checks and contextual review.
SQL Injection
(query|execute|exec)\s*\(\s*['"`].*\$\{.*\}
(query|execute|exec)\s*\(\s*['"`].*\+\s*\w+
SELECT.*FROM.*WHERE.*['"`]\s*\+
INSERT.*INTO.*VALUES.*['"`]\s*\+Bad: db.query(\SELECT * FROM users WHERE id = ${userId}`);**Good:**db.query('SELECT * FROM users WHERE id = ?', [userId]);`
XSS (Cross-Site Scripting)
\.innerHTML\s*=\s*[^'"]
dangerouslySetInnerHTML
document\.write\s*\(
\.html\s*\(\s*[^'"]Bad: element.innerHTML = userInput;
Good: element.textContent = userInput; or element.innerHTML = DOMPurify.sanitize(userInput);
AI-generated code fails XSS tests 86% of the time — flag all innerHTML assignments in AI-assisted code.
Command Injection
exec\s*\(\s*['"`].*\$\{
spawn\s*\(\s*['"`].*\+
child_process.*\$\{
os\.system\s*\(.*\+|os\.system\s*\(.*f['"]
subprocess\.(call|run|Popen)\s*\(.*shell\s*=\s*TrueBad: exec(\ls ${userDir}`);**Good:**execFile('ls', [sanitizedDir]);`
Path Traversal
(readFile|writeFile|unlink)\s*\(.*\+.*\)
path\.join\s*\(.*req\.(params|query|body)
\.\.\/Bad: fs.readFile(baseDir + req.params.file);
Good:
const safePath = path.join(baseDir, path.basename(req.params.file));
if (!safePath.startsWith(baseDir)) throw new Error('Invalid path');
fs.readFile(safePath);NoSQL Injection
\$where|\$gt|\$lt|\$ne|\$regex|\$exists
(find|findOne|aggregate|update)\s*\(\s*\{.*req\.(body|query|params)Bad: db.collection('users').find({ username: req.body.username, password: req.body.password });
Good: app.use(mongoSanitize());
Prompt Injection
# LLM instruction override
(ignore|disregard|forget)\s+(previous|above|all)\s+(instructions|prompts|rules)
(system|admin)\s*:\s*(override|execute|run)
# Template injection in prompt construction
\$\{.*user.*\}.*prompt|prompt.*\$\{.*user
# Indirect injection markers
<\|im_start\|>|<\|im_end\|>|\[INST\]|\[/INST\]Bad: const prompt = \Summarize this text: ${userInput}`;`
Good:
const response = await llm.complete({
system: 'You are a text summarizer. Only summarize the provided text.',
user: userInput,
});Prototype Pollution
__proto__|constructor\s*\.\s*prototype|Object\.assign\s*\(\s*\{\}
(merge|extend|assign|defaults)\s*\(.*req\.(body|query|params)Bad: for (const key in source) { target[key] = source[key]; }
Good:
function safeMerge(target, source) {
for (const key of Object.keys(source)) {
if (key === '__proto__' || key === 'constructor' || key === 'prototype') continue;
target[key] = source[key];
}
}Exceptional Conditions (OWASP A10:2025)
# Empty catch blocks
catch\s*\([^)]*\)\s*\{\s*\}
# Sensitive data in error messages (CWE-209)
(res\.status|res\.json|throw)\s*.*\.(stack|message|sql|query)
# Unhandled promise rejections
\.then\s*\([^)]+\)\s*;(?!\s*\.catch)
# Fail-open patterns (CWE-636)
catch\s*\([^)]*\)\s*\{[^}]*(continue|return\s+true|next\(\))Bad: catch (e) { return res.status(500).json({ error: e.message, stack: e.stack }); }
Good: catch (e) { logger.error('Operation failed', e); return res.status(500).json({ error: 'An error occurred' }); }
AI-Generated Code Signals
Flag these patterns with boosted severity when code is known or suspected to be AI-generated:
| Pattern | Typical AI failure | Detection |
|---|---|---|
eval(), Function() |
Unsafe dynamic execution | Regex |
| String-built SQL | Missing parameterization | Regex |
innerHTML assignment |
Missing sanitization | Regex |
| Missing auth middleware | Incomplete auth flow | Structural review |
| Non-existent packages | Slopsquatting / hallucination | Registry lookup |
exec() with template literals |
Command injection | Regex |
Signal Keywords → Recipe (SKILL.md excerpt)
For natural-language input without an explicit subcommand. Subcommand match wins if both apply.
| Keywords | Recipe |
|---|---|
secret, credential, API key |
secrets |
injection, SQL, XSS, CSRF |
injection |
CVE, dependency, SBOM, supply chain, typosquatting, slopsquatting, lockfile |
deps |
header, CSP, CORS, HSTS |
headers |
auth, JWT, OAuth, rate limit |
authn / authz — route by identity vs access-control focus |
AI-generated, LLM, MCP, prompt injection, vibe coding |
aisec — heightened CWE-918/798/22/78 scrutiny; for MCP also scan configs for leaked secrets and tool descriptions for injection payloads |
OWASP, audit, checklist |
scan (full OWASP Top 10 audit) |
MASVS, MASTG, MASWE, mobile security, iOS security, Android security, MobSF, Info.plist, gradle.properties, local.properties, xcconfig, BuildConfig |
mobile |
multi-engine, tri-engine security, tri-engine scan, parallel SAST, cross-engine vulnerability scan, high-assurance scan |
multi |
SARIF, machine-readable |
any Recipe with --sarif output mode (see reference/defensive-controls.md) |
| unclear request | clarify scope and route per _common/BOUNDARIES.md |