Five ready-to-edit Mermaid diagrams covering RBAC, OAuth 2.0 PKCE, Kubernetes attack surfaces, supply-chain threats, and zero-trust architecture. Open any one in the editor, adapt it to your system, share via URL.
Threat modeling fails in two predictable places: getting the diagram drawn at all, and keeping it current six months later. Most teams sketch a STRIDE diagram or attack tree during a kickoff workshop, paste a screenshot into Confluence, and watch it rot. By the time the architecture has shifted, no one wants to redraw it — so the documentation drifts away from the system it's supposed to describe.
Mermaid changes that arithmetic. The diagram lives next to the code as plain text. Trust boundaries, identity flows, attack vectors — all of them expressed in a few dozen lines of syntax that diff cleanly in pull requests. When the system changes, the diagram updates in the same commit. Reviewers see what changed in the model, not just that something did.
This page collects five diagrams that work as starting points for common security work. Click Open in editor on any example to start adapting it to your system — the diagram loads with full content via a shareable URL.
Five threat-modeling templates
Each template renders below. Open in editor to customize, then share the URL with your team.
RBAC: User → Role → Permission
Class diagram
The smallest useful authorization model. Map users to roles and roles to permissions. Use as the structural backbone before drawing dynamic auth flows.
classDiagram
class User {
+string username
+Role[] roles
}
class Role {
+string name
+Permission[] permissions
}
class Permission {
+string action
+string resource
}
User --> Role
Role --> Permission
A complete PKCE authorization-code flow with token exchange, refresh, and failure paths. Useful for review meetings when arguing about session handling and token storage.
sequenceDiagram
participant U as User Agent
participant SPA as SPA Client
participant Auth as Authorization Server
participant API as Resource API
Note over SPA: PKCE Setup
SPA->>SPA: Generate code_verifier
SPA->>SPA: code_challenge = SHA256(verifier)
SPA->>U: Redirect to /authorize
U->>Auth: GET /authorize + code_challenge
Auth->>U: Login form
U->>Auth: Credentials
Auth->>U: 302 Redirect ?code=xyz
U->>SPA: Callback with auth code
SPA->>Auth: POST /token + code_verifier
Auth->>Auth: Verify SHA256(verifier) == challenge
Auth->>SPA: access_token + refresh_token
SPA->>API: GET /resource (Bearer token)
API->>API: Verify JWT signature & claims
API->>SPA: 200 OK
A cluster with two pods, ingress, service, and secrets — with four threat vectors overlaid as dashed lines. Drop into a runbook for a baseline k8s threat conversation.
graph LR;
classDef threat fill:#fca5a5,stroke:#f66,stroke-width:2px,color:#000,stroke-dasharray:5,stroke-dashoffset:5
user((End-User))
threatCreds((Stolen Credentials))
threatDOS((DoS Attack))
threatMisconfig((Misconfiguration))
maliciousImage((Malicious Container Image))
subgraph cluster [Kubernetes Cluster]
ingress((Ingress))
svc((K8s Service))
subgraph node1 [Node 1]
pod1((Pod 1))
end
subgraph node2 [Node 2]
pod2((Pod 2))
end
secrets{{K8s Secrets}}
end
db[(SQL Database)]
user -->|HTTPS| ingress
ingress --> svc
svc --> pod1
svc --> pod2
pod1 --> db
pod2 --> db
secrets -.-> pod1
secrets -.-> pod2
threatCreds-.-> user
threatDOS-.-> ingress
threatMisconfig-.-> secrets
maliciousImage-.-> pod2
class threatCreds,threatDOS,threatMisconfig,maliciousImage threat
Where an attacker can land between “an open-source dependency exists” and “your code runs in production.” Three threat classes: malicious package, compromised dependency, build tampering.
flowchart LR
classDef threat fill:#fca5a5,stroke:#f66,stroke-width:2px,color:#000
subgraph Upstream
OSS[Open Source]
Vendor[Vendor SDK]
Registry[Package Registry]
end
subgraph Build
CI[CI/CD Pipeline]
Artifact[Build Artifact]
end
subgraph Deploy
Prod[Production]
end
OSS --> CI
Vendor --> CI
Registry --> CI
CI --> Artifact
Artifact --> Prod
Malicious([Malicious Package]):::threat -.-> Registry
Compromised([Compromised Dependency]):::threat -.-> OSS
Tampering([Build Tampering]):::threat -.-> CI
Identity provider → MFA → policy engine → access proxy, with continuous validation back to the policy engine. Use to anchor “why do we need this proxy” conversations.
flowchart TB
subgraph External
User[User]
Device[Device]
end
subgraph ZeroTrust [Zero Trust Architecture]
IDP[Identity Provider]
MFA[MFA]
Policy[Policy Engine]
Access[Access Proxy]
end
subgraph Resources
App1[App 1]
App2[App 2]
Data[(Data)]
end
User --> IDP
Device --> IDP
IDP --> MFA
MFA --> Policy
Policy -->|Verify Every Request| Access
Access --> App1
Access --> App2
Access --> Data
Policy -.->|Continuous Validation| Access
What you gain over Lucidchart, draw.io, or whiteboard photos.
Diff-able in pull requests
Reviewers see exactly what changed in the model — not just “here's a new screenshot.” Auditors trace decisions through git history.
No tool drift
Every developer renders the same diagram. No paid seats, no plugin install, no “the file format isn't compatible.”
Living documentation
The diagram lives in the repo with the code it describes. Change one, change the other — same commit.
Stays in your environment
Diagrams render client-side here — or in your repo's README. Sensitive architecture never leaves your network.
Tips for clearer threat-model diagrams
Patterns that have worked across the templates above.
Mark threats as dashed red lines using classDef threat fill:#fca5a5,stroke-dasharray:5 so they're visually distinct from normal data flow.
Group assets into subgraph blocks for trust boundaries (DMZ, internal, external). Boundaries are the highest-information part of any threat model.
For attack chains, prefer sequence diagrams with Note over annotations — they read like an attack narrative, which is closer to how STRIDE conversations actually flow.
Keep one diagram per concern: asset inventory, data flow, attack tree. Combining them into one mega-diagram makes the diff useless.
Commit the .mmd file alongside your README. Link to a rendered version on SimpleMermaid for stakeholders who don't read markdown.