Security Threat Model Skill
Produce a complete STRIDE-based threat model for a service or feature. A threat model is not a list of things that could go wrong — it is a structured analysis of attackers, assets, boundaries, and controls that lets an engineering team make informed, documented security decisions.
A good threat model is specific enough that a new engineer can understand what is being protected, why each control exists, and what risk the team has accepted.
Required Inputs
Ask for these if not already provided:
- Service name and description — what the service does, who uses it
- Architecture overview — components, dependencies, data flows (a diagram description or ASCII diagram is fine)
- Deployment environment — cloud provider, VPC/network topology, where it runs (Kubernetes, ECS, VMs, serverless)
- Data sensitivity — what data does this service handle? PII, payment data, credentials, internal-only?
- Existing controls — authentication method, encryption in transit/at rest, current WAF/firewall, existing security scanning
- Trust levels — who are the principals? (anonymous public, authenticated users, internal services, admins)
Output Format
Security Threat Model: [Service Name]
Service: [Name] | Team: [Team name] Author: [Name] | Reviewed by: [Security lead / peer] Date: [Date] | Next review: [Date — recommend 6 months or after major architecture change] Classification: [Internal / Confidential]
1. Overview
[2–3 sentences describing the service, its role in the system, and the scope of this threat model. State what is in scope and what is explicitly out of scope.]
In scope:
- [Component or data flow]
- [Component or data flow]
Out of scope:
- [e.g. Third-party payment processor internals]
- [e.g. Corporate network / end-user devices]
2. Asset Register
Assets are the things worth protecting — data, capabilities, and reputational value.
| Asset | Description | Sensitivity | Owner | |---|---|---|---| | [e.g. User PII] | Names, email addresses, profile data | High — GDPR-regulated | [Team] | | [e.g. API credentials] | Service-to-service auth tokens | Critical | [Team] | | [e.g. Session tokens] | User authentication state | High | [Team] | | [e.g. Audit logs] | Record of user and admin actions | Medium | [Team] | | [e.g. Service availability] | Uptime of the [X] endpoint | Medium | [Team] |
Data classification key:
- Critical — Credential material; exposure enables direct system compromise
- High — PII, financial data, health data; regulated or high reputational impact
- Medium — Internal configuration, non-sensitive business data
- Low — Public information, anonymised data
3. Trust Boundaries and Architecture
Trust boundaries are the lines that separate zones with different trust levels. Threats often occur when data or requests cross a boundary.
┌─────────────────────────────────────────────────────────────────┐
│ INTERNET (Untrusted) │
│ │
│ [Public User] [Bot / Attacker] │
└──────────────────────────────┬──────────────────────────────────┘
│ HTTPS
─ ─ ─ ─ ─ ─ ─│─ ─ ─ ─ ─ ─ ─ ─
Trust Boundary: Public → DMZ
─ ─ ─ ─ ─ ─ ─│─ ─ ─ ─ ─ ─ ─ ─
▼
┌──────────────────────────────────────────────────────────────────┐
│ DMZ / Edge Layer │
│ ┌────────────┐ ┌──────────────┐ │
│ │ WAF / CDN │────▶│ API Gateway │ │
│ └────────────┘ └──────┬───────┘ │
└──────────────────────────────┼───────────────────────────────────┘
─ ─ ─ ─ ─ ─ ─│─ ─ ─ ─ ─ ─ ─ ─
Trust Boundary: Edge → Application VPC
─ ─ ─ ─ ─ ─ ─│─ ─ ─ ─ ─ ─ ─ ─
▼
┌──────────────────────────────────────────────────────────────────┐
│ Application VPC (Private) │
│ ┌──────────────┐ ┌────────────┐ ┌──────────────────┐ │
│ │ [Service A] │────▶│ [Service B]│────▶│ [Database] │ │
│ └──────────────┘ └────────────┘ └──────────────────┘ │
│ ▲ │
│ │ │
│ ┌──────────────┐ │ │
│ │ Admin (IAM) │─────────────┘ │
└──────────────────────────────────────────────────────────────────┘
Trust Boundaries identified:
| Boundary | From | To | Auth mechanism | Encrypted | |---|---|---|---|---| | TB-1 | Public internet | API Gateway | [JWT / OAuth / API key] | TLS 1.2+ | | TB-2 | API Gateway | Service A | [mTLS / internal JWT / IAM role] | [Yes/No] | | TB-3 | Service A | Database | [Connection string + IAM / username+password] | [Yes/No] | | TB-4 | Admin | Service B | [IAM role / VPN + MFA] | TLS |
4. STRIDE Threat Analysis
STRIDE is a threat classification framework. For each significant component, enumerate threats in each category.
STRIDE key:
- S — Spoofing: Impersonating another user, service, or system
- T — Tampering: Modifying data or code without authorisation
- R — Repudiation: Denying an action occurred; insufficient audit trail
- I — Information Disclosure: Exposing data to unauthorised parties
- D — Denial of Service: Making the service unavailable
- E — Elevation of Privilege: Gaining capabilities beyond what is authorised
Component: [API Gateway / Auth Layer]
| ID | Category | Threat | Attack vector | Existing control | |---|---|---|---|---| | T-001 | S | Attacker forges a JWT token to authenticate as another user | Weak signing key or algorithm confusion (alg:none) | [e.g. RS256 with key rotation / none] | | T-002 | S | Attacker replays a stolen session token | Theft via XSS or network sniff | [e.g. Token expiry + refresh rotation] | | T-003 | T | Attacker modifies request headers to bypass tenant isolation | Missing validation of tenant ID header | [e.g. Server-side tenant resolution / none] | | T-004 | R | No audit trail for admin authentication events | Logging not configured for auth failures | [e.g. CloudTrail enabled / none] | | T-005 | I | Auth error messages reveal whether an email exists | Verbose error responses | [e.g. Normalised error responses / none] | | T-006 | D | Credential stuffing exhausts rate limits and blocks legitimate users | Automated login attempts | [e.g. Rate limiting per IP + CAPTCHA / none] | | T-007 | E | Compromised low-privilege token used to call admin endpoint | Missing role check on admin routes | [e.g. RBAC middleware on all routes / none] |
Component: [Application Service / Business Logic]
| ID | Category | Threat | Attack vector | Existing control | |---|---|---|---|---| | T-008 | T | SQL/NoSQL injection via unsanitised user input | Unparameterised queries | [e.g. ORM with parameterised queries / none] | | T-009 | T | Mass assignment — attacker sets fields they should not (e.g. isAdmin: true) | API accepts extra fields without allowlist | [e.g. Input validation / none] | | T-010 | I | Insecure direct object reference — user accesses another user's resource | Missing ownership check on resource ID | [e.g. Ownership middleware / none] | | T-011 | I | Sensitive data in application logs (PII, tokens) | Over-logging in debug mode | [e.g. Log scrubbing / none] | | T-012 | D | Unprotected expensive endpoint triggers large DB scan | No pagination or query cost limit | [e.g. Pagination enforced / none] | | T-013 | R | Business-critical state changes not logged | No audit eve