Skip to main content
Engineering/threat-model

Threat Model

You need a STRIDE-based threat model for a system or application with threat matrix and prioritized mitigations.

Use this when you need to systematically identify threats to a system -- when designing a new architecture, onboarding onto a client's system, preparing for a security review, or responding to a risk assessment request. Goes beyond feature-level security review to model threats across an entire system.

Related skills: Use /system-diagram for architecture input. Use /security-review for per-feature deep dives on high-risk components. Use /adr-generate for security architecture decisions. Use /architecture-discovery for domain boundary analysis.

Process

Step 1: Gather system context

Ask the user for:

  • Architecture diagram or description (or run /system-diagram to generate one)
  • Data flows -- what data moves where, in what format, over what protocols
  • Trust boundaries -- where do privilege levels change?
  • Authentication and authorization mechanisms
  • External integrations (third-party APIs, SaaS dependencies, payment processors)
  • Data sensitivity classification (PII, PHI, financial, public, internal)

If the user provides a description rather than a diagram, sketch a component list with data flows before proceeding.

Step 2: Identify trust boundaries

Map every point where data crosses a trust boundary:

  • Client to server -- browser/mobile app to backend API
  • Service to service -- internal microservice communication
  • Internal to external -- calls to third-party APIs, webhooks
  • User to admin -- privilege escalation boundaries
  • Encrypted to unencrypted -- TLS termination points, decryption for processing
  • Network zones -- public internet, DMZ, private subnet, database tier

Document each boundary with: source, destination, protocol, authentication method, data sensitivity.

Step 3: Apply STRIDE per component

For each component that sits on or crosses a trust boundary, analyze six threat categories:

CategoryQuestion
SpoofingCan an attacker impersonate a legitimate user, service, or component?
TamperingCan data be modified in transit or at rest without detection?
RepudiationCan a user or system deny performing an action with no way to prove otherwise?
Information DisclosureCan data leak through error messages, logs, side channels, or unauthorized access?
Denial of ServiceCan the component be overwhelmed, starved of resources, or made unavailable?
Elevation of PrivilegeCan an attacker gain higher permissions than intended?

Be specific about attack vectors. Not "the API could be attacked" but "an unauthenticated user could enumerate valid user IDs via timing differences in the login response."

Step 4: Generate the threat matrix

Produce a table covering every identified threat:

| Threat ID | STRIDE Category | Affected Component | Threat Description | Likelihood (1-5) | Impact (1-5) | Risk Score (L x I) | Existing Controls | Residual Risk |
|---|---|---|---|---|---|---|---|---|
| T-001 | {{category}} | {{component}} | {{specific_attack_vector}} | {{1-5}} | {{1-5}} | {{score}} | {{current_controls}} | {{low/medium/high/critical}} |

Scoring guidance:

  • Likelihood: 1 = requires nation-state capability, 5 = script kiddie with public tools
  • Impact: 1 = minor inconvenience, 5 = regulatory action, mass data breach, business shutdown
  • Risk score: multiply likelihood by impact. Critical >= 20, High >= 12, Medium >= 6, Low < 6

Step 5: Produce prioritized mitigations

For each threat rated high or critical, recommend a mitigation:

| Threat ID | Recommended Control | Control Type | Implementation Effort | Priority |
|---|---|---|---|---|
| T-001 | {{specific_control}} | Preventive / Detective / Corrective | S / M / L | {{P1-P4}} |

Every mitigation must be actionable -- include enough detail that an engineer could estimate and plan the work. "Implement rate limiting" is too vague. "Add per-IP rate limiting at the API gateway (100 req/min for unauthenticated, 1000 req/min for authenticated) with 429 responses and alerting at 80% threshold" is actionable.

Step 6: Annotate the data flow diagram

Mark the system diagram (or component list) with:

  • Trust boundary lines (dashed borders around zones)
  • Threat entry points (numbered, referencing threat IDs)
  • Highest-risk components (highlighted)
  • Data sensitivity labels at each flow

If starting from a text description, produce a labeled component diagram in Mermaid or ASCII.

Step 7: Review

Ask the user:

  • Are there components or integrations we missed?
  • Does the team have threat intelligence -- known attack patterns against similar systems?
  • Are there compliance requirements that mandate specific controls (PCI-DSS, HIPAA, SOC 2)?
  • What's the team's current security posture -- mature security practice or greenfield?
  • Which threats feel most realistic given the organization's exposure?

Output location

Deliver the threat model as a markdown document. Suggested filename: threat-model-{{system-name}}-{{date}}.md. Store in the project's security documentation directory or deliver directly to the requesting team.

Example Output

Input

  • System description: Meridian Health's new patient portal — React SPA frontend, Node.js/Express API gateway, three internal microservices (appointments, records, billing), PostgreSQL databases per service, and a Stripe integration for copay collection. Auth via Auth0 with JWT tokens passed between services.
  • Data sensitivity: PHI (diagnosis history, medication records), PII (name, DOB, SSN for insurance), and payment card data routed through Stripe
  • Trust boundaries: Public internet → API gateway, API gateway → internal microservices over private VPC, Auth0 (external IdP) → API gateway, billing service → Stripe API (outbound)
  • Compliance requirements: HIPAA, PCI-DSS SAQ-A
  • Security posture: Greenfield build, small engineering team, no dedicated security staff

Output (abbreviated)

Threat Model: Meridian Health Patient Portal

Date: 2025-01-14 Scope: Patient-facing portal including SPA, API gateway, three microservices, Auth0 IdP, and Stripe payment integration Classification: CONFIDENTIAL — Contains PHI system architecture details


System Component Inventory

ComponentZoneData HandledAuth Mechanism
React SPAPublic internet (client)Session tokens, form inputAuth0 PKCE flow
API Gateway (Node/Express)DMZJWTs, all PHI in transitAuth0 JWT validation
Appointments ServicePrivate VPCAppointment records, PHIInternal JWT (forwarded)
Records ServicePrivate VPCDiagnosis, medication, lab resultsInternal JWT (forwarded)
Billing ServicePrivate VPCCopay amounts, insurance IDsInternal JWT (forwarded)
Auth0 (external)External SaaSCredentials, session stateOAuth 2.0 / PKCE
Stripe (external)External SaaSCard data (tokenized)Stripe API key
PostgreSQL (×3)Database tierPHI at rest, financial recordsService account credentials

Trust Boundary Map

Boundary IDSourceDestinationProtocolAuth MethodData Sensitivity
TB-01Browser (public)API GatewayHTTPS/TLS 1.3Auth0 JWT (Bearer)PHI, PII
TB-02API GatewayAppointments / Records / BillingHTTPS (internal)Forwarded JWT (unvalidated per-service?)PHI
TB-03API GatewayAuth0HTTPSClient credentials + PKCECredentials
TB-04Billing ServiceStripeHTTPSStripe secret key (env var)PCI card tokens
TB-05MicroservicesPostgreSQL instancesTCP/TLSService account passwordPHI at rest
TB-06Any serviceCloudWatch / loggingHTTPSIAM rolePotential PHI in logs

STRIDE Threat Matrix

Threat IDSTRIDEAffected ComponentThreat DescriptionLikelihoodImpactRisk ScoreExisting ControlsResidual Risk
T-001SpoofingAPI Gateway (TB-01)Attacker presents a forged or expired JWT — if the gateway only checks signature but not exp or aud claims, any previously valid token grants access indefinitely4520 — CriticalAuth0 signature validationHIGH — claim validation unconfirmed
T-002Elevation of PrivilegeRecords Service (TB-02)API gateway forwards JWTs to microservices but individual services perform no independent authorization check; a compromised appointments service could call records endpoints with a patient JWT and retrieve any patient's full medical history3515 — HighVPC network isolationHIGH
T-003Information DisclosureLogging pipeline (TB-06)Node.js exception handlers log full request bodies on validation errors; a malformed request to the records endpoint could cause PHI (medication list, diagnosis codes) to appear in CloudWatch in plaintext4416 — HighNone confirmedHIGH
T-004Information DisclosureStripe integration (TB-04)Stripe secret key stored as plaintext environment variable; if any microservice achieves RCE or if env vars are exposed via a /debug or /health endpoint, the key leaks — enabling fraudulent charges against all stored payment methods3515 — HighStripe key scoped to billing service onlyHIGH
T-005Denial of ServiceAPI GatewayNo rate limiting on unauthenticated endpoints (login, password reset, appointment availability lookup); attacker can enumerate valid patient email addresses via timing differences in the login 401 response (~50ms delta observed) and exhaust appointment slot lookups5315 — HighNoneHIGH
T-006TamperingPostgreSQL — Records DB (TB-05)All three microservices use the same PostgreSQL service account with broad CRUD on all tables; a vulnerability in the appointments service could be used to modify records or billing data — no row-level security enforced3515 — HighVPC isolation, no public DB exposureHIGH
T-007RepudiationAll servicesNo centralized audit log for PHI access; a malicious insider or compromised session could read hundreds of patient records with no forensic trail — violates HIPAA §164.312(b) audit controls4416 — HighCloudWatch application logs (incomplete)HIGH
T-008SpoofingAuth0 integrationAuth0 tenant misconfiguration (e.g., allowing social login providers without MFA) could let attacker register a Google account matching a patient's email and gain portal access2510 — MediumAuth0 managedMEDIUM
T-009Information DisclosureReact SPAJWT stored in localStorage rather than httpOnly cookie; any XSS vulnerability in the SPA (including third-party npm package compromise) can exfiltrate the token and impersonate the patient3412 — HighContent Security Policy (status unknown)HIGH
T-010Denial of ServiceRecords ServiceNo pagination or query size limits on the records endpoint; an authenticated patient (or attacker with a valid token) can request full record history in a single call, causing memory exhaustion on the service pod339 — MediumKubernetes resource limits (unconfirmed)MEDIUM

Prioritized Mitigations (High + Critical)

Threat IDRecommended ControlControl TypeEffortPriority
T-001In the API gateway JWT middleware, enforce validation of exp, iat, aud (must equal https://portal.meridianhealth.com), and iss (must equal Auth0 tenant URL) on every request. Reject tokens with clock skew > 5 minutes. Add unit tests covering expired and wrong-audience tokens.PreventiveSP1
T-002Each microservice must independently validate the JWT and enforce its own authorization rules — appointments service may only access appointment-scoped claims; records service must verify the sub claim matches the requested patient ID. Implement a shared internal auth middleware library to standardize this across all three services.PreventiveMP1
T-003Audit all catch blocks and Express error handlers; redact PHI fields (defined by an allowlist of safe-to-log fields) before writing to CloudWatch. Adopt a structured logging library (e.g., pino) with a PHI scrubbing transform. Run a one-time scan of existing CloudWatch log groups and delete or restrict access to any group containing PHI.Preventive + CorrectiveMP1
T-007Implement a dedicated HIPAA audit log stream: every read/write of PHI must emit a structured event containing { timestamp, userId, patientId, resourceType, action, sourceIp } to an append-only log store (CloudWatch log group