Systematic pattern exhaustion methodology. Load after finding any confirmed vulnerability to search for all instances of the same root cause pattern across the codebase.
69
85%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
When you find a vulnerability, you have found a PATTERN. The same developer who wrote one broken auth check likely wrote twenty. The same framework that misses one guard has a systemic design gap. One root cause → multiple CVEs.
Real-world examples:
After confirming a vulnerability, classify its root cause pattern:
| Root Cause | Search Pattern |
|---|---|
| Missing auth/authz check | grep -rn 'def handle_|router\.\(get|post|put|delete\)' | grep -v 'auth|permission|require|middleware' |
| Unvalidated path parameter | grep -rn 'req\.params|request\.args|ctx\.params' | grep -v 'sanitize|validate|path\.resolve|path\.normalize' |
| SQL string interpolation | grep -rn 'f"SELECT|f"INSERT|f"UPDATE|query(.*\+.*|query(.*\$\{' --include='*.py' --include='*.ts' --include='*.js' |
| shell: true with user input | grep -rn 'shell:\s*true|shell=True|os\.system|subprocess\.call.*shell' --include='*.py' --include='*.ts' --include='*.js' |
| Missing ownership validation | grep -rn 'delete|update|modify' --include='*.py' --include='*.ts' | grep -v 'owner|author|created_by|user_id.*==' |
| Default-open feature flag | grep -rn 'enabled.*=.*false|feature.*disabled|trust.*=.*true' --include='*.ts' --include='*.py' |
| Unsafe deserialization | grep -rn 'pickle\.loads|yaml\.load|yaml\.unsafe|unserialize|JSON\.parse.*reviver|eval(' --include='*.py' --include='*.js' --include='*.php' |
| Type confusion in guard | grep -rn 'typeof.*==|instanceof|is_array|Array\.isArray' --include='*.ts' --include='*.js' --include='*.php' |
| Missing CSRF/state check | grep -rn 'state=|csrf|nonce' --include='*.py' --include='*.ts' | grep -v 'verify|validate|check' |
| Prototype pollution | grep -rn 'Object\.assign|merge(|extend(|deepMerge|_.merge|lodash' --include='*.js' --include='*.ts' |
For semgrep (when installed):
# Generic: user input reaching dangerous sink without sanitization
semgrep --config auto --severity ERROR /workspace/target/src/ --sarif -o /workspace/exhaustion.sarif
kg_ingest_sarif("/workspace/exhaustion.sarif", "pattern-exhaustion")Run the search. For EACH hit:
kg_add_node("hypothesis", "Missing ownership check in DELETE /api/v2/unaccess",
props={"pattern": "missing_ownership_validation", "file": "api/routes.py",
"line": 87, "related_finding": "<original_finding_id>",
"key": "api/routes.py:handle_unaccess:missing_ownership"})Link to the original vulnerability:
kg_add_edge(new_hypothesis_id, original_vuln_id, "chains_to", weight=0.3)Not all instances are equal. Prioritize:
Feed each top candidate to the verifier with a separate positive and baseline
command. Persist the validate_workspace_finding result beside the candidate;
only a result with validated=true becomes a separate operational finding.
Stop the pattern search when:
Record the exhaustion state:
kg_add_node("hypothesis", "pattern exhaustion complete: missing_ownership",
props={"pattern": "missing_ownership_validation", "status": "exhausted",
"total_instances": 15, "confirmed": 4, "rejected": 11})After exhaustion, the graph should show:
VULNERABILITY (original finding)
← chains_to ← FINDING (variant 1)
← chains_to ← FINDING (variant 2)
← chains_to ← FINDING (variant 3)
← chains_to ← HYPOTHESIS (rejected variant, status=rejected)This makes it easy for the report generator to group related findings under a single root cause narrative.
0cf691e
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.