Lesson 3 of 6 · 7 min read
Threat Modeling with Data-Flow Diagrams and STRIDE
In this lesson
TL;DR: A threat model answers four questions: what are we building, what can go wrong, what are we going to do about it, and did we do a good job? Answer the first with a data-flow diagram that marks every trust boundary. Answer the second by walking each element and each boundary-crossing flow through STRIDE. Answer the third with a decision per threat, not a generic control list. The deliverable is a short, specific list that engineers can act on and reviewers can check.
Before you read
Pick an answer before you read further. The lesson below explains it, and guessing first, right or wrong, helps the explanation stay with you.
1A team says it has threat-modeled its service because it ran a vulnerability scanner and fixed the findings. What is missing?
The four questions
Adam Shostack's four-question framework, now the common structure for threat modeling, keeps the exercise honest:
- What are we working on? A model of the system, usually a data-flow diagram.
- What can go wrong? Threats, found systematically rather than by inspiration.
- What are we going to do about it? A decision for each threat.
- Did we do a good enough job? A check that the model matched reality and the mitigations shipped. (The Threat Modeling Manifesto's wording says "good enough" on purpose: a model is never complete, only sufficient for the decision at hand.)
Teams that skip the first question produce threat lists that could apply to any system. Teams that skip the fourth produce documents nobody reads after the design review.
Drawing the data-flow diagram
A data-flow diagram uses five elements, and the vocabulary matters because STRIDE is applied per element:
| Element | What it is | Example |
|---|---|---|
| External entity | Something outside your control that sends or receives data | A user, a partner API, a model provider |
| Process | Code that transforms data | Your API service, a worker, an agent loop |
| Data store | Data at rest | A database, a bucket, a vector index, a log |
| Data flow | Data moving between elements | An HTTPS request, a queue message, a prompt |
| Trust boundary | A line where the level of trust changes | Internet to service, service to third party |
Keep the diagram at the level where trust changes. A diagram with forty boxes hides the three boundaries that matter; a diagram with three boxes and no boundaries tells you nothing. The trust boundaries lesson is the prerequisite here: every flow that crosses a boundary is where you will spend most of your time.
User
External entity
Upload API
Process
File store
Data store
Thumbnailer
Process
Also in the picture
Email provider
- External entity
Find the boundary crossings
Two flows cross trust boundaries: the upload from the internet and the share email to a third party. Start there.
STRIDE: six questions for every element
STRIDE was introduced at Microsoft by Loren Kohnfelder and Praerit Garg in 1999. Each letter is a threat category, and each category is the violation of a property from the security properties lesson:
| Threat | Violates | The question to ask | Typical mitigation |
|---|---|---|---|
| Spoofing | Authenticity | Can someone pretend to be another user, service or component? | Authentication, mutual TLS, signed tokens |
| Tampering | Integrity | Can data or code be changed in transit, at rest or in memory? | Signatures, MACs, write permissions |
| Repudiation | Non-repudiation | Can someone deny an action, and could we prove otherwise? | Tamper-evident audit logs tied to identity |
| Information disclosure | Confidentiality | Can data reach someone who should not read it? | Authorization, encryption, minimisation |
| Denial of service | Availability | Can someone exhaust or crash it? | Quotas, rate limits, timeouts, isolation |
| Elevation of privilege | Authorization | Can someone gain rights they were not granted? | Least privilege, sandboxing, input validation |
Not every category applies to every element. External entities are mainly spoofed; data stores are tampered with, disclosed and exhausted; processes are vulnerable to all six. This mapping is called STRIDE-per-element, and it keeps the walk-through fast. The table in the 2006 Microsoft article that published it is exact:
| Element | S | T | R | I | D | E |
|---|---|---|---|---|---|---|
| External interactor (rectangle) | yes | yes | ||||
| Process (circle) | yes | yes | yes | yes | yes | yes |
| Data store (parallel lines) | yes | yes | yes | |||
| Data flow (arrow) | yes | yes | yes |
Many teams also check repudiation for a data store that holds audit logs, because tampering with the log is how repudiation is achieved.
Worked example: how much work STRIDE-per-element creates
A diagram with 2 interactors, 3 processes, 2 data stores and 6 data flows produces:
| Element type | Count | Threats each | Checks |
|---|---|---|---|
| Interactors | 2 | 2 (S, R) | 4 |
| Processes | 3 | 6 | 18 |
| Data stores | 2 | 3 (T, I, D) | 6 |
| Data flows | 6 | 3 (T, I, D) | 18 |
| Total | 46 |
46 checks is manageable but not free. If only 3 of the 6 flows cross a trust boundary, starting with those 3 flows (9 checks) and the 2 processes at their ends (12 checks) covers the 21 highest-exposure checks first. The same article put it as effort reflecting exposure: spend it where data crosses boundaries.
Diagram
13 elements
Per-element STRIDE
46 checks
Boundary crossings
21 checks first
Findings
decision, owner, test
Why this order
Exposure
- 3 flows cross a boundary
- Their 2 endpoint processes
Threat trees
- Leading questions per element
- Found a replay threat the brainstorm missed
Enumerate systematically
The per-element table turns a diagram into a fixed list of questions, so nobody relies on inspiration.
Threat trees give the leading questions. Howard and Lipner's The Security Development Lifecycle (2006) included a threat tree per element type, whose leaves are concrete questions. One of them, whether a data flow is defended against replay, is the example the 2006 article uses: asking it surfaced a replay threat the team's brainstorm had missed. The fix in such cases is concrete: a per-request identifier the server refuses to accept twice, tested by submitting the same request twice and expecting a rejection.
STRIDE-per-interaction is the other common variant. Instead of single elements, it walks each (source, destination, flow) tuple that crosses a boundary and asks what each end assumes about the other. It finds composition threats, where two components that are each safe combine badly, which per-element analysis misses.
What a good threat model produces
The output is a list, and its quality is judged by specificity. Compare:
- Weak: "Attackers might access data. Mitigation: use encryption and access control."
- Strong: "A signed-in user can request
/files/{id}for another user's file because the API checks authentication, not ownership. Mitigation: the API loads the file's owner and compares it with the session user before returning it. Owner: storage team. Test: an automated case that requests another user's file and expects 403."
Each threat gets one of four decisions: mitigate it, accept it with a named owner and a reason, transfer it (insurance, a contract, a vendor's responsibility), or eliminate the feature that creates it. A threat with no decision is not finished.
The tools around the method
- The Elevation of Privilege card game, created by Adam Shostack at Microsoft in 2010 and released under a Creative Commons licence, deals STRIDE threats as cards so a team discusses one concrete threat at a time. It works well for teams new to threat modelling.
- The Microsoft Threat Modeling Tool generates STRIDE threats from a diagram and remains part of Microsoft's Security Development Lifecycle, whose practices include "perform security design review and threat modeling".
- The Threat Modeling Manifesto (November 2020), written by a working group of practitioners, sets out five values: a culture of finding and fixing design issues over checkbox compliance; people and collaboration over processes and tools; building understanding over time rather than taking a snapshot; doing threat modelling over talking about it; and continuous refinement over a single delivery.
When to do it
Threat model when a design is still cheap to change: at design review, before a new trust boundary is introduced, and whenever an existing boundary changes. Adding a model provider, giving an agent a new tool or opening an API to partners each changes the diagram. The Threat Modeling Manifesto (2020) values "continuous refinement over a single delivery", which in practice means a short model kept current beats a long one written once.
Misconceptions interviewers listen for
- "Apply all six letters to every box." The per-element table exists to stop that.
- "STRIDE is a complete list of threats." It is a prompt for finding them; composition and privacy threats need other passes.
- "The threat model is a document we finish." It is kept current as boundaries change.
- "A list of controls is a threat model." Without threats, decisions, owners and tests, it is a wish list.
- "Repudiation applies to data flows." In the standard table it applies to interactors and processes, plus stores holding audit logs.
What if · interview follow-ups
Hold your answer as the constraints change
Your team is threat modelling a new document-upload feature: browser, upload API, virus-scanning worker, object storage, metadata database and a third-party OCR service. The interviewer pushes on the method one step at a time.
Start here
What if the first diagram has 40 boxes and nobody can follow it?
What do the diagramming rules say about similar elements?
Collapse similar elements inside one trust boundary into one process or store, draw a context diagram showing only the system and its external entities, then break out the parts that cross boundaries. A diagram the team can hold in their heads produces better threats than a complete one nobody reads.
Carry it forwardDraw the diagram at the level where trust changes, not at the level of every service.
Weak answerAdding more detail to fix an unreadable diagram.
Constraint changes
What if the team has only one hour?
Which checks carry the most exposure?
Do the flows that cross trust boundaries and the processes at their ends: browser to upload API, worker to the OCR service, and anything that writes to storage from outside. Record explicitly what was not covered, so the fourth question, did we do a good enough job, has an honest answer and a follow-up.
Carry it forwardPrioritise by boundary crossing, and write down the scope you did not cover.
Weak answerRushing through all 46 checks superficially.
Constraint changes
What if the upload API and the scanning worker are each safe from spoofing on their own?
What does each assume about the other?
The composition can still fail: if the worker trusts that anything in the queue came from the API and the queue can be written by another service, a file can skip the API's checks. Walk the boundary-crossing interactions as source, destination and flow tuples and check each side's assumptions; authenticate queue messages or restrict who can publish to the queue.
Carry it forwardThreats often appear when safe components are joined; check assumptions per interaction.
Weak answerConcluding the system is safe because each component passed its own review.
Constraint changes
What if a finding is 'an attacker could replay an upload request to duplicate a payment'?
What makes a finding finished?
It needs a decision, an owner and a test: mitigate with a per-request idempotency key the server refuses to accept twice, owned by the payments team, tested by an automated case that submits the same request twice and expects a conflict response. A finding without those is a note, not a result.
Carry it forwardA threat model's output is decisions with owners and tests, not observations.
Weak answerWriting 'add replay protection' with no owner or test.
Constraint changes
What if the feature extracts personal data from the documents for search?
Which threats does STRIDE not ask about?
STRIDE covers security properties but not privacy harms such as linking records across contexts, identifying people from supposedly anonymous data, or keeping data longer than needed. Add a LINDDUN-style privacy pass for the extraction and search flows, and decide retention and minimisation as part of the same model.
Carry it forwardUse the threat method that matches the harm; privacy needs its own categories.
Weak answerAssuming STRIDE's information disclosure covers all privacy concerns.
Now defend it
As the defender, how do you know a threat model was good enough?
Its diagram matched the deployed system when diffed against infrastructure and service inventories; each mitigation shipped with a passing test; later pentest findings and incidents map to modelled threats, and any that do not are added to the team's checklist; and the model was updated when the next boundary changed.
How this shows up in interviews
Expect "walk me through how you'd threat-model X" in almost every security loop, and expect the interviewer to care more about your process than your list. Start by asking what the system does and who uses it, sketch the diagram aloud, name the boundaries, then take one boundary through STRIDE in detail rather than skimming all six letters for every box. Finish with decisions and owners. Candidates who recite STRIDE without a diagram score as having memorised an acronym.
Say it in 30 seconds: "I draw a data-flow diagram with external entities, processes, stores, flows and trust boundaries, then walk each element, starting with the flows that cross boundaries, through STRIDE: spoofing, tampering, repudiation, disclosure, denial of service and elevation of privilege. Each threat gets a specific mitigation with an owner and a test, or an explicit acceptance. I redo it whenever a boundary changes, like adding a model provider or giving an agent a new tool."
Check yourself
Say or write your answer first, then reveal. Explaining it from memory, in your own words, is the skill an interviewer is checking.
1Which STRIDE category is a prompt injection that makes an agent call a tool the user never asked for?
2Your threat model lists 'denial of service' for a public API with the mitigation 'use a CDN'. Why might a reviewer reject it?
3In STRIDE-per-element, which threats apply to a data flow and which to an external interactor?
4A diagram has 2 interactors, 3 processes, 2 stores and 6 flows. How many STRIDE-per-element checks is that?