The clearest way to learn threat modeling is to work through threat model examples on real systems, because the method only makes sense once you see it applied to an actual data flow. Abstract descriptions of STRIDE and attack trees leave most people no better at securing their own software. These threat model examples take three common systems, a web application, an API, and a CI/CD pipeline, and walk each one through the same four questions Adam Shostack popularized: what are we building, what can go wrong, what are we going to do about it, and did we do a good job.
The method in one paragraph
Threat modeling is structured worry. You draw how data moves through your system, identify where trust boundaries are crossed, enumerate what could go wrong at each boundary, and decide what to do about each threat. STRIDE gives you a checklist of threat categories to apply at every boundary: Spoofing, Tampering, Repudiation, Information disclosure, Denial of service, and Elevation of privilege. The data flow diagram (DFD) is the map; STRIDE is the lens you hold over it.
Example 1: A web application login flow
Consider a login form that posts credentials to a backend, which checks them against a user database and issues a session cookie.
The trust boundaries are the browser-to-server hop (untrusted client to your server) and the server-to-database hop. Applying STRIDE at the browser boundary:
- Spoofing: an attacker submits stolen or guessed credentials. Mitigation: rate limiting, account lockout with care to avoid a lockout-based denial of service, and multi-factor authentication.
- Tampering: request parameters are modified in transit. Mitigation: TLS everywhere, and never trust client-side validation alone.
- Information disclosure: credentials or session tokens leak. Mitigation: TLS,
HttpOnlyandSecurecookie flags, and no tokens in URLs or logs. - Denial of service: credential stuffing floods the login endpoint. Mitigation: rate limiting and progressive delays.
- Elevation of privilege: SQL injection in the credential check lets an attacker bypass authentication entirely. Mitigation: parameterized queries, never string-concatenated SQL.
That last one is worth dwelling on because it is the highest-impact and the most preventable. The fix is a coding pattern, not a product: use prepared statements so user input is always data and never executable SQL.
Example 2: A public REST API
Now model an API that accepts a bearer token, reads a resource ID from the path, and returns the record.
The interesting threats here are authorization, not authentication:
- Elevation of privilege / broken object-level authorization: a valid user requests
/orders/1002when they only own/orders/1001. This is the most common and damaging API flaw, and it slips past authentication entirely because the caller is legitimately logged in. Mitigation: check ownership on every object access, server-side, on every request. Never rely on the client only requesting IDs it should have. - Information disclosure through over-fetching: the endpoint returns the full record including internal fields. Mitigation: explicit response schemas that expose only intended fields.
- Denial of service through unbounded queries: a
limitparameter with no cap lets a caller request a million rows. Mitigation: enforce maximum page sizes server-side. - Repudiation: a user denies making a destructive call. Mitigation: audit logging of who did what, with request IDs.
An API threat model almost always concludes that authorization logic is the weak point, and that it must be enforced per request rather than assumed from the token. Complementing the model with running-application testing catches the cases you missed on paper; dynamic application security testing exercises these endpoints the way an attacker would.
Example 3: A CI/CD pipeline
Software supply chain attacks target the pipeline because it has broad access and is often less scrutinized than production. Model a pipeline that pulls source, installs dependencies, builds an artifact, and deploys with production credentials.
The trust boundaries are numerous: the source repository, the dependency registry, the build environment, and the deployment target. STRIDE surfaces threats that most teams never wrote down:
- Tampering (dependency): a malicious or compromised dependency executes code during install. Mitigation: pin dependencies by version and hash, use a lockfile, and scan the dependency tree. A single compromised transitive package can exfiltrate your build secrets, and an SCA tool that watches the full tree is the practical defense.
- Elevation of privilege (build): a pull request from a fork runs with access to production secrets. Mitigation: do not expose deployment credentials to untrusted PR builds; require approval before privileged steps.
- Tampering (artifact): the built artifact is swapped between build and deploy. Mitigation: sign artifacts and verify signatures at deploy time.
- Information disclosure (secrets): credentials leak into build logs. Mitigation: use masked secrets, scoped short-lived tokens, and scan logs for exposure.
The pipeline example tends to be the eye-opener, because teams that carefully threat-model their application often grant their CI system god-mode access without a second thought.
How to run your own session
You do not need a week or a specialist to get value. A useful session fits in an afternoon:
- Pick one feature or flow, not the whole system.
- Draw the data flow on a whiteboard, marking every place data crosses from less-trusted to more-trusted.
- Walk STRIDE at each boundary and write down every plausible threat without filtering.
- For each threat, decide: mitigate, accept, transfer, or eliminate.
- Turn the mitigations into tracked work items with owners.
Keep the artifact lightweight and living. A threat model that is a one-time PDF nobody revisits is worse than a whiteboard photo you update when the design changes. Free tools like the OWASP Threat Dragon or the Microsoft Threat Modeling Tool help draw and record DFDs if you want structure, but the thinking matters more than the tooling. If your team is new to this, our academy has foundational material worth pairing with these examples.
FAQ
What is the best framework for threat modeling?
STRIDE is the most widely used and the easiest to learn, because it gives a concrete checklist of six threat categories to apply at each trust boundary. Pair it with a data flow diagram and Shostack's four-question framing.
How detailed should a threat model be?
Detailed enough to surface real threats, no more. Model one flow at a time, keep the diagram lightweight, and update it when the design changes. An over-engineered model that nobody maintains provides less value than a simple one that stays current.
What threat do API threat models most often reveal?
Broken object-level authorization, where an authenticated user accesses records they do not own. It bypasses authentication entirely and requires per-request, server-side ownership checks to prevent.
Should CI/CD pipelines be threat-modeled?
Yes, and they often are not. Pipelines hold broad access and production credentials, making them a prime supply chain target. Model dependency tampering, secret exposure, and privileged builds from untrusted pull requests.