wiz-sec-public/attack-flow
Generate SITF-compliant attack flow JSON files from attack descriptions or incident reports. Use when analyzing supply chain attacks, breaches, or security incidents.
npx skills add https://github.com/wiz-sec-public/SITF --skill attack-flow
Generate SITF-compliant attack flow JSON files from attack descriptions or incident reports.
/attack-flow <attack-name> [source]
attack-name: Identifier for the attack (e.g., "s1ngularity", "solarwinds")source: URL, "websearch" for auto-research, or omit to use conversation contextArguments: $ARGUMENTS
When this skill is invoked:
techniques.json to get the full technique library."type": "technique-gap"/technique-proposal should be run for in-scope gapsApply these layout rules:
technique.x = component.x + (component.width - technique.width) / 2"type": "smoothstep" for all edgesGenerate the attack flow JSON with this exact structure:
{
"metadata": {
"name": "Attack Name",
"title": "Canvas Display Title",
"created": "ISO-8601 timestamp",
"version": "1.0",
"framework": "SITF",
"description": "Brief attack description"
},
"nodes": [],
"edges": []
}
Metadata field guidelines:
name: Short identifier (e.g., "tj-actions", "circleci")title: Concise canvas title, max 5-7 words (e.g., "tj-actions/changed-files Compromise", "CircleCI Security Incident (2023)")description: One sentence summary, max 150 characters{
"id": "entryPoint-attackname-1",
"type": "entryPoint",
"position": { "x": -150, "y": 200 },
"data": {
"label": "Entry Point Label"
},
"zIndex": 10,
"width": 195,
"height": 46
}
{
"id": "component-cicd-1",
"type": "component",
"position": { "x": 50, "y": 80 },
"data": {
"label": "CI/CD",
"componentId": "cicd",
"techniques": [],
"customLabel": "Context-specific label"
},
"zIndex": -1,
"width": 250,
"height": 500,
"style": { "width": 250, "height": 500 }
}
{
"id": "technique-c003-1",
"type": "technique",
"position": { "x": 95, "y": 160 },
"data": {
"id": "T-C003",
"name": "PWN Request / Poisoned Pipeline Execution",
"component": "cicd",
"stage": "Initial Access",
"description": "Full description from techniques.json",
"risks": ["risk1", "risk2"],
"controls": {
"protective": [{ "name": "control1", "frameworks": {...} }],
"detective": [{ "name": "control2", "frameworks": {...} }]
},
"customLabel": "Attack-specific context",
"evidence": "Optional: specific evidence from the attack"
},
"zIndex": 10,
"width": 160,
"height": 96
}
IMPORTANT technique.data fields:
id: Use technique ID (e.g., "T-C003") — NOT "techniqueId"name: Use technique name — NOT "label"risks: Copy full array from techniques.jsoncontrols: Copy full object with protective and detective arrays from techniques.jsoncustomLabel: Add attack-specific context (e.g., "PRs #18018, #18020")evidence: Optional field for attack-specific evidence{
"id": "exitPoint-attackname-1",
"type": "exitPoint",
"position": { "x": 950, "y": 200 },
"data": {
"label": "Secondary Supply Chain Attack"
},
"zIndex": 10,
"width": 144,
"height": 46
}
{
"id": "edge-source-target",
"source": "technique-c003-1",
"sourceHandle": "bottom",
"target": "technique-c004-1",
"targetHandle": "top",
"type": "smoothstep",
"animated": false,
"markerEnd": { "type": "arrowclosed" },
"label": "",
"labelStyle": { "fill": "#DC2626", "fontWeight": 600, "fontSize": 12 },
"labelBgStyle": { "fill": "#FEE2E2", "fillOpacity": 0.9 }
}
{
"id": "edge-cross-component",
"source": "technique-c011-1",
"sourceHandle": "right",
"target": "technique-r001-1",
"targetHandle": "left",
"type": "smoothstep",
"animated": false,
"style": { "stroke": "#9ca3af" },
"markerEnd": { "type": "arrowclosed", "color": "#9ca3af" },
"label": "Transition label",
"labelStyle": { "fill": "#DC2626", "fontWeight": 600, "fontSize": 12 },
"labelBgStyle": { "fill": "#FEE2E2", "fillOpacity": 0.9 }
}
Node types:
entryPoint: Attack entry (Phishing, Vulnerability Exploit, Stolen Credentials, Malicious Fork PR, etc.)component: SITF component container (endpoint, vcs, cicd, registry, production)technique: Attack technique from techniques.jsontechnique-gap: Placeholder for missing technique (flag for /technique-proposal)exitPoint: Attack outcome (Future Breach, Persistence, Secondary Supply Chain Attack, etc.)victimZone: Visual container grouping components belonging to a single victim organizationWhen an attack involves multiple victim organizations (e.g., supply chain attacks that cascade across vendors), use victimZone nodes to visually group each victim's components.
When to use victim zones:
Victim Zone Structure:
{
"id": "victimZone-aqua",
"type": "victimZone",
"position": { "x": -24, "y": 15 },
"data": {
"label": "Aqua Security",
"color": "#3B82F6"
},
"zIndex": -10,
"width": 1444,
"height": 945,
"style": { "width": 1444, "height": 945 }
}
Layout rules for victim zones:
#3B82F6 blue, #06B6D4 cyan, #8B5CF6 purple)zIndex: -10 so zones render behind components and techniquesReference: See flows/incidents/teampcp-campaign.json for a multi-victim example with 4 victim zones.
After generating the flow, analyze defensive gaps:
| Technique | Missing Control | Type | OWASP SPVS |
|-----------|-----------------|------|------------|
| T-C003 | Minimal workflow permissions | Protective | V3.1 |
| T-C005 | Log sanitization | Protective | V2.5 |
| T-C005 | Runtime agent on runner | Detective | V5.4 |
Run this checklist before outputting:
[ ] Valid JSON structure (parse test passes)
[ ] Required fields present: metadata.{name,title,created,version,framework}, nodes[], edges[]
[ ] All node IDs are unique
[ ] All edge source/target reference valid node IDs
[ ] Technique nodes use data.id and data.name (NOT techniqueId/label)
[ ] Technique nodes include full risks[] array and controls object with protective/detective arrays
[ ] Out-of-scope attack steps noted but not forced into SITF techniques
[ ] All techniques centered within components (x = component.x + 45 for width=250)
[ ] Component heights are adequate (minimum 500px)
[ ] Techniques ordered by attack flow sequence
[ ] Initial Access techniques appear first when order is ambiguous
[ ] All technique IDs exist in techniques.json OR flagged as technique-gap
[ ] Exit points connected to terminal techniques
[ ] No orphaned nodes (every non-entry node has incoming edge)
[ ] Edges have sourceHandle, targetHandle, markerEnd, labelStyle, labelBgStyle
flows/incidents/<attack-name>.jsonpython3 -c "import json; json.load(open('file'))"## Attack Flow: <attack-name>
### Attack Chain
1. Initial Access via [entry point]
2. [Technique] → [Technique] → ...
3. Impact: [exit point]
### Techniques Used
| ID | Name | Component | Stage |
|----|------|-----------|-------|
| T-C003 | PWN Request | CI/CD | Initial Access |
| ... | ... | ... | ... |
### Control Gaps Identified
| Missing Control | Type | Would Prevent | OWASP SPVS |
|-----------------|------|---------------|------------|
| Minimal workflow permissions | Protective | T-C003 | V3.1 |
| ... | ... | ... | ... |
### Out-of-Scope Steps
- [Step X]: Generic cloud attack, see MITRE ATT&CK T1078
### Technique Gaps
- [Step Y]: No matching SITF technique, run `/technique-proposal`
/technique-proposal/attack-flow ultralytics websearch
This will:
flows/incidents/ultralytics.jsonSee flows/incidents/ultralytics.json or flows/incidents/tj-actions.json for correctly structured examples.
Take wiz-sec-public/attack-flow from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.
The instructions reference pip.
Without those the skill loads but fails at the first command.