CtrlK
BlogDocsLog inGet started
Tessl Logo

pattern-exhaustion

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

Quality

85%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Passed

No findings from the security scan

SKILL.md
Quality
Evals
Security

Pattern Exhaustion

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:

  • Parse Server: 4 advisories from guard bypass patterns (prototype chain, falsy-value guard, protected-field bypass, complexity validator)
  • zrok: 3 advisories from access control (symlink traversal, broken ownership, reflected XSS in callback)
  • AVideo: 3 advisories from deployment config (SSRF, exposed installer, memcached session leak)

The Exhaustion Loop

1. Classify the root cause

After confirming a vulnerability, classify its root cause pattern:

Root CauseSearch Pattern
Missing auth/authz checkgrep -rn 'def handle_|router\.\(get|post|put|delete\)' | grep -v 'auth|permission|require|middleware'
Unvalidated path parametergrep -rn 'req\.params|request\.args|ctx\.params' | grep -v 'sanitize|validate|path\.resolve|path\.normalize'
SQL string interpolationgrep -rn 'f"SELECT|f"INSERT|f"UPDATE|query(.*\+.*|query(.*\$\{' --include='*.py' --include='*.ts' --include='*.js'
shell: true with user inputgrep -rn 'shell:\s*true|shell=True|os\.system|subprocess\.call.*shell' --include='*.py' --include='*.ts' --include='*.js'
Missing ownership validationgrep -rn 'delete|update|modify' --include='*.py' --include='*.ts' | grep -v 'owner|author|created_by|user_id.*=='
Default-open feature flaggrep -rn 'enabled.*=.*false|feature.*disabled|trust.*=.*true' --include='*.ts' --include='*.py'
Unsafe deserializationgrep -rn 'pickle\.loads|yaml\.load|yaml\.unsafe|unserialize|JSON\.parse.*reviver|eval(' --include='*.py' --include='*.js' --include='*.php'
Type confusion in guardgrep -rn 'typeof.*==|instanceof|is_array|Array\.isArray' --include='*.ts' --include='*.js' --include='*.php'
Missing CSRF/state checkgrep -rn 'state=|csrf|nonce' --include='*.py' --include='*.ts' | grep -v 'verify|validate|check'
Prototype pollutiongrep -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")

2. Enumerate all instances

Run the search. For EACH hit:

  1. Check: is this the SAME pattern as the confirmed vuln?
  2. Check: is there a mitigation the original instance lacked?
  3. Check: is this in test/fixture/example code? (reject if so)
  4. If potentially exploitable, create a HYPOTHESIS node:
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)

3. Prioritize by impact

Not all instances are equal. Prioritize:

  • Unauthenticated endpoints over authenticated ones
  • Write/delete operations over read-only
  • Production code paths over admin/debug routes
  • External-facing over internal-only

4. Verify each instance

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.

5. Exhaustion criteria

Stop the pattern search when:

  • All instances have been checked (grep returns no unchecked matches)
  • Remaining instances have proper mitigations in place
  • The pattern no longer applies (different framework version, different code path)
  • You've hit 10+ findings from the same pattern (diminishing returns on signal)

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})

Graph Structure

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.

Repository
PurpleAILAB/Decepticon
Last updated
First committed

Is this your skill?

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.