Build an ATT&CK Navigator layer from a folder of Sigma rules. Useful for showing "here's what my detection content covers" in a single picture, and for spotting tactics where you're light.
- Walks every
.ymlunder--rules-dir. - Reads each rule's
tags:list and pulls outattack.tXXXX[.YYY]entries. - Tallies how many rules touch each technique.
- Writes a Navigator layer JSON. Score = rule count. Heatmap colors run from light blue (one rule) to dark blue (many).
# Print layer JSON to stdout
uv run attack-coverage --rules-dir ../detection-rules/rules
# Write to a file + print a table to stderr for quick inspection
uv run attack-coverage --rules-dir ../detection-rules/rules \
--out coverage.json \
--tableThen drop coverage.json into the Navigator: open https://mitre-attack.github.io/attack-navigator/, click "Open Existing Layer → Upload from local", select the JSON.
Technique coverage
┏━━━━━━━━━━━┳━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Technique ┃ Rules ┃ Files ┃
┡━━━━━━━━━━━╇━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ T1003 │ 2 │ lsass_memory_access_un... │
│ T1003.001 │ 2 │ lsass_memory_access_un... │
│ T1547.001 │ 1 │ registry_run_key_modif... │
│ T1218.011 │ 1 │ rundll32_unusual_parent.yml │
│ T1547 │ 0 │ — │
└───────────┴───────┴───────────────────────────────┘
- Solid colored cells — techniques with at least one rule. Darker = more rules.
- Empty cells in a tactic column — gaps. Worth a hunt design exercise to figure out whether you can cover them.
- Hover text — shows the source rule filenames, so you can pivot back to the YAML.
Commit coverage.json to your repo on every push so the file is always current:
- name: Generate coverage layer
run: uv run attack-coverage --rules-dir rules --out coverage.json
- name: Commit if changed
uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_message: "Update ATT&CK coverage layer"
file_pattern: coverage.json- Two-color heatmap. Add
--threshold Nso techniques with ≥N rules render in one color and others in another. Easier-to-read at a glance. - Sub-technique aggregation. Currently each subtechnique is its own row. Add a
--rollupmode that aggregates a subtechnique's count into its parent. - Per-platform layers. Filter by
logsource.productand emit one layer per platform — "Windows coverage", "Linux coverage", "cloud coverage". - Diff mode. Two
--rules-dirflags. Output highlights techniques gained and lost between two repo states. - Coverage-quality scoring. Currently coverage is binary (any rule fires count). Add a
quality:field to your Sigma rules (levelcould substitute) and weight the score —critical=4, high=3, medium=2, low=1. - Combine with adversary-emulation results. If you have a YAML mapping of "atomic tests we run", layer that too — green where you have and test, yellow where you have but don't test, red where you have neither.