TMGoat
July 10, 2026 · View on GitHub
TMGoat is two things at once:
- a dojo for threat-modeling engineers — graded challenges with reference solutions, hints, and a skills path;
- a benchmark for threat-modeling tools — a scored harness with a published reference baseline.
This guide is the engineer's playbook. New to threat modeling? Start here, then open any fixture's README.md.
The method: Shostack's four questions
- What are we building? Read
inputs/. Identify components, data, and trust assumptions. Sketch a data-flow diagram (DFD) and mark the trust boundaries. - What can go wrong? Apply STRIDE (Spoofing, Tampering, Repudiation, Information disclosure, Denial of service, Elevation of privilege) to each element and each flow. Then go beyond the checklist: hunt authorization gaps, trust-boundary violations, business-logic flaws, and chained attack paths.
- What are we going to do about it? Propose a mitigation per threat; map it to a control/standard (NIST 800-53, PCI DSS, IEC 62443, …).
- Did we do a good job? Compare against
solution/after you attempt. Did you find the planted design threats? Did you avoid the documented false positives?
How to work a challenge
- Open the fixture's
README.md— scenario, your task, and how many planted threats to find. - Analyze
inputs/(diagrams, docs, code, IaC). The truth is in the code and IaC; the docs may be aspirational — and in adversarial fixtures they are deliberately wrong, so reconcile them. - Decompose → enumerate threats → propose mitigations.
- Stuck?
hints.mdgives three graduated nudges. - Score yourself (below), then read
result/threat-model.md(the reference) andsolution/threat-model.yaml(the answer key).
Scoring — humans and tools, same rule
Put your findings in a JSON list [{ "title": "...", "stride": ["T"], "target": "<component>" }] and run:
python harness/score.py --expected fixtures/<sector>/<tier>/solution/threat-model.yaml --findings your-findings.json
- Recall — of the planted design threats, how many you found (the headline metric).
- Precision — did you avoid noise and the documented false positives.
- Belts: Bronze = all planted found · Silver = + the chained/subtle threat · Gold = + mitigations mapped to standards + residual risk.
What's in each fixture
| File / folder | What it is |
|---|---|
README.md | the challenge brief + learning objectives |
inputs/ | what you analyze — diagrams/ docs/ code/ iac/ |
hints.md | three graduated hints |
solution/threat-model.yaml | the answer key (planted threats + mitigations + standards) — don't peek early |
result/ | the reference threat model (the model answer) + dfd.png + its score.json |
The one idea to internalize
Difficulty here is subtlety, not size. A 6-component app can hide a nastier flaw than a 30-component one. Tools (and juniors) that just run STRIDE on each box miss the race condition, the fail-open control, the over-trusted channel, the doc that lies about the code. Those design threats are where the points — and the real risk — live.