
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.
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:
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.
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.
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.
Set-Cookie: sid=...; HttpOnly; Secure; SameSite=Strict).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.
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.
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.
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.