| name | threat-modeling |
| description | STRIDE threat identification with coverage checking (prose judgment) plus deterministic STRIDE coverage and DREAD severity scoring via executable script. Covers system architecture security review, trust boundaries across services, auth, payments, and PII feature pre-implementation review, and threat model refresh sessions. Use proactively when designing or reviewing a new system architecture or API, running pre-implementation security review for features touching auth, payments, or PII, conducting threat modeling sessions (initial or refresh), or reviewing another team's threat model for completeness. Run the coverage checker for deterministic STRIDE gap and DREAD scoring. |
| version | 2.0.0 |
| source | derived from .claude/skills/security/threat-modeling.md (v1.0); L3 coverage checker added 2026-05-20 |
| when_to_use | ["Designing or reviewing a new system architecture or API","Pre-implementation security review for any feature touching auth, payments, or PII","Threat modeling sessions (initial or refresh)","Reviewing another team's threat model for completeness","Any context where trust boundaries cross multiple services or external parties"] |
| allowed-tools | ["Read","Grep","Glob","Bash"] |
Threat Modeling
STRIDE threat identification, attack surface mapping, and deterministic coverage checking.
Use this skill to produce a complete threat model — not just a list of obvious issues.
STRIDE enumeration is prose judgment — the model reasons through each category for each trust boundary and entry point. STRIDE coverage and optional DREAD scoring are deterministic — the script checks whether every category is represented and computes severity consistently.
Never claim a threat model is complete without running the coverage checker.
STRIDE Categories
Enumerate ALL six categories for every significant trust boundary. Absence is a finding.
| Letter | Category | Core Question |
|---|
| S | Spoofing | Can an attacker impersonate a user, service, or system component? |
| T | Tampering | Can data be modified in transit, at rest, or during processing? |
| R | Repudiation | Can actions be denied without an audit trail? |
| I | Information Disclosure | Can sensitive data leak to unauthorized parties? |
| D | Denial of Service | Can availability be degraded or exhausted? |
| E | Elevation of Privilege | Can an attacker gain access beyond their authorization? |
Per-Category Design Questions
- Spoofing: How does the system verify caller identity at each trust boundary?
- Tampering: What validates that data has not been modified in transit or at rest?
- Repudiation: Is every sensitive action logged with enough context for forensic reconstruction?
- Information Disclosure: Does each response return only the minimum data needed?
- DoS: Are all unbounded operations (queries, loops, file reads) protected by limits?
- EoP: Is every privileged action checked against the authenticated user's actual permissions?
STRIDE Tag Reference (for the Coverage Checker)
Use these tags in the stride array of each finding:
| Tag | Category | Aliases accepted |
|---|
S | Spoofing | "Spoofing" |
T | Tampering | "Tampering" |
R2 | Repudiation | "R2", "Rep", "Repudiation" |
I | Information Disclosure | "I", "Information Disclosure" |
D3 | Denial of Service | "D3", "DoS", "Denial of Service" |
E | Elevation of Privilege | "E", "EoP", "Elevation of Privilege" |
(R2 and D3 are used instead of R/D to avoid colliding with DREAD dimension names.)
Invocation — STRIDE Coverage Checker (L3 Script)
After enumerating threats, assemble findings as a JSON array and run the checker. Consume its output only — the script source never enters context.
Format each finding (STRIDE only):
[
{
"title": "Unauthenticated admin endpoint accepts commands",
"stride": ["S", "E"]
}
]
Format each finding (STRIDE + DREAD scoring):
[
{
"title": "SQL injection in search endpoint",
"stride": ["T", "I"],
"D": 9,
"R": 8,
"E": 7,
"A": 10,
"D2": 6
}
]
Run via Bash (file argument):
python .claude/skills/security/threat-modeling/scripts/stride_coverage.py findings.json
Run via Bash (stdin):
echo '<json array>' | python .claude/skills/security/threat-modeling/scripts/stride_coverage.py -
The script outputs:
- A JSON object with
findings (stride_labels + optional score/band), coverage (per-category finding list), gaps (uncovered categories), and a summary.
- A STRIDE Coverage markdown table showing which categories are covered and which are gaps.
- (Optional) A DREAD Severity Rankings table if D/R/E/A/D2 dimensions are provided.
Error handling: Non-zero exit on invalid input (unknown STRIDE tag, partial DREAD scores, bad JSON). Fix the input and re-run.
What the agent does with the output:
- Check
gaps — any uncovered STRIDE category is a model deficiency; reason about why it might be N/A before accepting it.
- Lead remediation recommendations with Critical/High findings (if DREAD scores provided).
- For each gap: either add findings or document why the category is genuinely not applicable.
Trust Boundary Mapping
Enumerate all locations where data or control crosses a trust boundary. Controls must exist at every boundary.
## Trust Boundary Map: [System Name]
### Boundary 1: External Users → API Layer
- Entry: HTTPS endpoints at /api/*
- Authentication: JWT bearer token
- Controls: Rate limiting, input validation
- STRIDE threats: Spoofing (forged tokens), Tampering (body), DoS (unbounded requests), EoP (IDOR)
### Boundary 2: API Layer → Database
- Entry: Connection pool, parameterized queries
- Authentication: DB credentials from secrets manager
- Controls: Least-privilege DB user, no dynamic SQL
- STRIDE threats: Tampering (injection), Information Disclosure (over-fetching)
Attack Surface Checklist
Public Entry Points
Privileged Entry Points
Data Entry Points
Anti-Patterns
| Anti-Pattern | Why It Fails |
|---|
| Threat model after launch | Finding threats post-deployment means expensive code changes; threat model during design |
| Skipping Repudiation | Logging is a security requirement, not an operational nicety |
| "We're internal only" | Lateral movement after any breach renders internal = trusted false |
| WAF as a fix | WAFs bypass via application logic; fix the code |
| Checkbox compliance | Compliance frameworks lag behind real threats; they are a floor, not a ceiling |
Anti-Generic Rules
- NEVER declare a threat model complete without running the coverage checker
- NEVER skip Repudiation — logging and audit trails are security requirements
- NEVER assume internal network = trusted
- NEVER rate severity by gut feel — use DREAD dimensions if you need a score
- NEVER recommend "add a WAF" as a remediation — fix the code
Self-Critique: "Have I tagged every finding with STRIDE categories and run the checker? Did the coverage output show zero gaps, or did I explain each gap? Would a pentester find something in 10 minutes of black-box testing that I missed?"