Limitations & methodology
July 10, 2026 · View on GitHub
TMGoat is useful, not perfect. In the spirit of an honest benchmark, here is what it does not claim and where the sharp edges are. If you're evaluating TMGoat critically, start here — we'd rather tell you than have you find out.
Ground truth is expert-authored, not universal
Each fixture's answer key (solution/threat-model.yaml) is a curated reference model, not an absolute
truth. Threat modeling is judgment work: reasonable experts disagree on what counts as a distinct threat,
what's in scope, and what severity applies. We mark the planted design flaws we deliberately built in,
and separate acceptable_threats (legitimate findings we won't penalize) from false_positive_guidance
(claims the inputs actually refute). A tool can surface a real threat we didn't enumerate — that's a gap in
the key, not necessarily a tool error. Treat recall against planted threats as the primary signal.
The corpus is synthetic
Fixtures are hand-built teaching artifacts, not scraped from real companies. They are deliberately smaller
and more internally consistent than real systems, and they follow a regular file layout. This makes them
learnable and scoreable — but a tool that does well here has proven it can reason over clean, bounded
inputs, not that it survives a messy 200-service estate with contradictory tribal knowledge. The
adversarial fixtures (docs that lie vs. code that tells the truth) are our attempt to inject real-world
mess; most fixtures are cleaner than production.
The bundled scorer is deliberately simple
harness/score.py's default matcher is lexical (concept-overlap + STRIDE), tuned to credit clear matches
and reject category-only coincidences. It is reproducible and free, but it is blunt: it can over-credit
findings that share vocabulary with the reference and under-credit findings phrased differently. An optional
LLM judge gives higher fidelity but is non-deterministic and depends on an external model. For any
published comparison, state which matcher you used. Don't read three-significant-figure precision into
either.
Difficulty labels are designed, not empirically calibrated
The three axes (architectural_complexity, threat_subtlety, input_completeness) are authored tags. We
believe "difficult" fixtures are subtler, but we have not run a large human/tool study to prove the tiers
are monotonic. Use the axes as descriptions of intent, not validated difficulty scores.
Coverage is intentionally bounded
The corpus centers on cloud/web/microservice architectures analyzed through a STRIDE lens, with compliance framings (PCI, HIPAA, PSD2, SOC 2, …) as mapping targets. It is thin on: privacy-specific modeling (LINDDUN), AI/ML and agentic-system threats, deep supply-chain scenarios, mobile, and true embedded/firmware. Sectors are tags for sourcing diverse architectures, not the variable under test — the real axes are intake-type × difficulty. Contributions that widen coverage are very welcome (see CONTRIBUTING.md).
Contamination & why some answers are held out
Public answer keys next to public inputs get ingested by tools and models over time, which erodes a benchmark's meaning (Goodhart's law). To keep scores honest, the corpus is split:
- Practice / dojo tier (easy + moderate): full solutions published, so you can learn and self-check.
- Held-out benchmark tier (the difficult fixtures): inputs are public, answer keys are not — they
live in a private vault, and scoring happens through a submission flow (see
benchmark/README.md). No tool — including the maintainers' — is scored against answers it could have seen.
Even so, once inputs are public they can be memorized. We version the corpus and may rotate held-out fixtures over time; cite the corpus version with any result.
Conflict of interest, stated plainly
TMGoat is built by Virantis, which also builds a commercial threat-modeling product. The benchmark is open (Apache-2.0), the ground truth is inspectable for the practice tier, and the held-out tier is scored by a fixed harness rather than by us. We would rather compete on an open yardstick than a private one — but you should weigh the source, and we encourage independent fixtures and independent scoring.