Threat modelling in an hour rather than a quarter
Do not model the system. Whole-estate threat modelling is the reason most organisations have one beautiful diagram from three years ago and no habit, because the exercise is large enough to require a project and projects end. The version that survives is one feature, one hour, five people and a whiteboard, repeated whenever a trust boundary changes. The output is a short list of decisions and tests, and it is worth more than a complete diagram nobody updates.
Why do threat modelling programmes stall?
Because they are scoped to the architecture rather than to a change. A model of the entire system is out of date the week after it is drawn, requires someone to own it, and produces findings too abstract to assign. Teams respond rationally by treating it as a documentation task, which means it gets done once, during a compliance push, by someone who was not going to build the thing.
The second cause is tooling. Buying a threat modelling product converts a thinking exercise into a data entry exercise, and the reports it generates are generic because the inputs were generic. There is a place for a repository of decisions, which is different from a place that generates threats from a template.
The third is the wrong people. A session run by security, for security, produces threats the engineers do not believe and controls they will route around. The session has to be run for the engineer who is about to write the code, and its success criterion is that they leave with a different implementation plan than they arrived with. If nothing about the plan changed, the hour was theatre.
What is the smallest useful threat model?
One diagram of one feature, showing where data crosses a trust boundary, plus a list of what an attacker would want. That is genuinely enough to find the majority of design-level problems, because design-level problems are almost always about a boundary: input arriving from somewhere less trusted, a privilege being granted, a service assuming another service has already checked something.
Draw processes as boxes, data stores as a distinct shape, flows as arrows, and boundaries as dashed lines cutting across the arrows. The boundaries are the only part that requires thought. A browser and your server are on opposite sides of one. Two of your own services are on opposite sides if either can be reached without the other's authorisation. A container and its host are on opposite sides. A tenant and another tenant are on opposite sides even though they share every line of code.
The test for whether the diagram is finished is whether every arrow crossing a dashed line has an answer to two questions: who is the caller, and what proves it. If any crossing has no answer, stop drawing and discuss that, because you have already found the most important thing the session will produce.
What does the hour actually look like?
Ten minutes drawing, five minutes listing what an attacker wants, twenty-five minutes walking the boundary crossings, ten minutes deciding, ten minutes writing it down. Fixed, visible on the wall, and enforced by whoever is facilitating, because the failure mode of a good session is spending fifty minutes on the diagram.
The attacker-wants list is short and specific to your product: other tenants' data, a free upgrade, someone else's session, the ability to send mail from your domain, the cloud credentials on the build agent, or simply the service being unavailable during a competitor's launch. Naming these in the room stops the discussion drifting into generic threats, and it is where domain knowledge earns its seat.
Then walk crossings one at a time and ask the prompts. Each crossing takes three to five minutes. Write threats as a sentence with an actor and an outcome: "a logged-in customer changes the account identifier in this request and reads another customer's invoices." Anything phrased as a category rather than a sentence is not actionable and should be rewritten or dropped.
How do you use STRIDE without turning it into a checklist?
Use it as six prompts applied to a specific arrow, never as a form to complete for the system. The value is that it interrupts the natural tendency to think only about the threat you already worried about, and the column that matters most is the last one, because each of these controls has a standard way of being implemented and quietly not working.
| Prompt | Question for this flow | Usual control | How the control fails |
|---|---|---|---|
| Spoofing | Could the caller claim to be someone else? | Authentication with a verified token | Token accepted without checking audience or issuer |
| Tampering | Could the data or the code be altered in transit or at rest? | Transport security, signatures, digests | Signature verified but the identity in it never checked |
| Repudiation | Could someone deny having done this? | Append-only audit log with actor and time | Log written by the same service that can rewrite it |
| Information disclosure | What does the response reveal beyond what was asked? | Field-level filtering by caller | Serialising the whole entity, then hiding fields in the UI |
| Denial of service | What is the most expensive request a stranger can make? | Rate limits, quotas, timeouts, bounded queries | Limit applied per address, not per account or per tenant |
| Elevation of privilege | Could this grant more than it should? | Authorisation at the object level, deny by default | Role checked at the route, ownership never checked at the record |
What is the output, and where does it live?
Three lists in the feature's own documentation, next to the code rather than in a security repository. First, threats accepted with a reason, which is the most valuable and most often omitted. Second, threats mitigated, each pointing at a specific ticket or a specific test. Third, assumptions, phrased so they can later be found false: "we assume this endpoint is only reachable from inside the cluster."
The assumptions list is what gives the exercise a second life. Assumptions are the part that goes stale, and they go stale silently. A network policy loosened a year later invalidates one line, and if that line is written down somewhere greppable, somebody has a chance of noticing. If it only ever existed in a conversation, nobody does.
Turn mitigations into tests wherever the threat is testable, and most authorisation threats are. A test that requests another tenant's record with a valid session and asserts a not-found response is three lines and it prevents the regression permanently. That conversion, from threat to executable assertion, is the difference between a model that decays and a model that hardens.
When is an hour not enough?
When you are designing a protocol rather than using one. Anything involving custom cryptography, a novel authentication or delegation flow, a signing or key management scheme, or a shared multi-tenant data path where isolation is enforced by application code rather than by separate stores. These deserve days, a written design and outside review, and the honest signal is that the hour session produced more open questions than decisions.
It is also not enough when the feature crosses an organisational boundary, because the interesting threats are then about what the other party will and will not commit to. Those sessions need the contract in the room, and the useful output is a list of questions for the counterparty rather than a list of controls for you.
For everything else, an hour per feature at design time is the highest return security activity available, and the way to prove it internally is retrospective. Take your last two security incidents or penetration test findings, and ask whether the one-hour session described here would have surfaced them. The answer is usually yes for at least one, which is a more persuasive business case than any framework.
Common questions
- How long should a threat modelling session take?
- An hour, scoped to one feature rather than the system. Ten minutes drawing the flow, five listing what an attacker wants, twenty-five walking each trust boundary crossing, ten deciding, and ten writing it down. Whole-system models require a project, go stale immediately and produce findings too abstract to assign, which is why organisations that attempt them end up with one diagram and no habit.
- What is a trust boundary in threat modelling?
- Any line across which data moves between differently trusted contexts. A browser and your server sit across one. Two of your own services sit across one if either can be reached without the other's authorisation. A container and its host sit across one. Two tenants of the same application sit across one even though they share every line of code. Boundaries are where design-level vulnerabilities cluster.
- Is STRIDE still useful?
- Yes, as six prompts applied to a specific data flow, not as a form filled in for a whole system. Its value is interrupting the tendency to consider only the threat you already had in mind. Used as a checklist over an architecture diagram it generates generic output, because the inputs were generic and no single flow was examined closely enough to produce a sentence with an actor in it.
- Who should be in a threat modelling session?
- The engineer who will write the code, someone who knows the domain well enough to name what an attacker would want, and someone who has handled incidents. Four or five people at most. A session run by security for security produces threats the engineers do not believe. The success criterion is that the builder leaves with a different implementation plan than they arrived with.
- What should a threat model produce?
- Three lists kept next to the code: threats accepted with a reason, threats mitigated with a link to a ticket or a test, and assumptions phrased so they can later be found false. The assumptions list matters most over time, because assumptions go stale silently. Convert testable threats into tests, since an assertion that another tenant's record returns not-found prevents the regression permanently.
- When do you need more than a one-hour threat model?
- When you are designing a mechanism rather than using one: custom cryptography, a novel authentication or delegation flow, key management, or multi-tenant isolation enforced by application code rather than separate data stores. The signal is that the hour produced more open questions than decisions. Features crossing an organisational boundary also need more, because the real threats concern what the counterparty will commit to.