Decide what a design must be true before code exists: naming assets and actors, locating trust boundaries, producing a written (asset, boundary, threat, control, owner) list, recording the assumptions the design rests on, and knowing when a change invalidates the model. Use when scaffolding a new feature, service, or endpoint, writing or reviewing a design doc, RFC, or ADR, or introducing a new trust boundary, integration, or data flow.
Scanned 9/6/2026
Install to Claude Code
npx -y skills add ShieldNet-360/secure-vibe --skill threat-modeling --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Threat Modeling?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/shieldnet-360-threat-modeling)More formats (shields.io, HTML) on the badges page.
---
name: threat-modeling
description: "Decide what a design must be true before code exists: naming assets and actors, locating trust boundaries, producing a written (asset, boundary, threat, control, owner) list, recording the assumptions the design rests on, and knowing when a change invalidates the model. Use when scaffolding a new feature, service, or endpoint, writing or reviewing a design doc, RFC, or ADR, or introducing a new trust boundary, integration, or data flow."
---
<!-- Native skill bundle for agent-skills (cross-tool convention). Generated by `secure-vibe dev regenerate`. -->
<!-- Do not edit by hand; the source of truth is skills/threat-modeling/SKILL.md. -->
# Threat Modeling
Decide what a design must be true before code exists: naming assets and actors, locating trust boundaries, producing a written (asset, boundary, threat, control, owner) list, recording the assumptions the design rests on, and knowing when a change invalidates the model. Use when scaffolding a new feature, service, or endpoint, writing or reviewing a design doc, RFC, or ADR, or introducing a new trust boundary, integration, or data flow.
## ALWAYS
- Produce a **written list**, not an impression. One row per finding, in the design doc, the RFC, or the PR description: `(asset, boundary, threat, control, owner)` — what is worth taking, where it crosses, what could go wrong there, what stops it, and which component enforces it. A model that exists only in the reasoning that produced the code cannot be reviewed, disagreed with, or checked later.
- Name the **assets** and the **actors** first: data, funds, credentials, keys and compute on one side; users, tenants, services, admins and the attacker on the other. Every later row references one of each, which is what makes the list finite.
- Locate the **trust boundaries** — internet to application, tenant to shared store, service to service, user input to an interpreter, model output to anything that acts on it. A boundary is where data arrives from a party you do not control, and it is the unit the rest of the model is organised around.
- At each boundary, ask the six **STRIDE** questions and write down only the answers that matter: can the caller be **spoofed** (is there authentication), can the data be **tampered** with in flight, will there be a record if someone **repudiates** the action, what is **disclosed** if this crossing leaks, what happens under **denial of service**, and does anything here allow **elevation of privilege**. A category with no answer is not a gap; a category nobody asked about is.
- Write down the **assumptions the design depends on**: this gateway is the only ingress, this queue's producers are authenticated, this field is already validated upstream, this CDN strips that header. Assumptions are the part of a threat model that later becomes false without anyone noticing, and an unwritten one cannot be rechecked.
- Rank the rows and say which ones **block the design**. A model that treats every threat as equally urgent gets implemented in whatever order the work happens to arrive, which means the ranking gets made anyway, by accident.
- Design controls to **fail closed**: on error, missing configuration, a timeout, or an unhandled case, the secure outcome is denial. This is a design property because the alternative is usually invisible in the code — an exception that skips a check reads exactly like an exception that skips a log line.
- Put each control **at the component that owns the asset**, behind any gateway rather than instead of it. The owning service authenticates and authorizes even when a perimeter also does, because perimeters get bypassed, reconfigured, and eventually routed around by the next service that needs direct access.
- **Re-run the model when its inputs change** — a new actor, a new boundary, a new data flow for an existing asset, a component moving between trust zones, or an assumption you wrote down turning out to be false. A model is a statement about a design, so it expires when the design moves.
- Route each control to the skill that owns it, and record that in the row's `owner`. `auth-security` owns who the caller is and what they may touch, `api-security` the endpoint's own controls, `database-security` how tenant isolation is actually enforced, `iam-best-practices` the privileges a workload runs with, and `llm-app-security` what a model's output is allowed to reach. This skill decides which controls the design requires; those skills say what the control is.
## NEVER
- Treat anything the **client** controls as a control — hidden fields, disabled buttons, client-side role checks, an unverified token, a price in the request body. All of it is advisory. This is the design-level statement of a rule several code skills enforce, and it belongs here because it is usually decided before any code is written.
- Design a component that is **trusted because of where it sits**. "Internal service", private subnet, VPN, IP allowlist: those describe reachability, and reachability is not authentication. `api-security` owns the endpoint-level rule; the design-level version is that a trust boundary drawn around a network segment has no enforcement behind it.
- Invent a bespoke authentication, session, or access-control primitive when a vetted one exists. Design in the standard building block — OIDC for identity, mTLS or SPIFFE for workload identity, a policy engine for authorization decisions. `crypto-misuse` owns the equivalent rule for cryptographic primitives.
- Add an external **integration, dependency, or webhook** without deciding three things in writing: who may call it, what it is trusted to assert, and what happens when the counterparty is compromised or impersonated. The third is the one that gets skipped, and it is the one that determines blast radius.
- Leave a sensitive datum with **no sanctioned home**. For each one, name where it lives and, by implication, where it must not appear — logs, error payloads, client bundles, URL parameters, analytics. An undecided lifecycle is how a credential ends up in four places, none of them chosen.
- Ship a design whose security analysis is "we will add auth later". Retrofitting a trust boundary onto a built feature means changing the data model, and that is the point at which it does not happen.
## KNOWN FALSE POSITIVES
- A genuinely public, read-only surface — marketing site, public docs, a public catalog — legitimately has no authentication. The model's job is to confirm it holds nothing sensitive and grants nothing, not to add auth to it.
- Network controls layered **on top of** service-level authentication are good design. The finding is network position as the *sole* control, never its presence.
- mTLS or SPIFFE workload identity **is** authentication — a cryptographic caller identity, not a network location — so a service-to-service call over it is not relying on network position.
- A design that reuses an existing, documented boundary without changing it inherits that boundary's model. The trigger is a *new* or *moved* boundary; a fifth endpoint behind the same authenticated, tenant-scoped surface as the other four is not a new model.
## Reference files
Read these only when the task calls for them.
- `references/design-level-failures.md`
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!