Leer en español · Lire en français · Auf Deutsch lesen
Section 8.2 of 8.8 · Intermediate · 22 min read
Threat modelling: STRIDE, attack trees and data-flow diagrams
Video lesson
5 min · narrated, with captionsListen only (audio)
Read the transcript
Threat modelling is how security principles become concrete design decisions. In this lesson you'll see how a team examines a design, finds what could go wrong, and decides what to do about it.
Before a family goes on holiday, someone usually walks round the house asking what could go wrong. Is the back door locked? Is the spare key under the flowerpot? Will the post pile up and show that nobody is home? Then they decide what to do about each one. Threat modelling is the same walk round a software design: draw how data moves, ask what an attacker could do at each step, and decide.
Adam Shostack, who led threat modelling work at Microsoft, reduces it to four questions. First, what are we working on? That means a model of the system, usually a diagram. Second, what can go wrong? You find threats systematically, not by guessing. Third, what are we going to do about it? Each threat gets a decision. Fourth, did we do a good enough job? You review the model and the follow up. Any method that answers these four questions is threat modelling.
The usual model is a data flow diagram. Rectangles are external entities, ellipses are processes, parallel lines are data stores, arrows are data flows, and dashed boxes are trust boundaries. This one shows a new checkout. The customer app is outside the platform's trust boundary. Flow one, the order and a token, crosses that boundary into the API gateway. Inside, the ordering service asks Pricing to price the basket, and writes the order to its database. A second, tightly restricted zone surrounds Payments and its database, which hold only payment tokens and references. Payments asks the payment provider to take the money, and the provider reports the result by webhook. Both flows cross a boundary, and attacks follow data across boundaries. And notice flow nine, along the bottom. Card details go from hosted fields in the app straight to the provider, so they never enter the platform at all.
To find threats, most teams use STRIDE, created at Microsoft in 1999. Each letter names a threat that violates one property. Spoofing violates authenticity, such as a rogue process pretending to be the ordering service. Tampering violates integrity: a client sends a changed basket total. Repudiation: someone denies an action, and nothing proves otherwise. Information disclosure violates confidentiality, such as addresses shown to the wrong couriers. Denial of service violates availability. And elevation of privilege violates authorisation. A practical way to use it is to walk through every element of the diagram, spending most attention on flows that cross trust boundaries.
Attack trees look from the attacker's side. The root is a goal: here, getting meals without paying. Each child is a way of reaching it. These three are alternatives, and any one will do: abuse vouchers, change the price, or pay with a stolen card. Paying with a stolen card needs both of its steps together. The attacker must buy card details and also pass the fraud checks, which is costly. But editing the total in the client request is trivial, if the server trusts it. The cheapest path decides the risk. So recomputing every price on the server is worth more than any amount of card fraud tuning.
Here's what came out of a ninety minute session on this checkout. A changed price is mitigated by recomputing every total on the server. A fake caller asking Payments for refunds is stopped with mutual TLS and workload identity. A forged payment succeeded webhook is stopped by checking the provider's signature and confirming the status. Guessing other customers' order numbers is stopped by an ownership check on every request. And card numbers are not mitigated at all. They're eliminated. The cheapest way to protect them is not to hold them.
Rate each threat by likelihood and impact on a simple scale. The written reason matters more than the number. Then every threat ends in one of four decisions: mitigate, eliminate, transfer to someone better placed, or accept. The most common failure is unrecorded acceptance: the threat was found, nobody fixed it, and nobody decided not to. Threat model at design time, when change is cheapest, and again whenever trust boundaries, sensitive data or authentication change.
The full section has the complete checkout threat table and common mistakes to avoid. Next, in Section eight point three, we look at identity and access: who is calling, and what may they do? See you there.
What you need to know
- Threat modelling answers Shostack's four questions: what are we working on, what can go wrong, what are we going to do about it, and did we do a good enough job.
- A data-flow diagram of external entities, processes, data stores, data flows and trust boundaries is the usual model; flows that cross trust boundaries deserve the most attention.
- STRIDE (Kohnfelder and Garg, Microsoft, 1999) names six threat categories, each violating one property: spoofing (authenticity), tampering (integrity), repudiation (non-repudiation), information disclosure (confidentiality), denial of service (availability) and elevation of privilege (authorisation).
- Attack trees (Schneier, 1999) model an attacker's goal as AND and OR nodes; the cheapest path through the tree shows where a mitigation matters most.
- Rate threats by likelihood and impact with written reasons; DREAD fell out of favour because its scores were subjective, and CVSS rates known vulnerabilities, not design threats.
- Every threat ends as mitigated, eliminated, transferred or explicitly accepted by someone with authority; threat-model at design time and again whenever trust boundaries, data or authentication change.
What threat modelling is
Threat modelling is the activity of examining a design to find what could go wrong with its security, and deciding what to do about it, before attackers or incidents find it for you. It is the main way security principles become concrete decisions, and the most direct answer to the OWASP category of insecure design: flaws that no amount of correct coding can fix because the needed control was never designed in.
Adam Shostack, who led threat modelling work at Microsoft and wrote the standard book on it, reduces the activity to four questions. What are we working on? (a model of the system, usually a diagram). What can go wrong? (threats, found systematically). What are we going to do about it? (mitigate, eliminate, transfer or accept each threat). Did we do a good enough job? (review the model, the threats and the follow-up). Any method that answers the four questions is threat modelling; the rest of this section describes the techniques most teams use to answer them.
In 2020 a group of practitioners, including Shostack, published the Threat Modeling Manifesto, modelled on the Agile Manifesto. It values a culture of finding and fixing design issues over checkbox compliance, people and collaboration over processes and tools, a journey of understanding over a one-off security snapshot, doing threat modelling over talking about it, and continuous refinement over a single delivery. Its point is that threat modelling is a habit of the team that builds the system, not a document produced by outsiders once a year.
Modelling the system: data-flow diagrams and trust boundaries
The first question needs a model of the system that shows where data goes and where trust changes. The traditional choice is a data-flow diagram (DFD) with five kinds of element: external entities (people or systems outside your control, drawn as rectangles), processes (code that you run, drawn as circles or ellipses), data stores (databases, files, queues and caches, drawn between two parallel lines), data flows (arrows showing data moving between the others) and trust boundaries (dashed lines or boxes where the level of trust changes).
DFDs suit threat modelling because attacks follow data: every flow that crosses a trust boundary is a place where an attacker can inject, intercept or replay something. A C4 container diagram from Chapter 4 is a good starting point; add the trust boundaries, make every arrow a data flow with a direction and a label, and include the stores and queues that container diagrams sometimes leave implicit. Keep the diagram at the level where threats are found: one diagram per significant feature or flow is more useful than one huge diagram of everything.
Finding threats with STRIDE
STRIDE was created at Microsoft in 1999 by Loren Kohnfelder and Praerit Garg as a mnemonic to help developers think about threats to their products. Each letter names a category of threat, and each category is the violation of one security property, which is what makes it useful: it is a systematic prompt, not a list of known attacks.
STRIDE and the property each threat violates
| Threat | Property violated | Food-delivery example | Typical mitigations |
|---|---|---|---|
| Spoofing | Authenticity | An attacker logs in as a customer with a stuffed password; a rogue process calls Payments pretending to be Orders. | Strong authentication (MFA, passkeys), rate limits, mutual TLS and workload identity between services. |
| Tampering | Integrity | A client sends a changed basket total; someone alters a payment webhook or a database row. | Server-side recomputation, signatures and MACs, TLS, least-privilege write access. |
| Repudiation | Non-repudiation (accountability) | A customer denies placing an order; a support agent denies issuing a refund, and nothing proves otherwise. | Audit logs tied to authenticated identities, timestamps, tamper-evident storage. |
| Information disclosure | Confidentiality | An API returns customers' addresses to couriers who are not delivering to them; error messages reveal internals. | Authorisation on every object, data minimisation, encryption, generic error messages. |
| Denial of service | Availability | Bots flood checkout during the evening peak; an expensive search query exhausts the database. | Rate limits and quotas, timeouts, bulkheads, autoscaling, query cost limits. |
| Elevation of privilege | Authorisation | A customer calls a restaurant-manager endpoint; injection lets an attacker run code as the service. | Deny-by-default authorisation, input validation, sandboxing, least privilege. |
A practical way to apply STRIDE is STRIDE per element: walk through every element of the DFD and ask only the questions that apply to its type. External entities can be spoofed and can repudiate; processes are exposed to all six categories; data stores to tampering, information disclosure and denial of service (and to repudiation when the store is a log); data flows to tampering, information disclosure and denial of service. Spending most attention on flows that cross trust boundaries keeps the exercise focused.
STRIDE finds threats; it does not rank them or choose mitigations. Its categories also overlap in practice (a spoofed identity usually leads to information disclosure or elevation of privilege), which does not matter: the goal is to find the threat, not to classify it perfectly. For privacy threats, such as linking or identifying people from data that looks harmless, the LINDDUN method from KU Leuven plays the role that STRIDE plays for security; it is discussed with privacy by design.
Attack trees
An attack tree, popularised by Bruce Schneier in a 1999 article in Dr. Dobb's Journal, looks at the system from the attacker's side. The root is a goal, such as getting meals without paying; each child is a way of reaching its parent. Children of an OR node are alternatives; all children of an AND node are needed together. Leaves can be annotated with properties such as cost, skill needed, or whether the step is possible at all, and those values propagate up the tree: the cost of an OR node is that of its cheapest child, the cost of an AND node the sum of its children.
Attack trees complement STRIDE well. STRIDE walks the design element by element and is good at coverage; an attack tree follows a motivated attacker and is good at showing which path is cheapest and therefore where a mitigation buys most. In the tree below, paying with a stolen card is relatively costly because it needs two things at once, while changing the price in the client request is trivial if the server trusts it. The cheapest path sets the risk, so recomputing every price on the server is worth more than any amount of card-fraud tuning.
Rating risk
A threat model typically finds more threats than a team can address at once, so each needs a rating. The usual approach is to judge likelihood (how easy, how attractive, how exposed) and impact (what is lost if it happens: money, personal data, availability, reputation, legal exposure) on simple scales such as low, medium and high, and to combine them in a matrix. The value of the rating lies less in the precision of the number than in a written reason that others can challenge. Organisations with mature risk management sometimes use quantitative methods such as FAIR (Factor Analysis of Information Risk) to express risk as a range of expected loss.
Two popular shortcuts are worth knowing because they are often misused. DREAD (damage, reproducibility, exploitability, affected users, discoverability), once used at Microsoft, scored each threat on five factors (often from 1 to 10) and averaged them. It fell out of favour, including at Microsoft, because different people scored the same threat very differently and the averaged number gave a false sense of precision; discoverability in particular rewards obscurity, which contradicts open design. CVSS, the Common Vulnerability Scoring System maintained by FIRST (version 4.0, 2023), is the right tool for a different job: rating the severity of a known vulnerability in a product, such as a flaw in a library. Its base score describes the vulnerability, not the risk of a design threat in your context, so it should not be used to rank the output of a threat model.
Every threat ends in one of four decisions: mitigate (add a control), eliminate (remove the feature or the data, often the best option), transfer (let someone better placed carry it, such as a payment provider holding card data) or accept (record that a person with the authority to do so has accepted the residual risk, and why). Unrecorded acceptance is the most common failure: the threat was found, nobody fixed it, and nobody decided not to.
Worked example
Worked example: threat-modelling the checkout
The food-delivery team is redesigning checkout so that customers can pay in the app with a card or a wallet. The architect runs a 90-minute session with the ordering and payments developers, a product owner and a security champion. The DFD below answers the first question, what are we working on. It shows two trust boundaries: the platform as a whole, and a narrower, tightly restricted payments zone (labelled PCI zone) around the payments service and its database, which hold payment tokens and references and talk to the payment provider; isolating them keeps the platform's PCI DSS scope small. Card details themselves (flow 9) go straight from hosted payment fields in the app to the payment provider and never enter the platform.
| 1. What are we working on? | The checkout DFD below: customer app, API gateway, Orders, Pricing, Payments, two databases and the payment provider, with two trust boundaries (the platform and the PCI zone) and nine numbered flows. |
|---|---|
| 2. What can go wrong? | STRIDE per element on every flow that crosses a boundary (1, 5, 6, 8 and 9) and on the order API, plus the attack tree for getting meals without paying shown earlier. |
| 3. What are we going to do about it? | Each threat is rated, given a decision (mitigate, eliminate, transfer or accept) and an owner; the most important are in the table below. |
| 4. Did we do a good enough job? | A review a month later compares the model with what was built and checks that every high risk was mitigated or accepted in writing. |
The cheapest way to protect card numbers is not to hold them: flow 9 keeps them out of the platform entirely, which removes threats rather than mitigating them.
Selected threats from the checkout threat model
| ID and where | STRIDE | Threat | Risk | Decision and mitigation |
|---|---|---|---|---|
| T1, flow 1 | S | Credential stuffing takes over accounts that have saved cards. | High | Mitigate: passkeys, or MFA on new devices; rate limits per account and IP; breached-password check. |
| T2, flows 1 and 2 | T | The client sends an altered price, discount or delivery fee. | High | Mitigate: Orders ignores client prices; Pricing recomputes from menus and vouchers; the payment is created for the server's total. |
| T3, flow 5 | S, E | Another internal service, or an attacker inside the network, asks Payments to authorise or refund arbitrary amounts. | High | Mitigate: mutual TLS with workload identity; Payments accepts authorisations only from Orders' identity, bound to an order ID and amount. |
| T4, flow 8 | S, T | A forged "payment succeeded" webhook marks an unpaid order as paid. | High | Mitigate: verify the provider's signature and timestamp; confirm status with the provider's API before releasing the order; process each event once. |
T5, GET /orders/{id} | I | Enumerating order IDs reveals other customers' addresses (broken object-level authorisation). | High | Mitigate: ownership check on every request; random identifiers as a secondary measure only. |
| T6, Orders DB | I | Order records with addresses leak from a backup or through an over-broad analytics account. | Medium | Mitigate: encryption at rest with KMS keys, least-privilege accounts, backups in a separate account. |
| T7, flow 1 | D | Bots exhaust checkout capacity at the evening peak. | Medium | Mitigate: rate limits and bot detection at the edge, reserved capacity for checkout, a waiting room if needed. |
| T8, Orders | R | A customer disputes placing an order and there is no evidence. | Low | Mitigate: audit event with user ID, device, time and order details, retained according to policy. |
| T9, flow 9 | I | Card numbers passing through the platform would bring every component into PCI DSS scope. | Design | Eliminate and transfer: hosted fields send card data directly to the provider; the platform stores only tokens and references. |
The answers to the last two questions are as important as the table. Each mitigation becomes a backlog item with an owner; T3 and T4 also become security scenarios with automated tests (a webhook with a bad signature must be rejected; a call to Payments from any identity other than Orders must fail). The two architectural decisions, hosted payment fields and mutual TLS between Orders and Payments, are recorded as ADRs. For the fourth question, the team reviews the model a month later against what was actually built, and the security champion checks that every high-risk item was either mitigated or explicitly accepted.
When and how often to threat-model
Threat modelling pays off most at design time, when changing a decision costs a whiteboard eraser. It should then be repeated whenever something significant changes: a new trust boundary or external integration, a new kind of sensitive data, a change to authentication or authorisation, a new deployment environment, or a move from a monolith to services. A sensible rule is to make "does this change the threat model?" a question in design reviews and in the template for architecture decision records, and to schedule a review of each system's model at least yearly and after every security incident.
The effort should be proportionate, in the spirit of the risk-driven approach in Chapter 1. A new microservice that processes payments deserves a half-day session with a full DFD; adding a field to a public menu needs five minutes and a STRIDE glance at the changed flow. Many teams keep their DFD as code next to the system (OWASP Threat Dragon and Microsoft's Threat Modeling Tool are free diagramming tools, and libraries such as OWASP pytm generate diagrams and candidate threats from code), so that the model is reviewed and updated with the system it describes.
Check your understanding
Which STRIDE categories apply to a data flow in STRIDE per element?
Tampering, information disclosure and denial of service: data in transit can be altered, read or blocked.
Why is CVSS the wrong tool for ranking threats found in a threat model?
CVSS scores the severity of a specific known vulnerability in a product; it does not account for your design, assets and context, so it does not measure the risk of a design-level threat.
In an attack tree, how is the cost of an AND node computed from its children, and why does that matter?
It is the sum of its children's costs, because all steps are needed. AND nodes are therefore usually costly paths, while the cheapest child of an OR node sets the risk.
What is the most common failure in the fourth step of threat modelling?
Threats that were found but neither fixed nor explicitly accepted: nobody owns them and nobody decided to live with them.
Sources and further reading
Have a question about this section? ArchitectBot, the course’s AI study assistant, answers from the course first.
Ask: “How would I run a first threat-modelling session for a new payments feature, and what should come out of it?”