Threat Modeling Is Just Asking βWhat Could Go Wrong, and Who Cares?β
Threat modeling has a reputation for being expensive consultant work involving 80-page documents and ceremonies that nobody reads. It doesn't have to be. The pragmatic version is a one-hour conversation per significant feature, captured in a diagram, with concrete mitigations in the next sprint. The framework matters less than the cadence.
- Security review is a checkbox at the end of a six-month project
- You've never drawn the trust boundaries of the feature you're building
- βWho's the attacker?β is met with shrugs in design reviews
- You shipped auth code without listing what could be tampered with or repudiated
Shostack's four questions are enough: What are we building? What can go wrong? What are we going to do about it? Did we do a good job? STRIDE and DREAD give those four questions a vocabulary.
Shostack's Four Questions
- What are we building? (diagram)
- What can go wrong? (threats)
- What are we going to do about it? (mitigations)
- Did we do a good job? (validation)
STRIDE β The Threat Categories
| Letter | Threat | Property violated | Example |
|---|---|---|---|
| S | Spoofing | Authentication | Forged JWT, stolen cookie |
| T | Tampering | Integrity | Modified request body, parameter pollution |
| R | Repudiation | Non-repudiation | No audit log, no signed receipt |
| I | Information Disclosure | Confidentiality | IDOR, verbose errors, side channels |
| D | Denial of Service | Availability | Unbounded queries, expensive endpoints, regex DoS |
| E | Elevation of Privilege | Authorization | Missing role check, prototype pollution to admin |
Data Flow Diagrams and Trust Boundaries
flowchart LR
B[Browser] -.->|TLS| LB[Load Balancer]
LB --> API[API gateway]
API --> APP[App service]
APP -->|VPC| DB[(Database)]
APP -->|public| LLM[LLM provider]
subgraph EXT[External / untrusted]
B
LLM
end
subgraph VPC[Trust boundary: VPC]
LB
API
APP
DB
end
Trust boundaries (the boxes) are where threats concentrate. Every arrow crossing a boundary needs to enforce authentication, validate inputs, and log what happened. The LLM provider being outside your trust boundary is why prompt injection and data exfiltration matter β once data leaves your VPC, you've lost it.
Walking STRIDE Through a Feature
Take a feature like βCustomer uploads a CSV and we run a background import.β In ten minutes:
Element: Upload endpoint
S: Could someone POST as another user? β JWT verify, scope to user
T: Could the CSV contents be tampered? β Signed pre-signed URL + checksum
R: Will we log who uploaded what? β Append audit row {who, hash, time}
I: Does the response leak file paths? β Return opaque ID only
D: Can someone DoS by uploading 10GB? β Size limit at gateway, virus scan
E: Can a CSV cell execute code anywhere? β Strict parser, no eval, no formulas (CSV injection)
Element: Background importer
S: Workload identity, not a shared key
T: Validate row schema before processing
R: Job-id audit trail per row outcome
I: Errors logged with row index, never row contents
D: Bounded concurrency; dead-letter on repeated failure
E: Importer runs with least-privilege DB role (no DDL)DREAD β A Quick Severity Score
DREAD lets you rank findings consistently. Score each 1β10 and average:
- Damage β how bad if exploited?
- Reproducibility β how easy to repeat?
- Exploitability β skill required?
- Affected users β how many?
- Discoverability β how findable?
DREAD is famously subjective. Use it for relative ranking inside a session, not for cross-team comparisons. Many teams have moved to CVSS-aligned scoring for those.
Attack Trees
For high-value targets (the payment flow, the secret manager itself), draw an attack tree. Root = goal. Children = OR/AND of intermediate steps. Leaves = concrete actions. Each path is a chain of mitigations to consider.
flowchart TB
G[Steal customer PII] --> A{OR}
A --> A1[Compromise DB]
A --> A2[Compromise app]
A --> A3[Compromise a vendor]
A1 --> A1a[Stolen DB creds]
A1 --> A1b[Privilege escalation in cloud]
A2 --> A2a[XSS β cookie theft]
A2 --> A2b[RCE via dep]
A3 --> A3a[OAuth scope abuse]
PASTA β When STRIDE Isn't Enough
PASTA (Process for Attack Simulation and Threat Analysis) is a 7-stage methodology that ties technical threats to business impact. It's heavyweight β used by financial and regulated industries where you need to demonstrate a risk-based approach to auditors. For most product teams, STRIDE + light DREAD + attack trees for crown jewels is enough.
Integrating into the SDLC
- Design reviews: every new service or significant feature gets a one-hour threat modeling session, captured in the design doc.
- Templates: a Threat Model section in the ADR/RFC template makes it the default, not an extra step.
- Living document: re-visit when the system materially changes (new trust boundary, new data category).
- Tooling: Microsoft TMT, OWASP Threat Dragon, IriusRisk. For text-first teams, threagile (YAML in repo) is excellent.
- Outcomes flow into the backlog with concrete tickets, owners, and due dates. A threat model with no tickets is a creative writing exercise.
Pitfalls
Trying to model everything
You don't need a threat model per CRUD endpoint. Model the trust boundaries and the crown jewels β the auth path, the payments path, the AI agent that can call tools, the admin surface. Everything else inherits the platform-level model.
Threat model as a deliverable, not a habit
A 60-page PDF that nobody reads is worse than a 1-page diagram with 6 action items. The output should be a small number of crisp tickets, not a document with sign-off ceremonies.
No security person in the room
Engineers know what they built; security knows what tends to go wrong. A 60-minute joint session early in design saves weeks of retrofitting later. If you don't have a security team, the senior-most engineer plays the role β Shostack's book or the OWASP cheat sheets are enough to drive the conversation.

