SITF 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.
git clone https://github.com/wiz-sec-public/SITF
T=$(mktemp -d) && git clone --depth=1 https://github.com/wiz-sec-public/SITF "$T" && mkdir -p ~/.claude/skills && cp -r "$T/.claude/skills/attack-flow" ~/.claude/skills/wiz-sec-public-sitf-attack-flow && rm -rf "$T"
.claude/skills/attack-flow/SKILL.mdAttack Flow Generator
Generate SITF-compliant attack flow JSON files from attack descriptions or incident reports.
Usage
/attack-flow <attack-name> [source]
: Identifier for the attack (e.g., "s1ngularity", "solarwinds")attack-name
: URL, "websearch" for auto-research, or omit to use conversation contextsource
Arguments: $ARGUMENTS
Instructions
When this skill is invoked:
Phase 1: Research
-
If source is "websearch" or a URL, gather attack details:
- Attack timeline and phases
- Entry point and initial access method
- Lateral movement and persistence techniques
- Data exfiltration or impact
- Affected components (CI/CD, VCS, Registry, Endpoint, Production)
-
If source is omitted, use context from the current conversation.
Phase 2: Technique Mapping
-
Read
to get the full technique library.techniques.json -
For each attack step, find the best matching technique:
- Match by action semantics, not surface keywords
- Example: Uploading stolen data to repos → T-V003 (Secret Exfiltration), NOT T-V008 (Malicious Hosting)
- Example: Accessing VCS with stolen creds → T-V001 must come BEFORE any VCS actions
-
If no matching technique exists:
- Check if attack step is in-scope for SITF (SDLC/supply-chain related)
- If in-scope: Create placeholder with
"type": "technique-gap" - If out-of-scope (generic cloud/infra attack): Note in output, reference MITRE ATT&CK
- Note in output that
should be run for in-scope gaps/technique-proposal
Phase 3: Layout Calculation
Apply these layout rules:
Rule 1: Component Layout (Left-to-Right by Attack Flow)
- Order components by their sequence in the attack chain, not by standard SITF order
- If attack flows CI/CD → Registry → Endpoint → VCS, layout left-to-right accordingly
- Minimum horizontal gap between components: 80-100px
- Component x-positions: Use increments of ~300px starting from x=50
Rule 2: Technique Ordering (Top-to-Bottom)
- Primary: Order techniques by their sequence in the attack flow
- Secondary: Within same attack step, order by stage (Initial Access → Discovery → Post-Compromise)
- Vertical gap between techniques: ~130px
- First technique starts at y = component.y + 80
Rule 3: Technique-Component Centering
- Every technique node MUST be visually centered within its parent component
- Centering formula:
technique.x = component.x + (component.width - technique.width) / 2 - With component.width=250 and technique.width=160: offset = (250-160)/2 = 45
- Example: component at x=50 → technique at x=95
- Example: component at x=350 → technique at x=395
- Validate technique.data.component matches parent component.data.componentId
Rule 4: Component Sizing
- Width = 250px (standard)
- Height = max(500, (technique_count × 130) + 160) — ensures adequate vertical space
- All components should have consistent height for visual alignment
Rule 5: Edge Connections
- Connect source.bottom → target.top for vertical flows within component
- Connect source.right → target.left for cross-component flows
- Add labels for significant transitions ("Stolen token", "pip install", etc.)
- Use
for all edges"type": "smoothstep"
Phase 4: JSON Generation
Generate the attack flow JSON with this exact structure:
{ "metadata": { "title": "Human-readable title for canvas display", "name": "Attack Name", "created": "ISO-8601 timestamp", "version": "1.0", "framework": "SITF", "description": "Brief attack description" }, "nodes": [], "edges": [] }
Node Structure - Entry Point
{ "id": "entryPoint-attackname-1", "type": "entryPoint", "position": { "x": -150, "y": 200 }, "data": { "label": "Entry Point Label" }, "zIndex": 10, "width": 195, "height": 46 }
Node Structure - Component
{ "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 } }
Node Structure - Technique (CRITICAL: use exact field names)
{ "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:
: Use technique ID (e.g., "T-C003") — NOT "techniqueId"id
: Use technique name — NOT "label"name
: Copy full array from techniques.jsonrisks
: Copy full object withcontrols
andprotective
arrays from techniques.jsondetective
: Add attack-specific context (e.g., "PRs #18018, #18020")customLabel
: Optional field for attack-specific evidenceevidence
Node Structure - Exit Point
{ "id": "exitPoint-attackname-1", "type": "exitPoint", "position": { "x": 950, "y": 200 }, "data": { "label": "Secondary Supply Chain Attack" }, "zIndex": 10, "width": 144, "height": 46 }
Edge Structure (with full styling)
{ "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 } }
Cross-component Edge (with gray styling)
{ "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:
: Attack entry (Phishing, Vulnerability Exploit, Stolen Credentials, Malicious Fork PR, etc.)entryPoint
: SITF component container (endpoint, vcs, cicd, registry, production)component
: Attack technique from techniques.jsontechnique
: Placeholder for missing technique (flag for /technique-proposal)technique-gap
: Attack outcome (Future Breach, Persistence, Secondary Supply Chain Attack, etc.)exitPoint
Phase 5: Control Gap Analysis
After generating the flow, analyze defensive gaps:
-
For each technique used in the attack:
- List the protective controls from techniques.json
- Identify which controls were missing (enabled the attack)
-
Generate a Controls Gap Summary:
| 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 | -
Prioritize recommendations by:
- Number of techniques the control would prevent
- Stage of attack it would block (earlier = higher priority)
Phase 6: Validation
Run this checklist before outputting:
[ ] Valid JSON structure (parse test passes) [ ] Required fields present: metadata.{title,name,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
Phase 7: Output
- Write the JSON file to
flows/incidents/<attack-name>.json - Validate the JSON with Python:
python3 -c "import json; json.load(open('file'))" - Provide output summary:
## 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`
- If any technique-gaps exist, list them and recommend running
/technique-proposal
Example
/attack-flow ultralytics websearch
This will:
- Search for ultralytics attack details
- Map attack steps to SITF techniques
- Generate
flows/incidents/ultralytics.json - Output attack flow summary
Reference: Working Sample
See
flows/incidents/ultralytics.json or flows/incidents/tj-actions.json for correctly structured examples.