# Threat Model: [System or feature name]

> STRIDE threat model for a system, service or feature. It records the
> scope, the assumptions, a data flow diagram with trust boundaries, the
> assets and entry points, threats enumerated per element with the STRIDE
> categories (Spoofing, Tampering, Repudiation, Information disclosure,
> Denial of service, Elevation of privilege), a risk rating, mitigations
> mapped to threats, validation evidence and residual risk acceptance.
> Replace every `[bracketed]` value and every row marked *Example*.

<!--
Guidance: How to use this template
- Model early (design phase) and update on every significant change. A threat
  model written after launch mostly documents regret.
- Draw the data flow diagram first. Threats are found per element and per flow
  that crosses a trust boundary; without the diagram the enumeration is guesswork.
- Work as a group: one developer who knows the code, one security reviewer, one
  person who knows operations. Timebox sessions to 60-90 minutes.
- Every threat ends in one of four states: mitigated, transferred, accepted (with
  a named owner and expiry) or not applicable (with a reason). "Open" is a work
  state, not an end state.
- For a full security architecture, use security/security-architecture; this
  template is the per-system working model.
-->

## Document control

<!-- Guidance: Identify the model, the version of the system it describes, and who owns it. A model is only valid for the system version named here. -->

| Field | Value |
|---|---|
| Document ID | [TM-SYSTEM-001] |
| System / feature | [Name] |
| System version or commit modelled | [v2.4 / commit abc1234] |
| Version | [0.1] |
| Status | [Draft / In review / Approved / Superseded] |
| Owner | [@security-champion] |
| Participants | [@dev-lead, @appsec, @sre, @product] |
| Classification | [Internal / Confidential] |
| Last reviewed | YYYY-MM-DD |
| Next review due | YYYY-MM-DD |

### Approvals

| Role | Name | Decision | Date |
|---|---|---|---|
| System owner | [@name] | [Approved / Changes requested] | YYYY-MM-DD |
| Application security | [@name] | [Decision] | YYYY-MM-DD |
| Engineering lead | [@name] | [Decision] | YYYY-MM-DD |

## Revision history

<!-- Guidance: Record each modelling session and each change that added, closed or re-rated threats. -->

| Version | Date | Author | Change summary |
|---|---|---|---|
| 0.1 | YYYY-MM-DD | [@name] | Initial DFD and threat enumeration |
| 1.0 | YYYY-MM-DD | [@name] | *Example:* Mitigations agreed, residual risks accepted |

## Contents

1. [Scope](#1-scope)
2. [Assumptions and dependencies](#2-assumptions-and-dependencies)
3. [System model](#3-system-model)
4. [Assets and entry points](#4-assets-and-entry-points)
5. [Threat enumeration](#5-threat-enumeration)
6. [Risk rating](#6-risk-rating)
7. [Mitigations](#7-mitigations)
8. [Validation](#8-validation)
9. [Residual risk and acceptance](#9-residual-risk-and-acceptance)
10. [Review cadence and triggers](#10-review-cadence-and-triggers)
11. [Standard and licence note](#standard-and-licence-note)

## 1. Scope

<!-- Guidance: State exactly what was modelled. Name components, flows and environments. Common mistake: modelling "the platform" in one session and finding nothing specific. -->

This model covers [system name] as deployed in [production / all environments]
at version [v2.4]. It answers four questions: what are we working on, what can
go wrong, what are we going to do about it, and did we do a good job.

### 1.1 In scope

<!-- Guidance: List components and data flows by name so each can be traced to the DFD. -->

- *Example:* Public web client (SPA) and mobile app calling the REST API.
- *Example:* `orders-api` service, its PostgreSQL database and Redis cache.
- *Example:* Outbound call to the payment provider and inbound webhook.
- *Example:* Admin console used by support staff.

### 1.2 Out of scope

<!-- Guidance: Say why each item is excluded and where it is covered instead. -->

| Item | Reason | Covered by |
|---|---|---|
| *Example:* Cloud provider physical security | Inherited control | Provider SOC 2 report |
| *Example:* Corporate identity provider | Separate model | [TM-IDP-003] |
| [Item] | [Reason] | [Reference] |

### 1.3 Security objectives

<!-- Guidance: Short list of what "secure" means for this system, in business terms. -->

- *Example:* A customer can only read and change their own orders.
- *Example:* Card data never touches our systems (payment provider tokenisation).
- *Example:* Every privileged action by support staff is attributable and logged.
- *Example:* The checkout path stays available during a volumetric attack up to [10x] normal load.

## 2. Assumptions and dependencies

<!-- Guidance: Write down what you rely on without verifying it in this model. Each assumption is a place where a threat could hide; give each an ID so it can be challenged later. -->

| ID | Assumption | Consequence if false | Validated by |
|---|---|---|---|
| AS-01 | *Example:* TLS 1.2+ is terminated at the load balancer with a managed certificate | Traffic interception on the public flow | Config scan, quarterly |
| AS-02 | *Example:* The identity provider enforces MFA for all admin accounts | Admin account takeover via password spray | IdP policy export |
| AS-03 | *Example:* Database is reachable only from the application subnet | Direct data access from other workloads | Network policy test |
| AS-04 | *Example:* Payment provider webhooks are signed with a shared secret | Forged payment confirmations | Provider documentation |
| AS-05 | [Assumption] | [Consequence] | [Evidence] |

## 3. System model

<!-- Guidance: A data flow diagram (DFD) with external entities, processes, data stores, data flows and trust boundaries. Keep it to one page; split into level-1 diagrams for large systems. Every arrow that crosses a boundary is a candidate for threats. -->

The diagram below shows the elements and flows in scope. Dashed subgraphs are
trust boundaries: places where data moves between different levels of
privilege or ownership.

```mermaid
flowchart LR
    U["Customer (browser, mobile)"]
    ADM["Support agent"]
    PSP["Payment provider"]
    subgraph TB1["Trust boundary: public internet to edge"]
        LB["Load balancer + WAF"]
    end
    subgraph TB2["Trust boundary: application network"]
        API["orders-api"]
        ADMIN["admin-console"]
        Q["Job worker"]
    end
    subgraph TB3["Trust boundary: data tier"]
        DB[("PostgreSQL")]
        C[("Redis cache")]
    end
    U -- "F1 HTTPS + session" --> LB
    ADM -- "F2 HTTPS + SSO" --> LB
    LB -- "F3" --> API
    LB -- "F4" --> ADMIN
    API -- "F5 SQL" --> DB
    API -- "F6" --> C
    ADMIN -- "F7 SQL" --> DB
    API -- "F8 HTTPS" --> PSP
    PSP -- "F9 signed webhook" --> LB
    API -- "F10 enqueue" --> Q
```

### 3.1 Element catalogue

<!-- Guidance: One row per element in the DFD. The type decides which STRIDE categories apply (see section 5). -->

| ID | Element | Type | Owner | Notes |
|---|---|---|---|---|
| E-01 | Customer | External entity | n/a | Untrusted, authenticated by session |
| E-02 | Support agent | External entity | Support team | Authenticated by SSO + MFA |
| E-03 | orders-api | Process | Team Orders | Node.js, runs as non-root container |
| E-04 | admin-console | Process | Team Support Tools | Internal only via SSO |
| E-05 | PostgreSQL | Data store | Platform | Encrypted at rest |
| E-06 | Payment provider | External entity | Vendor | Tokenises card data |
| E-07 | [Element] | [Type] | [Owner] | [Notes] |

### 3.2 Data flows

<!-- Guidance: Classify the data on each flow and note the protection in transit. -->

| ID | From -> to | Data | Classification | Protection |
|---|---|---|---|---|
| F1 | Customer -> LB | Credentials, order data | Confidential | TLS 1.2+, HSTS |
| F5 | orders-api -> PostgreSQL | Orders, addresses | Confidential (PII) | TLS, least-privilege DB role |
| F9 | Payment provider -> LB | Payment status | Internal | HMAC signature, IP allow-list |
| [Fn] | [From -> to] | [Data] | [Class] | [Controls] |

## 4. Assets and entry points

<!-- Guidance: Assets are what an attacker wants or what you cannot afford to lose. Entry points are where an attacker can interact with the system. Both drive impact and likelihood ratings. -->

The assets and entry points below define what is worth protecting and where an
attacker can reach the system.

### 4.1 Assets

| ID | Asset | Sensitivity | Security property at stake | Impact if compromised |
|---|---|---|---|---|
| A-01 | *Example:* Customer accounts and sessions | High | Confidentiality, integrity | Account takeover, fraud |
| A-02 | *Example:* Order and address records (PII) | High | Confidentiality | Privacy breach, regulator notification |
| A-03 | *Example:* Payment status | High | Integrity | Goods shipped without payment |
| A-04 | *Example:* Audit log | Medium | Integrity, availability | Loss of attribution |
| A-05 | *Example:* Checkout availability | High | Availability | Revenue loss of [~$12k/hour] |
| A-06 | [Asset] | [H/M/L] | [C/I/A] | [Impact] |

### 4.2 Entry points

| ID | Entry point | Exposed to | Authentication | Trust level required |
|---|---|---|---|---|
| EP-01 | *Example:* `POST /api/orders` | Internet | Session cookie | Authenticated customer |
| EP-02 | *Example:* `POST /webhooks/payments` | Internet (provider IPs) | HMAC signature | Payment provider |
| EP-03 | *Example:* Admin console UI | Corporate network | SSO + MFA | Support role |
| EP-04 | *Example:* CI/CD deployment pipeline | Engineers | SSO + branch protection | Maintainer |
| EP-05 | [Entry point] | [Exposure] | [Mechanism] | [Level] |

## 5. Threat enumeration

<!-- Guidance: Walk the DFD element by element. Use "STRIDE per element": external entities face S and R; processes face all six; data stores face T, R, I, D; data flows face T, I, D. Write each threat as "attacker + action + asset + consequence". Common mistake: listing generic categories ("XSS") instead of a concrete threat on a named element. -->

STRIDE categories map to the security property they violate: Spoofing
(authentication), Tampering (integrity), Repudiation (non-repudiation),
Information disclosure (confidentiality), Denial of service (availability),
Elevation of privilege (authorisation).

| Element type | S | T | R | I | D | E |
|---|---|---|---|---|---|---|
| External entity | Yes | | Yes | | | |
| Process | Yes | Yes | Yes | Yes | Yes | Yes |
| Data store | | Yes | Yes | Yes | Yes | |
| Data flow | | Yes | | Yes | Yes | |

### 5.1 Threat register

<!-- Guidance: One row per threat. Link to the element (E-), flow (F-) or entry point (EP-). Ratings are filled in section 6. -->

| ID | Element / flow | STRIDE | Threat description | Assets | Existing controls |
|---|---|---|---|---|---|
| T-01 | E-01 / F1 | S | *Example:* Attacker replays a stolen session cookie to act as the customer | A-01 | HttpOnly, Secure cookies |
| T-02 | F9 / EP-02 | S, T | *Example:* Attacker forges a payment webhook marking an unpaid order as paid | A-03 | HMAC check |
| T-03 | E-03 | E, I | *Example:* Customer changes `order_id` in the URL to read another customer's order (IDOR) | A-02 | None identified |
| T-04 | E-04 | R | *Example:* Support agent refunds an order and later denies it; no per-action audit record | A-04 | App logs only |
| T-05 | E-05 | I | *Example:* Database backup copied to an unrestricted storage bucket | A-02 | Encryption at rest |
| T-06 | EP-01 | D | *Example:* Bot floods order creation, exhausting DB connections | A-05 | WAF rate limit (global only) |
| T-07 | EP-04 | T | *Example:* Compromised dependency injects code at build time | A-01, A-02 | Lockfile, Dependabot |
| T-08 | [ID] | [S/T/R/I/D/E] | [Threat] | [A-nn] | [Controls] |

## 6. Risk rating

<!-- Guidance: Rate every threat consistently. Use the qualitative likelihood x impact matrix for design-level threats; use CVSS v4.0 base scores for concrete vulnerabilities found in testing. State which scale you used. -->

Each threat is rated with likelihood $L$ and impact $I$ on a 1 to 5 scale,
after existing controls. The risk score is:

$$
R = L \times I, \qquad 1 \le R \le 25
$$

| Score $R$ | Rating | Required response |
|---|---|---|
| 15-25 | Critical | Mitigate before release; no acceptance below CTO level |
| 8-14 | High | Mitigate within [30] days or accept with expiry |
| 4-7 | Medium | Plan in backlog; acceptance by system owner allowed |
| 1-3 | Low | Accept and monitor |

| Level | Likelihood (L) | Impact (I) |
|---|---|---|
| 5 | Expected; trivial to exploit, public tooling exists | Large-scale breach, regulatory notification, long outage |
| 3 | Plausible; needs some skill or insider position | Limited data exposure or degraded service for some users |
| 1 | Rare; needs multiple unlikely conditions | Negligible, contained, easily reversed |

### 6.1 Rated threats

| Threat | L | I | $R$ | Rating | Rationale |
|---|---|---|---|---|---|
| T-01 | 3 | 4 | 12 | High | *Example:* Session lifetime 30 days, no binding |
| T-02 | 2 | 5 | 10 | High | *Example:* HMAC present but no timestamp check, replay possible |
| T-03 | 4 | 5 | 20 | Critical | *Example:* IDs are sequential integers; no ownership check |
| T-04 | 3 | 3 | 9 | High | *Example:* Needed for dispute handling |
| T-05 | 2 | 5 | 10 | High | *Example:* One misconfigured bucket found last year |
| T-06 | 3 | 4 | 12 | High | *Example:* Seen in peak season |
| T-07 | 2 | 5 | 10 | High | *Example:* Industry-wide trend |

For a confirmed vulnerability, record the CVSS vector alongside, for example
`CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N`, and use the
vendor calculator to derive the score.

## 7. Mitigations

<!-- Guidance: Each mitigation names the threats it addresses, an owner, a tracking ticket and a target date. Prefer controls that remove the threat class (parameterised queries, framework-level authorisation) over point fixes. -->

Mitigations are mapped to threats so that every rated threat above Low has at
least one planned or implemented control.

| ID | Mitigation | Addresses | Type | Owner | Ticket | Due | Status |
|---|---|---|---|---|---|---|---|
| M-01 | *Example:* Enforce ownership check in the data access layer for all order queries; use UUIDs | T-03 | Prevent | @orders-lead | [SEC-412] | YYYY-MM-DD | In progress |
| M-02 | *Example:* Reject webhooks older than 5 minutes; store and dedupe event IDs | T-02 | Prevent | @payments | [SEC-413] | YYYY-MM-DD | Planned |
| M-03 | *Example:* Reduce session lifetime to 12 h idle, rotate on privilege change, bind to device | T-01 | Prevent | @identity | [SEC-414] | YYYY-MM-DD | Planned |
| M-04 | *Example:* Append-only audit log for admin actions with actor, reason and diff | T-04 | Detect | @support-tools | [SEC-415] | YYYY-MM-DD | Done |
| M-05 | *Example:* Per-account and per-IP rate limits on order creation; connection pool caps | T-06 | Prevent | @sre | [SEC-416] | YYYY-MM-DD | Planned |
| M-06 | *Example:* Signed build provenance, pinned dependencies, review of new packages | T-07 | Prevent | @platform | [SEC-417] | YYYY-MM-DD | Planned |
| M-07 | [Mitigation] | [T-nn] | [Prevent/Detect/Respond] | [@owner] | [Ticket] | YYYY-MM-DD | [Status] |

### 7.1 Coverage check

<!-- Guidance: Quick reconciliation so nothing falls through. -->

- Threats rated Critical or High without a mitigation: [none / list].
- Threats transferred to a third party and the contract clause: [list].
- Threats marked not applicable and why: [list].

## 8. Validation

<!-- Guidance: "Did we do a good job?" Show evidence that each mitigation works. Tests should be automated where possible so they keep working after the review. -->

Every implemented mitigation needs evidence that it works and keeps working.

| Mitigation | Validation method | Evidence | Result | Date |
|---|---|---|---|---|
| M-01 | *Example:* Automated authorisation test: user B requests user A's order, expects 404 | CI job `authz-tests` | Pass | YYYY-MM-DD |
| M-02 | *Example:* Replay a captured webhook after 6 minutes in staging | Test log [link] | Pass | YYYY-MM-DD |
| M-04 | *Example:* Review audit entries for 20 sampled refunds | Review notes [link] | Pass | YYYY-MM-DD |
| M-05 | *Example:* Load test at 10x baseline order rate | Report [link] | [Result] | YYYY-MM-DD |
| [M-nn] | [SAST / DAST / pentest / unit test / config scan] | [Link] | [Result] | YYYY-MM-DD |

Model quality checks:

- [ ] Every element and every boundary-crossing flow has been considered for all applicable STRIDE categories.
- [ ] Every assumption in section 2 has a validation method or an owner.
- [ ] Findings from the latest penetration test (see security/pentest-report) are reflected in the register.

## 9. Residual risk and acceptance

<!-- Guidance: Residual risk is what remains after mitigations. Acceptance needs a named person with authority, a reason and an expiry date. An acceptance without expiry is a permanent exception nobody remembers. -->

The threats below keep a residual risk that the owners named have accepted for
the period stated.

| Threat | Residual $R$ | Reason for acceptance | Compensating control | Accepted by | Date | Expires |
|---|---|---|---|---|---|---|
| T-05 | 4 (Medium) | *Example:* Bucket policy guardrail covers the org; full DLP scanning deferred | Weekly public-bucket scan | @cto | YYYY-MM-DD | YYYY-MM-DD |
| [T-nn] | [Score] | [Reason] | [Control] | [@name] | YYYY-MM-DD | YYYY-MM-DD |

## 10. Review cadence and triggers

<!-- Guidance: Decide when this model is revisited, and who calls the review. Tie it to change, not only to the calendar. -->

This model is reviewed every [6 months] and additionally when any trigger below
occurs. The owner schedules the review and updates the revision history.

| Trigger | Example | Action |
|---|---|---|
| New entry point or trust boundary | Public API for partners | Full session on affected elements |
| New data class | Storing date of birth | Re-rate information disclosure threats |
| New third-party integration | Switching payment provider | Model the new flows |
| Security incident or pentest finding | IDOR reported via bug bounty | Add threat, root cause, re-validate |
| Major framework or platform change | Moving to serverless | Revisit assumptions section |
| Acceptance expiry | Risk T-05 expires | Re-accept or mitigate |

Related documents: [architecture/technical-design-doc], [security/pentest-report],
[dev/service-readiness], [incident postmortems that involved security].

## Standard and licence note

Based on the STRIDE threat classification published by Microsoft and on common
industry threat modelling practice (data flow diagrams with trust boundaries,
STRIDE per element, likelihood x impact rating, mitigation mapping and risk
acceptance). CVSS is maintained by FIRST; consult the CVSS v4.0 specification
for scoring rules. This template is original text written for this collection
and reproduces no text from those sources. Template licence: MIT.
