security-threat-model
Security threat model: scan toolkit for attack surface, supply-chain risks.
Best use case
security-threat-model is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Security threat model: scan toolkit for attack surface, supply-chain risks.
Teams using security-threat-model should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/security-threat-model/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How security-threat-model Compares
| Feature / Agent | security-threat-model | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Security threat model: scan toolkit for attack surface, supply-chain risks.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Security Threat Model Skill
## Overview
This skill executes a structured, phase-gated security threat model workflow that scans
the toolkit installation for attack surface exposure, supply-chain injection patterns,
and learning DB contamination. It follows the toolkit's four-layer architecture:
deterministic Python scripts perform all checks and produce JSON artifacts; Phase 5
(synthesis only) is the LLM step. Each phase gates on artifact validation before proceeding.
Outputs are saved to `security/` with a shared `run_id` for correlation across phases.
Phase 5 produces an actionable threat model document.
---
## Instructions
### Phase 1: SURFACE SCAN
**Goal**: Enumerate the active attack surface of the current installation.
Create the `security/` output directory and run the surface scan script:
```bash
mkdir -p security
python3 scripts/scan-threat-surface.py --output security/surface-report.json
```
This script enumerates:
- Registered hooks (from `~/.claude/settings.json`) with file paths and event types
- Installed MCP servers (from `~/.claude/mcp.json` and `.mcp.json`)
- Installed skills (from `skills/`) with `allowed-tools` entries
- Any file in `hooks/`, `skills/`, or `agents/` containing `ANTHROPIC_BASE_URL`
**Validate output**:
```bash
python3 -c "import json; d=json.load(open('security/surface-report.json')); print('hooks:', len(d.get('hooks',[])), '| skills:', len(d.get('skills',[])), '| mcp_servers:', len(d.get('mcp_servers',[])))"
```
**Gate (ARTIFACT VALIDATION)**: `security/surface-report.json` must exist, parse as valid JSON, and contain `hooks`, `skills`, and `mcp_servers` keys. A missing directory is handled gracefully with empty arrays. All artifacts are written to `security/` before gating. Do not proceed to Phase 2 until this gate passes.
---
### Phase 2: DENY-LIST GENERATION
**Goal**: Produce a concrete deny-list config derived from Phase 1 findings.
Generate the deny-list from the surface report:
```bash
python3 scripts/generate-deny-list.py \
--surface security/surface-report.json \
--output security/deny-list.json
```
The script applies these mappings from surface findings to deny rules:
- Hook uses `curl` or `wget` → append `"Bash(curl *)"` and `"Bash(wget *)"`
- Hook uses `ssh` or `scp` → append `"Bash(ssh *)"` and `"Bash(scp *)"`
- Skill `allowed-tools` contains unscoped `Read(*)` or `Write(*)` → add path-scoped deny entries
- Any file contains `ANTHROPIC_BASE_URL` override → append `"Bash(* ANTHROPIC_BASE_URL=*)"`
Always includes static baseline deny rules for credentials and privileged operations:
```json
["Read(~/.ssh/**)", "Read(~/.aws/**)", "Read(**/.env*)",
"Write(~/.ssh/**)", "Write(~/.aws/**)",
"Bash(curl * | bash)", "Bash(ssh *)", "Bash(scp *)", "Bash(nc *)",
"Bash(* ANTHROPIC_BASE_URL=*)"]
```
**Display deny-list for human review**:
```bash
python3 -c "
import json
d = json.load(open('security/deny-list.json'))
print('Deny-list entries to add to settings.json:')
for rule in d['permissions']['deny']:
print(' ', rule)
print()
print('Review security/deny-list.json before merging.')
"
```
**Gate (HUMAN APPROVAL REQUIRED)**: The deny-list is produced for human review only — it is never merged automatically. Display the diff and block until the operator confirms review. This gate is the highest-ROI control in the workflow. In `--ci-mode`, skip this gate and proceed to Phase 3. Do not proceed without explicit acknowledgment.
---
### Phase 3: SUPPLY-CHAIN AUDIT
**Goal**: Scan all installed hooks, skills, and agents for injection patterns and hidden characters.
Run the supply-chain audit:
```bash
python3 scripts/scan-supply-chain.py \
--scan-dirs hooks/ skills/ agents/ \
--output security/supply-chain-findings.json
```
Detection patterns (full regex details in `scripts/scan-supply-chain.py` source):
| Pattern | Severity |
|---------|----------|
| Zero-width + bidi Unicode characters | CRITICAL |
| HTML comments and hidden payload blocks | CRITICAL |
| `ANTHROPIC_BASE_URL` override in any file | CRITICAL |
| Instruction-override and role-hijacking phrases | CRITICAL |
| Outbound network commands in hooks/skills | WARNING |
| `enableAllProjectMcpServers` setting | WARNING |
| Broad permission grants without path scoping | WARNING |
**Check for CRITICAL findings**:
```bash
python3 -c "
import json, sys
d = json.load(open('security/supply-chain-findings.json'))
crits = [f for f in d.get('findings', []) if f.get('severity') == 'CRITICAL']
warns = [f for f in d.get('findings', []) if f.get('severity') == 'WARNING']
print(f'CRITICAL: {len(crits)}, WARNING: {len(warns)}')
if crits:
for c in crits:
print(f' CRITICAL: {c[\"file\"]}:{c.get(\"line\",\"?\")} -- {c[\"pattern\"]}')
sys.exit(1)
"
```
**Gate (BLOCKING CRITICAL FINDINGS)**: Any CRITICAL finding halts forward progress. All CRITICAL findings must be remediated or explicitly acknowledged before Phase 4 can start. This includes zero-width Unicode, ANTHROPIC_BASE_URL overrides, hidden payloads, and instruction-override phrases. WARNING findings are logged but do not block. Log warnings in the threat model under "Gaps and Recommended Next Controls" with acceptance rationale.
---
### Phase 4: LEARNING DB SANITIZATION
**Goal**: Inspect the learning DB for entries that may contain injected content from external sources.
Run the sanitization check in dry-run mode (never mutates without explicit `--purge`):
```bash
python3 scripts/sanitize-learning-db.py \
--output security/learning-db-report.json
```
Flags entries where:
- `key` or `value` contain instruction-override or role-hijacking phrases
- `source` is `pr_review`, `url`, or `external` (high-risk origins)
- `value` contains zero-width Unicode or base64 blobs
- `first_seen` is older than 90 days and `source` indicates external origin
**Review flagged entries**:
```bash
python3 -c "
import json
d = json.load(open('security/learning-db-report.json'))
flagged = d.get('flagged_entries', [])
print(f'Total flagged: {len(flagged)}')
for e in flagged[:10]:
print(f' [{e[\"severity\"]}] id={e[\"id\"]} source={e.get(\"source\",\"?\")} action={e[\"action\"]}')
if len(flagged) > 10:
print(f' ... and {len(flagged)-10} more. See security/learning-db-report.json')
"
```
**Gate (DRY-RUN BY DEFAULT)**: The script operates in dry-run mode by default. No rows are deleted without explicit operator request and `--purge` flag. Present the report to the operator. If purge is desired after review, re-run with `--purge`. Learning DB is not found gracefully — script produces an empty report (`total_entries: 0`, `flagged_entries: []`). Proceed to Phase 5 when operator acknowledges the report or when no entries are flagged.
---
### Phase 5: THREAT MODEL SYNTHESIS
**Goal**: Synthesize Phases 1-4 findings into an actionable threat model document. This is the only LLM-driven phase.
Load all phase artifacts:
- `security/surface-report.json`
- `security/deny-list.json`
- `security/supply-chain-findings.json`
- `security/learning-db-report.json`
Write `security/threat-model.md` with these required sections (validator checks for exact headings):
```markdown
# Threat Model
## Run Metadata
## Attack Surface Inventory
## Active Threats
## Mitigations In Place
## Gaps and Recommended Next Controls
## Deny-List Status
## Supply-Chain Audit Summary
## Learning DB Sanitization Summary
```
Write `security/audit-badge.json`:
```json
{
"status": "pass",
"timestamp": "2026-01-01T00:00:00Z",
"run_id": "from-surface-report",
"critical_count": 0,
"warning_count": 0,
"phases_completed": 5
}
```
Status is `fail` if any CRITICAL finding was not remediated or if any phase gate did not pass.
**Validate outputs**:
```bash
python3 scripts/validate-threat-model.py \
--threat-model security/threat-model.md \
--badge security/audit-badge.json
```
**Gate (ARTIFACT VALIDATION WITH RETRY LIMIT)**: `validate-threat-model.py` must exit 0. If validation fails, add the missing sections and re-run. Maximum 3 fix iterations before escalating to operator for review.
---
## Error Handling
### Supply-chain audit CRITICAL finding blocks progress
**Cause**: A hook, skill, or agent contains zero-width Unicode, ANTHROPIC_BASE_URL override, or known injection phrase.
**Resolution**:
1. Open the flagged file at the reported line number
2. Determine if it is a legitimate false positive (e.g., documentation discussing injection patterns)
3. If false positive: add the file to `--exclude` list and re-run `scan-supply-chain.py`
4. If genuine: remediate the file (remove hidden payloads, instruction-override phrases) before continuing to Phase 4
### Validation fails with missing sections
**Cause**: Phase 5 synthesis omitted a required section heading.
**Resolution**: Read the validator output for the exact missing section name. Add the section to `security/threat-model.md` with content synthesized from the phase artifacts and re-run `validate-threat-model.py`. Maximum 3 fix iterations before escalating to operator.
### Missing configuration or databases
**Cause**: `~/.claude/settings.json` or learning DB doesn't exist.
**Resolution**: These are handled gracefully by the scripts:
- Missing `settings.json` → surface-report produces empty arrays for hooks
- Missing learning DB → sanitization report returns `total_entries: 0` and `flagged_entries: []`
These are not error conditions. Re-run with `--verbose` for detail on missing paths.
---
## References
- [ADR-102: Security Threat Model Skill](../../adr/ADR-102-security-threat-model.md)
- [pretool-prompt-injection-scanner.py](../../hooks/pretool-prompt-injection-scanner.py) -- session-time injection scanner (complements, does not replace this skill)
- [learning_db_v2.py](../../hooks/lib/learning_db_v2.py) -- learning DB schema and connection interface
- OWASP MCP Top 10 (living document)
- Snyk ToxicSkills research: 36% of public skills contained injection patternsRelated Skills
kubernetes-security
Kubernetes security: RBAC, PodSecurity, network policies.
x-api
Post tweets, build threads, upload media via the X API.
worktree-agent
Mandatory rules for agents in git worktree isolation.
workflow
Structured multi-phase workflows: review, debug, refactor, deploy, create, research, and more.
workflow-help
Interactive guide to workflow system: agents, skills, routing, execution patterns.
wordpress-uploader
WordPress REST API integration for posts and media uploads.
wordpress-live-validation
Validate published WordPress posts in browser via Playwright.
with-anti-rationalization
Anti-rationalization enforcement for maximum-rigor task execution.
voice-writer
Unified voice content generation pipeline with mandatory validation and joy-check. 8-phase pipeline: LOAD, GROUND, GENERATE, VALIDATE, REFINE, JOY-CHECK, OUTPUT, CLEANUP. Use when writing articles, blog posts, or any content that uses a voice profile. Use for "write article", "blog post", "write in voice", "generate content", "draft article", "write about".
voice-validator
Critique-and-rewrite loop for voice fidelity validation.
vitest-runner
Run Vitest tests and parse results into actionable output.
video-editing
Video editing pipeline: cut footage, assemble clips via FFmpeg and Remotion.