What Is Threat Modeling? A Practical Introduction
Threat modeling is a structured process for finding security weaknesses before code ships, by asking what could go wrong and how an attacker would exploit it.
Threat modeling is a structured process for identifying security weaknesses in a system before it’s built, by systematically asking what could go wrong, who would exploit it, and what the impact would be. Rather than waiting for a penetration test or a breach to reveal problems, threat modeling pushes that thinking to design time — when fixing a problem is a diagram edit, not a production incident.
Why do it before writing code
Security reviews that happen after a system is built find real bugs, but they’re expensive to act on: by the time a scanner or pentester finds a flaw, the architecture is already set, and fixing it might mean reworking a data flow or an entire auth model. Threat modeling front-loads that analysis. Done during design, it catches architectural mistakes — a service trusting a client-side check, a token with no expiry, an API that leaks internal IDs — before they’re baked into thousands of lines of code.
It’s not a replacement for later-stage security work like SAST and DAST scanning; it’s the layer that happens earlier and catches a different class of problem — design flaws rather than implementation bugs.
The core process
Most threat modeling follows a version of the same four questions:
- What are we building? Diagram the system — components, data flows, trust boundaries (where data crosses from a less-trusted zone to a more-trusted one, like the internet to your API). This is usually a simple data-flow diagram, not a full architecture document.
- What can go wrong? Systematically enumerate threats against each component and data flow. This is where a framework like STRIDE (below) earns its keep — it turns “think of everything bad” into a checklist.
- What are we going to do about it? For each credible threat, decide: mitigate it (add a control), accept it (the risk is low enough), transfer it (insurance, a third party), or eliminate it (remove the feature or component entirely).
- Did we do a good job? Review the model against the finished design or implementation, and repeat the process as the system evolves — threat modeling isn’t a one-time document, it’s revisited when the architecture changes meaningfully.
STRIDE: a framework for step 2
STRIDE is a mnemonic for six categories of threat, originally developed at Microsoft, that gives structure to “what can go wrong”:
| Category | Threat | Property violated |
|---|---|---|
| Spoofing | Pretending to be something or someone else | Authentication |
| Tampering | Modifying data or code without authorization | Integrity |
| Repudiation | Denying an action was performed | Non-repudiation |
| Information disclosure | Exposing information to unauthorized parties | Confidentiality |
| Denial of service | Degrading or denying service to legitimate users | Availability |
| Elevation of privilege | Gaining capabilities without authorization | Authorization |
Walking through each category against every component and trust boundary in a data-flow diagram is a mechanical, repeatable way to surface threats a free-form brainstorm would miss. A login endpoint, for instance, prompts questions like: can it be spoofed (credential stuffing)? Tampered with (parameter injection)? Does it leak information (username enumeration through timing or error messages, the same class of issue covered in timing attacks)?
Trust boundaries matter most
The highest-value part of a threat model is usually identifying trust boundaries — the points where data crosses from an environment you don’t control into one you do. A public API endpoint is a trust boundary between the internet and your backend. A call to a third-party service is a trust boundary in the other direction. Every trust boundary is a place where input should be validated and where the same-origin policy, CORS rules, or authentication checks need to be explicit rather than assumed.
Threat modeling vs related practices
Threat modeling is often confused with adjacent security activities, but each answers a different question:
- Threat modeling — what could go wrong in this design, before it’s built?
- SAST vs DAST — does the implemented code have known vulnerability patterns?
- Penetration testing — can a skilled attacker actually break the deployed system?
- Zero trust — an architectural principle (never trust, always verify) that threat modeling can help you apply consistently.
They’re complementary, not redundant. A mature security program runs all of them at different points in the lifecycle.
Getting started without overengineering it
Full STRIDE-per-component threat modeling on every feature is more process than most teams need. A lightweight version — a whiteboard session with a data-flow diagram and 30 minutes of “what could go wrong here” before building anything with a new trust boundary, a new auth flow, or sensitive data — captures most of the value. Save the more rigorous, formal exercise for systems where the blast radius of a mistake is large: payment processing, authentication infrastructure, anything handling regulated data.
The takeaway
Threat modeling asks what could go wrong before code makes that question expensive to answer. Diagram the system, identify trust boundaries, walk through threat categories like STRIDE for each one, and decide how to handle what you find — mitigate, accept, transfer, or eliminate. It’s cheapest and most valuable early, but the process is worth repeating whenever the architecture changes in a way that shifts where the trust boundaries are.
Keep reading
Takina · · 4 min read What Is a Lockfile? Reproducible Dependency Installs
A lockfile records the exact dependency versions your package manager resolved, so every install — from your laptop to CI — reproduces the same tree.
Chisato · · 5 min read IDS vs IPS: Intrusion Detection vs Prevention
An IDS watches network traffic and alerts on threats; an IPS sits inline and blocks them automatically. How the two compare and when to use each.
Takina · · 4 min read JavaScript Intl API: Formatting Dates and Numbers
The Intl API formats dates, numbers, and currency using a user's locale without a library. How Intl.DateTimeFormat and Intl.NumberFormat work.