Guide
Threat modeling explained
Harbor Commerce shipped a guest-checkout API in a Friday deploy. By Monday a security researcher reported that anyone who guessed an order UUID could fetch another customer's shipping label PDF — no session required. The team had run penetration tests on login flows and passed a SOC 2 checklist, but nobody had asked a simpler question during design: who is allowed to read this resource, and what happens when they are not? A two-hour threat modeling workshop on the checkout data flow would have surfaced the missing authorization check before code merged. Threat modeling is structured thinking about how your system can be abused — not a compliance checkbox, not a substitute for code review, but a design-time habit that maps assets, trust boundaries, and attacker goals so you fix architectural holes cheaply. This guide explains the core process, the STRIDE mnemonic, data flow diagrams, attack trees, a Harbor Commerce checkout workshop worked example, a methodology decision table, common pitfalls, and a production checklist. It complements CSRF and SSRF defenses and authentication vs authorization without replacing penetration testing or runtime monitoring.
What threat modeling is (and is not)
Threat modeling is a repeatable exercise where engineers, product owners, and security reviewers collaboratively answer four questions about a system or feature:
- What are we building? (scope and assets)
- What can go wrong? (threats and abuse cases)
- What are we going to do about it? (mitigations and acceptance)
- Did we do a good job? (validation, tests, residual risk)
The output is not a 200-page report. It is usually a diagram, a ranked list of threats with owners, and tracked mitigations tied to tickets. Good threat models are living documents — updated when architecture changes, not filed once at launch.
Threat modeling is not vulnerability scanning (that finds known bugs in running code), not a guarantee of safety (attackers invent new chains), and not only for large enterprises. A five-person team modeling a single webhook endpoint still catches authorization gaps that scanners miss.
Core artifacts: assets, boundaries, and data flows
Before naming threats, draw what you are protecting. Three artifacts anchor most workshops:
Assets
Anything worth stealing, tampering with, or denying access to: PII, payment tokens, API keys, admin actions, reputation, availability of checkout. Rank assets by impact if compromised — not every field in a JSON blob deserves equal attention.
Trust boundaries
A trust boundary is where data crosses from one security context to another: browser to API, API to database, worker to third-party webhook, VPC to internet. Threats concentrate at boundaries because assumptions about identity, encryption, and validation often change there. Draw boundaries as dashed lines on your diagram; every arrow crossing a line is a candidate threat surface.
Data flow diagrams (DFDs)
A simplified data flow diagram shows processes (your services), data stores (databases, caches), external entities (users, payment gateways), and labeled flows (HTTPS POST, queue message, SQL query). Keep DFDs at the right altitude: too detailed and the workshop drowns in microservice boxes; too vague and you miss the webhook that bypasses auth. Level 0 for the whole product, Level 1 per major feature is a practical split.
STRIDE: a structured threat checklist
Microsoft's STRIDE model assigns six threat categories to components and flows. For each element on your DFD, ask whether an attacker could achieve:
- Spoofing — pretend to be someone or something else (fake JWT, forged webhook sender, session fixation).
- Tampering — modify data in transit or at rest (parameter manipulation, unsigned webhooks, SQL injection).
- Repudiation — deny an action occurred (missing audit logs on refunds, unsigned admin commands).
- Information disclosure — leak data to unauthorized parties (IDOR on order IDs, verbose error messages, log PII).
- Denial of service — degrade availability (expensive queries, queue flooding, lock contention).
- Elevation of privilege — gain capabilities beyond intent (horizontal IDOR, role confusion, SSRF to internal admin APIs).
STRIDE is a brainstorming aid, not a scorecard. A single flow may have multiple categories; prioritize by likelihood and business impact after the brainstorm. Pair STRIDE with concrete abuse stories: “attacker replays captured webhook with modified amount” beats abstract “tampering risk on webhook flow.”
Attack trees (optional depth)
For high-value assets, an attack tree decomposes a goal (“steal customer PII”) into sub-goals (compromise DB credentials, exploit IDOR, phish support agent). Trees help estimate which paths are cheapest for attackers and which mitigations collapse whole branches (e.g., field-level encryption at rest removes the DB-credential branch for bulk exfiltration).
The workshop process (90 minutes that pays back)
A focused session beats a month-long document. A proven agenda:
- Scope (10 min) — one feature or service boundary; name assets and out-of-scope neighbors.
- Diagram (20 min) — whiteboard DFD with trust boundaries; facilitator draws, team corrects.
- STRIDE pass (30 min) — walk each box and arrow; capture threats on sticky notes or a shared doc.
- Rank and assign (20 min) — score impact x likelihood; top five become tickets with owners.
- Validate (10 min) — schedule retest after mitigations ship; note accepted residual risk with exec sign-off if needed.
Include someone who knows deployment reality (SRE), someone who owns the code, and a skeptical voice who asks “what if the attacker already has a valid session?” Security specialists facilitate; they should not be the only people who understand the model.
Worked example: Harbor Commerce guest checkout
Harbor Commerce added guest checkout: browser posts cart and
address to checkout-api, which creates an order in PostgreSQL,
charges via Stripe, and enqueues a fulfillment message. A webhook from the
label printer posts tracking numbers back to /webhooks/shipping.
Diagram highlights
- External entities: customer browser, Stripe, label printer SaaS.
- Processes:
checkout-api,fulfillment-worker. - Data stores:
orderstable, Redis session cache. - Trust boundaries: internet to API gateway, API to DB VPC, webhook ingress.
Threats surfaced (sample)
| Flow | STRIDE | Threat | Mitigation |
|---|---|---|---|
GET /orders/{id} |
Info disclosure / Elevation | UUID guessing exposes other guests' labels (the real Monday bug) | Require session or signed token bound to order; rate-limit lookups |
POST /webhooks/shipping |
Spoofing / Tampering | Attacker forges tracking updates | HMAC signature with rotated secret; reject replay via timestamp + nonce store |
| Browser to checkout-api | Tampering | Client modifies price_cents in JSON body |
Server recomputes price from catalog; never trust client totals |
| checkout-api to Stripe | Repudiation | Support cannot prove who authorized charge | Immutable audit log with request ID, IP, and Stripe payment intent ID |
| fulfillment-worker queue | DoS | Poison message retries exhaust workers | Dead-letter queue, circuit breaker, max retry budget per order |
The workshop produced five tickets before sprint end. The IDOR fix shipped in two days; webhook HMAC was already planned but got priority bumped. Total calendar cost: one meeting. Compare that to incident response, customer notification, and regulatory inquiry after a breach.
Methodology decision table
| Approach | Best for | Strengths | Limitations |
|---|---|---|---|
| STRIDE + DFD | Web apps, APIs, microservices | Fast, familiar to engineers, maps cleanly to OWASP categories | Less natural for privacy-only or physical-security focus |
| PASTA (Process for Attack Simulation) | Risk teams aligning threats to business impact | Seven-stage process ties technical threats to financial risk | Heavier; overkill for small features |
| LINDDUN | Privacy-heavy products (health, fintech PII) | Privacy threat categories beyond STRIDE | Not a full substitute for abuse-case security modeling |
| Attack trees | High-value single assets (root keys, treasury wallets) | Shows combined attack paths and mitigation leverage | Time-consuming if applied to every endpoint |
| OWASP Cornucopia / Elevation of Privilege card game | Training, junior teams, workshop icebreaker | Gamified STRIDE-like brainstorming | Needs skilled facilitator to produce actionable tickets |
Most product teams standardize on STRIDE + DFD for feature reviews and pull PASTA or attack trees for annual risk registers or regulated launches.
Common pitfalls
- Checkbox theater — model filed once, never updated after a major architecture pivot (monolith to microservices, new AI agent tool access).
- Threats without owners — a list of scary bullets in Confluence that never becomes a ticket.
- Wrong altitude — modeling every CSS file instead of the payment authorization boundary; or only “hackers” with no data flows.
- Ignoring insider and supply chain — compromised CI token publishing malicious artifacts is a design threat, not only an external hacker with a hoodie.
- Confusing threat model with pen test — modeling finds design flaws early; pen testing validates running code. You need both.
- Accepting risk silently — if a threat is deferred, document residual risk and who accepted it; avoids surprise audits.
- LLM and agent blind spots — new tool-calling surfaces (prompt injection, excessive tool scope) need their own STRIDE pass; see prompt injection for abuse patterns.
Production checklist
- Scope one feature or service with named assets and explicit out-of-scope items.
- Draw a DFD with trust boundaries; label protocols and authentication on each flow.
- Run STRIDE (or chosen framework) on every process, store, and boundary crossing.
- Write abuse stories in attacker language, not abstract category names.
- Rank threats; create owned tickets for top risks before merge or launch.
- Verify mitigations with tests (unit, integration, DAST) tied to threat IDs.
- Re-run the model after material architecture, auth, or data-classification changes.
- Store models where engineers actually look (repo
docs/security/, ADR links). - Pair design-time modeling with runtime controls: secrets management, zero trust, and alerting on authorization failures.
Key takeaways
- Threat modeling is design-time defense — cheapest before code ships.
- Diagrams beat imagination — trust boundaries reveal where auth and crypto must change.
- STRIDE structures brainstorming — spoofing through elevation covers most web abuse cases.
- Outputs must become tickets — unowned threats are decoration.
- Models decay — revisit when architecture or adversary landscape shifts.
Related reading
- CSRF and SSRF explained — request-forgery threats that STRIDE often surfaces at browser and server fetch boundaries
- SQL injection and XSS explained — classic tampering and information-disclosure bugs with concrete defenses
- Authentication vs authorization explained — spoofing and elevation threats at identity boundaries
- Secrets management explained — protecting keys and credentials identified as high-value assets