Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Use when starting an engagement, before exploitation, or whenever the attack surface changes — build/validate the threat model and detect drift (new unreviewed surface) before advancing
.claude/skills/hypnguyen1209-threat-model-discipline/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | -33% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 202% | 0% |
| case-04 | ✗→✓ | ▲ Improved | -38% | 0% |
| case-06 | ✗→✓ | ▲ Improved | -30% | 0% |
| case-08 | ✗→✓ | ▲ Improved | -28% | 0% |
You cannot test what you have not modeled. A threat model names the assets, entry points, trust boundaries, relevant ATT&CK techniques, and existing mitigations — so coverage is deliberate, not accidental. On a long engagement the surface drifts (a new endpoint, a new dependency); un-reviewed drift is where bugs hide. This skill keeps the model complete and re-checks it for drift.
/engage.gate — the gate refuses to advance on un-acknowledged drift.threat-model.json (see templates/threat-model/): five required lists — assets, entry_points, trust_boundaries, attck (technique ids), mitigations.
bash# 1. Lint - every required field present, no placeholders, valid ATT&CK ids python skills/threat-model-discipline/scripts/threatmodel_lint.py lint .engage/recon/threat-model.json # 2. Drift - diff a re-run against the reviewed baseline; NEW entry points/assets/boundaries are # unreviewed surface and BLOCK the gate until re-reviewed or acknowledged python skills/threat-model-discipline/scripts/threatmodel_lint.py drift \ .engage/recon/threat-model.baseline.json .engage/recon/threat-model.json
Or use /engage.threatmodel (materialize | lint | drift).
TBD/[fill in] — that is not a model; the lint fails it.entry_point appeared and you proceeded anyway — that is the exact gap attackers use.| Excuse | Reality | |--------|---------| | "The model is obvious, skip it" | Obvious to you ≠ documented. Coverage you can't diff is coverage you can't trust. | | "Drift is just noise" | A new entry point is new attack surface. Acknowledge it explicitly or re-review. | | "ATT&CK mapping is busywork" | It turns 'we tested stuff' into 'we covered these techniques' — the report's backbone. |
Pairs with scope-discipline (what you may touch) and finding-discipline (what counts as proven).
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 8,349 | 4,573 | -45% | 1 | 1 | 0% | 1,428 | 951 | -33% | 0 | 0 | — |
case-02 | fail→pass | 3,532 | 7,475 | +112% | 1 | 1 | 0% | 460 | 1,388 | +202% | 0 | 0 | — |
case-03 | fail→fail | 13,282 | 5,765 | -57% | 1 | 1 | 0% | 2,303 | 949 | -59% | 0 | 0 | — |
case-04 | fail→pass | 9,118 | 1,863 | -80% | 1 | 1 | 0% | 1,499 | 927 | -38% | 0 | 0 | — |
case-05 | pass→pass | 5,369 | 3,173 | -41% | 1 | 1 | 0% | 981 | 1,113 | +13% | 0 | 0 | — |
case-06 | fail→pass | 10,807 | 3,908 | -64% | 1 | 1 | 0% | 1,661 | 1,163 | -30% | 0 | 0 | — |
case-07 | pass→pass | 9,632 | 4,201 | -56% | 1 | 1 | 0% | 1,419 | 1,360 | -4% | 0 | 0 | — |
case-08 | fail→pass | 9,160 | 2,616 | -71% | 1 | 1 | 0% | 1,403 | 1,009 | -28% | 0 | 0 | — |
case-09 | fail→pass | 5,775 | 4,446 | -23% | 1 | 1 | 0% | 925 | 1,365 | +48% | 0 | 0 | — |
case-10 | fail→fail | 2,772 | 2,980 | +8% | 1 | 1 | 0% | 251 | 893 | +256% | 0 | 0 | — |
case-11 | fail→pass | 8,382 | 2,004 | -76% | 1 | 1 | 0% | 1,447 | 891 | -38% | 0 | 0 | — |
case-12 | fail→pass | 16,860 | 1,952 | -88% | 1 | 1 | 0% | 2,446 | 820 | -66% | 0 | 0 | — |
case-13 | fail→pass | 15,138 | 7,321 | -52% | 1 | 1 | 0% | 2,228 | 1,741 | -22% | 0 | 0 | — |
case-14 | fail→pass | 6,978 | 4,814 | -31% | 1 | 1 | 0% | 1,020 | 1,044 | +2% | 0 | 0 | — |
case-15 | fail→pass | 5,855 | 2,047 | -65% | 1 | 1 | 0% | 788 | 868 | +10% | 0 | 0 | — |
case-16 | fail→pass | 12,550 | 3,871 | -69% | 1 | 1 | 0% | 1,939 | 856 | -56% | 0 | 0 | — |
case-17 | fail→pass | 15,684 | 4,223 | -73% | 1 | 1 | 0% | 2,273 | 1,399 | -38% | 0 | 0 | — |
case-18 | pass→pass | 9,342 | 11,269 | +21% | 1 | 1 | 0% | 927 | 1,348 | +45% | 0 | 0 | — |
case-19 | fail→pass | 10,265 | 1,599 | -84% | 1 | 1 | 0% | 1,583 | 850 | -46% | 0 | 0 | — |
case-20 | pass→pass | 11,508 | 4,411 | -62% | 1 | 1 | 0% | 1,748 | 1,312 | -25% | 0 | 0 | — |
case-21 | pass→pass | 15,858 | 11,400 | -28% | 1 | 1 | 0% | 2,644 | 2,538 | -4% | 0 | 0 | — |
case-22 | pass→fail | 9,461 | 7,735 | -18% | 1 | 1 | 0% | 702 | 1,081 | +54% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +59 percentage points is the difference between those two pass rates over the 22 comparable cases. 2 cases got worse with the skill loaded, and they are included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.