$npx -y skills add hypnguyen1209/offensive-claude --skill threat-model-disciplineUse 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
| 1 | # Threat-Model Discipline |
| 2 | |
| 3 | ## Overview |
| 4 | |
| 5 | **You cannot test what you have not modeled.** A threat model names the assets, entry points, trust |
| 6 | boundaries, relevant ATT&CK techniques, and existing mitigations — so coverage is deliberate, not |
| 7 | accidental. On a long engagement the surface drifts (a new endpoint, a new dependency); **un-reviewed |
| 8 | drift is where bugs hide.** This skill keeps the model complete and re-checks it for drift. |
| 9 | |
| 10 | ## When to Activate |
| 11 | |
| 12 | - At engagement start (after recon-osint), before weaponize/exploit. |
| 13 | - Whenever recon is re-run or the target changes — to catch new attack surface. |
| 14 | - At `/engage.gate` — the gate refuses to advance on un-acknowledged drift. |
| 15 | |
| 16 | ## The model (JSON, materialized from recon) |
| 17 | |
| 18 | `threat-model.json` (see `templates/threat-model/`): five required lists — |
| 19 | `assets`, `entry_points`, `trust_boundaries`, `attck` (technique ids), `mitigations`. |
| 20 | |
| 21 | ```bash |
| 22 | # 1. Lint - every required field present, no placeholders, valid ATT&CK ids |
| 23 | python skills/threat-model-discipline/scripts/threatmodel_lint.py lint .engage/recon/threat-model.json |
| 24 | |
| 25 | # 2. Drift - diff a re-run against the reviewed baseline; NEW entry points/assets/boundaries are |
| 26 | # unreviewed surface and BLOCK the gate until re-reviewed or acknowledged |
| 27 | python skills/threat-model-discipline/scripts/threatmodel_lint.py drift \ |
| 28 | .engage/recon/threat-model.baseline.json .engage/recon/threat-model.json |
| 29 | ``` |
| 30 | |
| 31 | Or use `/engage.threatmodel` (materialize | lint | drift). |
| 32 | |
| 33 | ## Red Flags — STOP |
| 34 | |
| 35 | - "We'll model it as we go" — unmodeled surface = untested surface. Model first. |
| 36 | - "Recon changed but the threat model didn't" — re-run drift; new surface must be re-reviewed. |
| 37 | - A threat model full of `TBD`/`[fill in]` — that is not a model; the lint fails it. |
| 38 | - A new `entry_point` appeared and you proceeded anyway — that is the exact gap attackers use. |
| 39 | |
| 40 | ## Rationalizations |
| 41 | |
| 42 | | Excuse | Reality | |
| 43 | |--------|---------| |
| 44 | | "The model is obvious, skip it" | Obvious to you ≠ documented. Coverage you can't diff is coverage you can't trust. | |
| 45 | | "Drift is just noise" | A new entry point is new attack surface. Acknowledge it explicitly or re-review. | |
| 46 | | "ATT&CK mapping is busywork" | It turns 'we tested stuff' into 'we covered these techniques' — the report's backbone. | |
| 47 | |
| 48 | Pairs with `scope-discipline` (what you may touch) and `finding-discipline` (what counts as proven). |