attack-flow — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited attack-flow (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
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:
#### Rule 1: Component Layout (Left-to-Right by Attack Flow)
#### Rule 2: Technique Ordering (Top-to-Bottom)
#### Rule 3: Technique-Component Centering
technique.x = component.x + (component.width - technique.width) / 2#### Rule 4: Component Sizing
#### Rule 5: Edge Connections
"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#### 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:
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#### 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:
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 organization#### Victim Zones (Multi-Organization Attacks)
When 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, labelBgStyleflows/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 websearchThis will:
flows/incidents/ultralytics.jsonSee flows/incidents/ultralytics.json or flows/incidents/tj-actions.json for correctly structured examples.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.