Skip to content

rsigma rule coverage🔗

Map a rule set onto MITRE ATT&CK: export an ATT&CK Navigator layer and report coverage gaps against the Atomic Red Team library, the SigmaHQ baseline heatmap, and a target technique list.

Synopsis🔗

rsigma rule coverage [OPTIONS] --rules <PATH>

Description🔗

rule coverage reads the attack.* tags off every detection and correlation rule, builds an inventory of which ATT&CK techniques the rule set covers (scored by the number of rules per technique), and answers the operational question "what does my rule set cover, and where are the holes."

It produces two kinds of output:

  • An ATT&CK Navigator layer (format 4.5) written with --navigator, scored the same way SigmaHQ scores its published heatmap (score = rule count), so a rsigma-generated layer overlays cleanly on the SigmaHQ baseline.
  • A coverage report on stdout, optionally cross-referenced three ways:
    • --atomics against the Atomic Red Team index: techniques that have atomics but no rule (a detection gap) and rules whose technique has no atomic (a validation gap).
    • --baseline against a baseline Navigator layer (the SigmaHQ heatmap by default): baseline techniques you do not cover, and techniques you cover that the baseline does not.
    • --targets against a plain-text technique list (an internal threat model): which targeted techniques are uncovered.

The command works entirely from the technique IDs already on the rules. It does not download the full ATT&CK matrix: the Navigator renders that, and each cross-reference supplies its own technique set.

Sub-technique roll-up🔗

A rule tagged with a sub-technique (attack.t1059.001) counts toward its parent technique (T1059) for gap analysis, reported as covered_via_subtechnique. The reverse does not hold: a rule on the parent T1059 does not vouch for a specific sub-technique target like T1059.002. The exported Navigator layer always keeps exact per-ID scores.

Flags🔗

Flag Default Description
-r, --rules <PATH> required Sigma rule file or directory of rules. Repeatable.
--navigator <FILE> unset Write an ATT&CK Navigator layer (format 4.5) to this file.
--atomics [<PATH_OR_URL>] unset Cross-reference the Atomic Red Team index. A bare --atomics uses the upstream atomics/Indexes/index.yaml; pass a local index.yaml, an atomic-red-team atomics/ directory, or a URL. May also be supplied via coverage.atomics.
--baseline [<PATH_OR_URL>] unset Cross-reference a baseline Navigator layer. A bare --baseline uses the SigmaHQ coverage heatmap; pass a local path or URL. May also be supplied via coverage.baseline.
--targets <FILE> unset Cross-reference a target technique list (one technique ID per line; # comments allowed). May also be supplied via coverage.targets.
--fail-on-gaps off Exit 1 when any requested cross-reference reports uncovered techniques. May also be supplied via coverage.fail_on_gaps.
--config <PATH> unset Load a specific YAML config file instead of running the discovery chain.
--dry-run off Print the effective coverage section and exit 0 without running.

Bare --atomics and --baseline fetch their default upstream sources over HTTP and cache them for 7 days under the user cache directory (~/.cache/rsigma/coverage on Linux), with a stale-cache fallback when offline.

The global --output-format applies: table (the TTY default) renders the human report with gap sections, json emits the single report document, and ndjson/csv/tsv emit one row per technique.

Targets file🔗

# Internal threat-model: techniques we want covered.
T1059        # covered directly
T1059.001    # a sub-technique target
T1003        # uncovered -> fails under --fail-on-gaps

One technique ID per line. Blank lines and # comments are ignored; lines that are not valid technique IDs are skipped with a warning.

Report🔗

The JSON document (--output-format json) has a stable shape:

  • summary: total rules, tagged vs untagged rules, technique and sub-technique counts, and tactic count.
  • techniques[]: per technique, the ID, the tactics its rules tagged, the rule count, and the rule titles.
  • untagged_rules: rules carrying no attack.* tag (a tagging-hygiene signal).
  • atomics (when --atomics is set): atomics_without_rule (detection gaps) and rules_without_atomic (validation gaps).
  • baseline (when --baseline is set): baseline_not_covered (the baseline covers it, you do not) and ahead_of_baseline (you cover it, the baseline does not).
  • targets (when --targets is set): uncovered and covered_via_subtechnique.

Exit codes🔗

Code Meaning
0 Success. With --fail-on-gaps, no requested cross-reference reported uncovered techniques.
1 --fail-on-gaps was set and at least one cross-reference reported uncovered techniques.
2 The rules path could not be read or parsed.
3 A cross-reference input could not be fetched or parsed, or an invalid flag was passed.

Examples🔗

Export a Navigator layer🔗

rsigma rule coverage -r rules/ --navigator coverage.json

Open coverage.json in the ATT&CK Navigator to see the heatmap.

Diff your coverage against the SigmaHQ baseline🔗

rsigma rule coverage -r rules/ --baseline --output-format json | jq '.baseline'

Find techniques with atomics but no detection rule🔗

rsigma rule coverage -r rules/ --atomics --output-format json \
    | jq '.atomics.atomics_without_rule'

Gate CI on a target technique list🔗

rsigma rule coverage -r rules/ --targets threat-model.txt --fail-on-gaps

See also🔗