| name | insecure-patterns |
| description | Use when the user asks which insecure coding patterns recur across the portfolio, wants findings grouped/ranked by CWE or OWASP ASVS category, asks "what are our top vulnerabilities by pattern", "which repos share CWE-X", or asks to (re)build the insecure-patterns dashboard. Walks every *-security-audit.json under analysis-results/findings/, keeps only source-code findings (drops YAML/Dockerfile/Helm config gaps), buckets by primary CWE mapped to ASVS 5.0, and writes insecure-patterns/{top25.md, detailed.md, dashboard.html, .json}. |
| argument-hint | [summary] [open] [<results-root-path>] |
| allowed-tools | ["Bash(python3:*)","Bash(ls:*)","Bash(open:*)","Read"] |
Insecure Coding Patterns — ASVS 5.0 roll-up
Aggregate every source-code security finding across the campaign into a ranked
table of recurring insecure coding patterns, categorised against the OWASP
ASVS 5.0 taxonomy, with example repo · file · function tuples and a
one/two-line root-cause fix per pattern.
Input
$ARGUMENTS is optional and may be any combination of:
| Token | Meaning |
|---|
| (none) | Default run — scan findings/, write all four outputs. |
summary | Also print the top-25 table to the conversation. |
open | Open the resulting dashboard in the default browser when done. |
<path> | Override the analysis-results root (directory containing findings/). |
Procedure
Step 1 — Locate the analysis-results root
Resolution order:
- A path passed in
$ARGUMENTS.
$AUDIT_RESULTS_ROOT environment variable.
../analysis-results relative to the ai-security-harness checkout (the normal sibling layout).
If none resolve, ask the user for the path.
Step 2 — Run the harness script
python3 harnessing/insecure-patterns/build_insecure_patterns.py \
--results-root <resolved-root> \
[--summary]
What the script does:
- Globs
findings/**/*-security-audit.json (recursive; ~5 k reports). When a
sibling *-findings-current.json (cumulative report from the
track-findings skill) exists, it is parsed instead of the audit by
default, so the false-positive drop honours human triage and machine
validation dispositions. The stats table reports how many reports carried
dispositions.
- For each finding, decides code vs config: kept iff ≥1
location.path
has a source-code extension (.go/.py/.ts/.js/.java/.c/.rs/…)
or ≥1 evidence.language is a source-code language. Findings whose only
artefacts are YAML/JSON/Dockerfile/Helm/TOML/Makefile are dropped as
config/manifest gaps.
- Drops findings with
validation_status: false_positive.
- Pattern key = primary CWE (
cwes[0], required by the report schema).
- De-duplicates occurrences by
(repo, cwe, path) so per-branch report
copies count once. Repo is metadata.repository normalised to owner/repo.
- Maps each CWE → OWASP ASVS 5.0 chapter/section via the curated
CWE_META table in the script (ASVS 5.0 dropped its own CWE column, so
this mapping is maintained in-harness). Unmapped tail CWEs land in
V15.3 Defensive Coding.
- Extracts a best-effort function/method name per occurrence from evidence
code (
func/def/function/fn regexes) → location description →
filename:lines fallback.
- Ranks patterns by distinct repository count, then occurrence count.
- Writes four artefacts under
<results-root>/insecure-patterns/.
Step 3 — Report back
Always tell the user:
- The four output paths (relative to the results root).
- Corpus stats: reports scanned, total findings, code findings kept,
config/manifest dropped, distinct patterns.
- The top-25 table (CWE · pattern · ASVS § · repos · occurrences).
If open was requested, open the dashboard:
open <results-root>/insecure-patterns/insecure-patterns-dashboard.html
Outputs
| File | Purpose |
|---|
insecure-patterns/insecure-patterns-top25.md | Ranked top-25 table + ASVS-chapter distribution + method note. |
insecure-patterns/insecure-patterns-detailed.md | Top-50: per-pattern ASVS ref, repo count, 6 example repo · file:lines · function tuples, co-tagged CWEs, and a 1-2 line root-cause fix. |
insecure-patterns/insecure-patterns-dashboard.html | Self-contained interactive dashboard: summary cards, ASVS-chapter bars, filterable top-50 table with expandable examples + inline fixes. |
insecure-patterns/insecure-patterns.json | Machine-readable roll-up: full ranked pattern list with all repos, examples, severity mix. |
Tuning
Edit constants at the top of build_insecure_patterns.py:
CODE_EXT / CODE_LANGS — what counts as source code
CONFIG_EXT — what marks a finding as config-only
CWE_META — CWE → (name, ASVS section, section name, root-cause fix). Add
entries here when a new CWE enters the top-50.
FUNC_PATTERNS — regexes that pull function names out of evidence blocks
Failure modes
| Symptom | Likely cause | Fix |
|---|
error: <root>/findings/ not found | Wrong --results-root | Pass the directory that contains findings/. |
| Top-N pattern shows a finding-title instead of a CWE name | CWE not in CWE_META | Add a curated entry (name + ASVS section + fix). |
Function column mostly file:lines | Evidence blocks don't include the definition line | Expected — the fallback is intentional. |
| A config-only finding leaked through | It also touched a .sh/.go helper | Tighten CODE_EXT or add the path to CONFIG_EXT. |