Threat Modeling Explained: STRIDE and Methodology
- ✓Threat modeling analyzes a system's design to find security flaws while they are still cheap to fix, ideally before code exists.
- ✓STRIDE gives you six threat categories, each the inverse of a security property: Spoofing breaks authentication, Tampering breaks integrity, and so on through Elevation of privilege.
- ✓You run STRIDE against a data flow diagram with explicit trust boundaries, walking every element and asking which of the six threats apply.
- ✓Attack trees decompose one attacker goal into AND/OR steps; STRIDE enumerates breadth, attack trees explore depth on the scary ones.
- ✓DREAD scoring fell out of favor for being subjective; teams now prioritize with CVSS or a risk matrix, and use tools like OWASP Threat Dragon to keep the model as code.
Imagine the design review for a new login service. Someone sketches a browser, an API, and a user database on a whiteboard, and the room nods. Now ask one question at each arrow: what stops an attacker from forging that session cookie, tampering with that request, or reading every row out of that database? That is threat modeling, and the flaw you catch on the whiteboard costs minutes. The same flaw caught after a breach can cost the company.
This guide runs STRIDE all the way through on that exact login-plus-API-plus-database system: a text data flow diagram, two trust boundaries, and one concrete threat and mitigation for every letter. Then it shows where attack trees, DREAD, and PASTA fit, and which tooling keeps the model alive. STRIDE was built at Microsoft and remains the most widely taught framework, so that is where we start.
What is threat modeling and what does STRIDE add?
Threat modeling is the structured analysis of a system's design to identify, categorize, and prioritize threats before they become real vulnerabilities. It 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 enough job. STRIDE is the answer to the second question, a checklist so you do not have to invent threats from a blank page.
It is a design-phase activity, which is the whole point. Where secure code review and dynamic testing find bugs in code that already exists, threat modeling catches architectural mistakes (a missing trust boundary, an over-trusted service, an authorization gap) when the fix is an edit to a diagram rather than a refactor. STRIDE supplies six categories, each the inverse of a property you want to hold:
- Spoofing breaks authentication: pretending to be another user or system.
- Tampering breaks integrity: modifying data in transit or at rest.
- Repudiation breaks non-repudiation: acting without a traceable record.
- Information disclosure breaks confidentiality: exposing data to the unauthorized.
- Denial of service breaks availability: making the system unusable.
- Elevation of privilege breaks authorization: gaining capabilities you should not have.
Point those six at each process, data store, data flow, and external entity in your diagram and "what could go wrong" becomes a finite, repeatable pass.
Trust boundaries are where every threat concentrates
A trust boundary is any line in your design where data crosses from a less-trusted zone into a more-trusted one, and it is where threats cluster because it is where assumptions about who is calling and what they may do get made or broken. Before you name a single threat, draw the data flow diagram and mark those boundaries, because the boundary is the map you run STRIDE against.
A data flow diagram uses a tiny vocabulary: external entities (users, third-party APIs), processes (your services), data stores (databases, queues, caches), and data flows (the arrows). Here is the login system drawn in text, with both trust boundaries marked explicitly:
TRUST BOUNDARY A: internet | application
|
[Browser] --(1) POST /login {user,pass}--> [Login API]
[Browser] <--(3) Set-Cookie: sid=...------- [Login API]
|
- - - - - - - - - - - - - - - - - - - -+- - - - - - - -
TRUST BOUNDARY B: application | data store
|
[Login API] --(2) SELECT * FROM users--> [User DB]Boundary A is the internet meeting your API (flows 1 and 3); boundary B is your API reaching the database (flow 2). Everything dangerous happens on those two lines, which is the same boundary thinking that drives API penetration testing, where each service-to-service call is a place trust can be abused.
A worked STRIDE pass on the login system
Walk the two trust boundaries above one STRIDE letter at a time, and the abstract framework turns into a concrete list of threats and fixes. Each item below pairs the threat with the config-level mitigation that actually closes it, not generic advice.
- Spoofing (boundary A): the login endpoint accepts credentials, so credential stuffing or a forged cookie lets an attacker become another user. Mitigate with MFA, rate limiting, and signed random session IDs (
Set-Cookie: sid=...; HttpOnly; Secure; SameSite=Strict). - Tampering (boundary A): flow 1 crosses the internet, so a machine-in-the-middle can alter the body. Mitigate with TLS everywhere and server-side validation; never trust a client-supplied role field.
- Repudiation: a successful or failed login with no record cannot be traced. Mitigate with tamper-evident, append-only logging of every auth event including source IP and outcome.
- Information disclosure (boundary B): a verbose error ("user not found" vs "bad password") leaks valid usernames, and a raw SQL error leaks schema. Mitigate with a single generic auth-failure message and parameterized queries, which ties straight back to secure code review at the sink.
- Denial of service (boundary A): an unauthenticated path running an expensive password hash with no rate limit exhausts CPU. Mitigate with per-IP and per-account rate limits and a tuned work-factor budget.
- Elevation of privilege (boundary B): if the session token encodes a role the client can edit, a normal user becomes admin. Mitigate by deriving authorization server-side from the verified identity, never from the token payload.
On a recent design review of a healthcare scheduling platform, this exact one-page pass on the login flow surfaced an EoP issue nobody had noticed: the API trusted a tenant_id in the JWT body that the client could re-sign, letting any clinic read another clinic's patient schedule. The fix was a one-line server-side lookup, made before a single endpoint shipped. That is the entire payoff of modeling at boundary B early.
How do attack trees go deeper than STRIDE?
STRIDE gives you breadth, one threat per category per element; an attack tree gives you depth on a single goal you care about. You put the attacker's objective at the root and decompose it into the alternatives (OR) and prerequisites (AND) needed to reach it. Here is the tree for taking over an account in the login system above:
GOAL: take over a user account
OR
+-- 1. Steal the session cookie
| OR +-- 1a. XSS to read document.cookie
| +-- 1b. Network sniff (mitigated by TLS)
+-- 2. Defeat the credentials
| OR +-- 2a. Credential stuffing (mitigated: rate limit + MFA)
| +-- 2b. Abuse password-reset token reuse
+-- 3. Forge the session token directly
AND +-- 3a. Recover the signing key
+-- 3b. Mint a token for the victim userThe tree makes mitigations visible as cut branches: TLS kills 1b, MFA and rate limiting kill 2a, and a properly protected signing key makes the entire branch 3 require an AND of two hard steps. Read it and you immediately see that branch 2b (reset-token reuse) is the cheapest unmitigated path, so that is where the next control should go. STRIDE would have listed "Spoofing" once; the tree tells you which spoofing path to fix first.
How does STRIDE compare to DREAD and PASTA?
STRIDE identifies and categorizes; DREAD and PASTA mostly help you rate and align threats to business risk. They are complementary, and the common pattern is to enumerate with STRIDE, explore with attack trees, and prioritize with something better than DREAD.
DREAD (Damage, Reproducibility, Exploitability, Affected users, Discoverability) was the original way to score STRIDE findings, and it has rightly fallen out of favor. The problem is consistency: two assessors rating the same threat routinely disagree by several points because the criteria are subjective and the math has no calibration, so the resulting "score" gives false precision. Most teams now prioritize with CVSS, which at least has a defined vector, or a simple high/medium/low risk matrix tied to real impact. PASTA (Process for Attack Simulation and Threat Analysis) goes the other direction: a heavier seven-stage, risk-centric methodology that starts from business objectives and ties every technical threat back to business impact, suited to formal programs that need that traceability. The biggest mistake across all of them is modeling too late, treating it as a sign-off ritual after the architecture is frozen, when the entire payoff is catching the flaw while it is still a diagram edit.
When should you model, and with which tools?
Model during design, and re-model the part that changes whenever the architecture shifts meaningfully. You do not re-model the whole system every sprint; you model the new feature that introduces a trust boundary, the new data store holding sensitive data, the change to authentication, or the new third-party integration. Attaching a lightweight threat-model review to design docs keeps the practice continuous, the same philosophy behind continuous, agentic pentesting on the testing side, and it pairs with framework knowledge from the OWASP Web Security Testing Guide.
For tooling, pick based on how much process you want. OWASP Threat Dragon is free and open source, runs in the browser or desktop, lets you draw the DFD and attach STRIDE threats per element, and stores the model as JSON in your repo so it versions alongside code, the best default for most teams. The Microsoft Threat Modeling Tool is free, Windows-based, and auto-generates STRIDE threats from your diagram via a built-in template, strong for Microsoft-heavy stacks. IriusRisk is commercial and built to scale modeling across an organization with rule-based automation, control libraries, and Jira and CI integrations. Whatever you choose, the output should be a living artifact tied to the design process, not a PDF that is stale the day after the meeting.
