~ / foobarto.me / blog
--:--:-- UTC
~ / blog / 2026 / threat-model-nobody-reads.md

The threat model nobody reads

2026-04-20 · 11 min read · #threat-modeling

Every appsec engineer has a folder. Mine lives in a Confluence space; yours might be in a git repo, a shared drive, or the bottom of someone’s laptop. Inside are threat models. Maybe a dozen of them. Some are good. Some were good once. Most were last edited during the feature’s original design review and haven’t been opened since, unless somebody wanted to reference them in a compliance questionnaire.

This is the dirty secret of threat modeling. It’s universally acknowledged as the highest-leverage security activity a team can do — finding a design flaw on a whiteboard costs roughly a hundredth of what it costs to fix in production — and it’s universally underused. Not because people don’t know about STRIDE. Not because they don’t have Threat Dragon or the Microsoft tool or IriusRisk. They do the exercise once, get something valuable out of it, and then the thing rots.

There are two separate failure modes here, and they’ve been the same two failure modes for fifteen years. It’s worth pulling them apart before talking about what AI actually changes.

Problem one: the first draft is expensive and boring

A proper threat model for a non-trivial service takes somewhere between one and eight days of senior effort. That’s not a vendor statistic; that’s the range I’ve watched teams hit, and it matches the published numbers. You pull the architect, a senior dev, and someone from appsec into a room (or a call) for a few sessions. You draw the DFD. You walk every data flow through six STRIDE lenses. You write down a mitigation for each credible threat. You score them. You end up with a forty-page document.

The output is almost always useful. The process is almost always miserable. Developers tolerate it once, learn the shape of the questions you’ll ask, and quietly route around it the second time. The feedback loop is brutal: you spend two days in workshops, two days writing, and the team gets back a document with one hundred and forty threats in it, of which maybe twenty will ever materially change their design.

Nobody on the product side wakes up excited to threat-model. And — this is the part security people sometimes miss — they shouldn’t have to. The process as traditionally practiced is optimized for completeness, not for the developer’s time. That’s backwards. The scarce resource is the developer’s attention, not the threat catalog.

Problem two: day two

Assume you solve problem one. You get a beautiful threat model committed on day zero. What happens next?

The service adds a new upstream dependency. Two weeks later, someone swaps the auth library. A month after that, a queue gets introduced between two services that used to talk synchronously. A quarter in, there’s a new admin endpoint that bypasses the main API gateway because someone needed a quick internal tool. Each of these changes, on its own, is a small delta. Together, over six months, they turn the threat model into a document that describes a system that no longer exists.

Stale threat models are worse than no threat model, because they create false confidence. Auditors see the green checkmark. Engineers see a diagram that doesn’t match their mental model of the service and conclude the whole exercise is security theater. The model’s authority collapses the first time a developer catches it being wrong about something they know cold.

The “threat model as code” movement — keeping the model in YAML next to the application code, version-controlling it, regenerating diagrams from the source of truth — was a real and necessary step forward. It made threat models diffable. It put them in PRs. But it didn’t solve the problem. It turns out a YAML file that nobody updates rots exactly as fast as a Confluence page that nobody updates. Putting the model in git was necessary but not sufficient.

Where the agent actually helps

Here’s the part where most blog posts on this topic get breathless, so let me be boring about it. AI does not replace the security engineer’s judgment. A model that doesn’t understand your architecture will happily generate fifty plausible-sounding threats that don’t apply to your system, and an appsec engineer who ships that catalog to the dev team has just made everything worse.

But there are three specific places in the threat modeling lifecycle where an agent, used by someone who knows what they’re looking at, closes a gap that tooling has not been able to close before.

The first draft. Give an agent read access to a repository — the actual code, the IaC, the service dependencies, the existing architecture docs if any — and ask it to produce a STRIDE-ordered first pass. Not the final model. The strawman. What you get is not authoritative, but it’s a lot more grounded than a blank page at the start of a workshop. You walk into the session with a diagram that already matches the code, a list of trust boundaries the agent inferred from how services actually call each other, and forty candidate threats with proposed mitigations. Your job in the workshop shifts from “enumerate everything that could go wrong” to “confirm, correct, and prioritize.” That changes the developer experience completely. It also compresses a week of work into an afternoon. Not because the agent did the thinking — you still do the thinking — but because the mechanical parts of the exercise are no longer yours.

The delta review. This is the interesting one. Plug an agent into your PR workflow with the threat model checked into the repo and a simple rule: on every PR, compare the diff against the current model. Flag the ones that touch a trust boundary, introduce a new data flow, change an authentication path, or add an external dependency. For everything else, stay quiet. What you get is a bot that behaves the way a senior appsec engineer would if they had infinite time and read every PR in the organization. Ninety-five percent of PRs generate no comment. The five percent that do get a comment that looks like: this PR adds a new endpoint that accepts unauthenticated input from a partner network. The current threat model documents two entry points behind the gateway; this is a third. Relevant threats from the model: T-014 (auth bypass), T-022 (input validation on partner-trusted data). Consider updating §3.2. That is signal. That is what dev teams will actually read.

The drift check. Run the agent periodically against the live codebase and the threat model, and ask it to identify divergence. Not to generate a new model — to point at specific places where the model and the code disagree. The service talks to a Redis the model doesn’t know about. The gateway the model claims to protect two endpoints now protects five. The auth middleware has been rewritten and the assumptions the model makes about session handling no longer hold. These findings don’t auto-fix the model; they become tickets. The appsec engineer triages them during quarterly model review — which, incidentally, now takes a day instead of a week, because the divergence is pre-catalogued.

None of this is conceptually novel. All three of these things were theoretically possible with rule-based static analysis. The reason they never worked in practice is that the rules didn’t generalize across architectures, and maintaining them was a full-time job of its own. An agent reading code with context handles the generalization problem cheaply enough that the economics finally line up.

Skills as the encoding of your specific knowledge

The piece that makes this actually work in a real organization, rather than in a blog post, is the part where the agent knows your environment. Generic threat modeling advice is a commodity. What’s valuable is your org’s accumulated knowledge: the attack patterns that keep showing up in your sector, the shape of your standard mitigations, the things your compliance team actually cares about, the libraries you’ve blessed, the ones you’ve banned.

This is where the emerging skills pattern — a SKILL.md or equivalent that tells the agent how to do a specific task in your specific context — becomes genuinely useful for appsec work rather than being another vendor buzzword. Your threat-modeling skill is a living document in the same repo as the application. It encodes: the STRIDE-plus-your-additions checklist the team actually uses, the mitigation library with your approved controls, the threats that are explicitly out of scope because the platform handles them, the format you want the output in, the tone. When you iterate on your threat modeling practice — and you should, constantly — you edit the skill, and every subsequent run benefits. The skill is the place where institutional knowledge stops living in the appsec team’s heads and starts being applied at PR speed.

You can do similar things for pen-test scoping, for SOC2 evidence collection, for triaging SAST findings. The common pattern is the same: write down the thing your team has learned to do well, give it to the agent, and let the agent apply it consistently across surface area you could never cover by hand.

A handful of public examples already exist if you want to see what these look like in practice. tiffanymwr15/Threat-Model-Skill-for-Claude-Code is a small, focused skill that walks through framework selection, asset enumeration, and STRIDE/OWASP threat identification before producing a structured report — a good starting template if you want to see the shape of a single-purpose skill. fr33d3m0n/threat-modeling is more ambitious: an eight-phase workflow covering threat modeling, security testing, and compliance, with explicit CI/CD integration hooks. Trail of Bits has published a set of security-focused skills in the community awesome-agent-skills catalog — their differential-review skill in particular maps cleanly onto the PR-delta pattern I described above. For a broader library, mukul975/Anthropic-Cybersecurity-Skills collects several hundred cybersecurity skills mapped to MITRE ATT&CK, NIST CSF, D3FEND, and the NIST AI RMF — more than any one team will use, but a useful reference for how skills can be tagged and organized against existing security frameworks.

These are community efforts, quality varies, and treating any of them as turnkey is a mistake. Read them like you’d read any third-party security tool — as a starting point to fork and shape to your own environment, not as gospel. The real value shows up once a skill is specific to your codebase, your mitigation library, and your threat patterns. The open-source ones are there to steal patterns from.

Where this breaks

Some honest limits. The agent is not good at business-logic threats — the abuse cases that come from understanding what the product does, not just how it’s built. An agent can notice you’ve added an unauthenticated endpoint; it probably won’t notice that the combination of two authenticated endpoints lets a low-privilege user leak a high-privilege user’s data through a race condition in the feature spec. Those are still your job.

The agent is also, famously, confident when it shouldn’t be. If the model doesn’t understand the architecture, it generates threats that sound like threats. An appsec engineer who doesn’t read the output critically ends up shipping hallucinated risks to the dev team, which is the fastest way to destroy whatever goodwill the practice had built up. Rule of thumb: the threat catalog the agent produces is a draft for you, not for the developers. Developers see what you’ve reviewed and endorsed.

And finally: none of this removes the need for the workshop. The value of getting the architect, the dev, and the security person in a room for an hour is not that they’re collectively drawing a DFD. It’s that they’re arguing about what actually matters. The agent takes the drawing off the table so they can spend the hour on the argument. That’s the point.

The shape of the change

Threat modeling has always had the right idea. Find the design flaws before they become code. The problem was never the concept; it was that the cost of doing it well, and doing it continuously, exceeded what any team was willing to pay. Static DFDs rotted. Threat-model-as-code made them diffable but didn’t make them self-maintaining. Every serious attempt to close the gap ran into the same wall: producing and maintaining a good model is a judgment-heavy, full-time job per product surface, and nobody has that headcount.

What changes with agents is the unit economics of that judgment. The security engineer’s attention is still the scarce input. What’s different is how much surface area one hour of that attention can cover — because the drafting, the diffing, and the drift detection have stopped being the expensive part.

The threat model nobody reads isn’t doomed to stay that way. It just needs to stop being a document and start being a living artifact the system checks itself against. We finally have the tools to build that. The only question is whether the hands holding them know what they’re looking for.

You are holding it wrong →