Skip to main content

Honest Sigma-rule backtest harness

Project description

sigmaforge

Honest Sigma-rule backtest harness. Measures detection rules against real log corpora and reports two numbers per rule — recall (does it catch attacks of its ATT&CK sub-technique?) and precision / false-positives (does it fire on benign activity?) — with honesty gates that return unmeasured instead of a fake 0 or a tautological 1.0 when the data can't support a number.

CI python license

[!NOTE] Learning / portfolio project, built by directing AI coding agents. Christian Huhn (photography → SOC career change) designed, reviewed, and gated the work; the implementation was AI-pair-programmed. It is an honest measurement harness, not a polished product — see Status below for exactly what works and what doesn't yet.

What problem it solves

Every SOC ships dozens to hundreds of detection rules and rarely measures them. sigmaforge answers two questions with reproducible evidence:

  • Which rules are noise generators? (high false-positives on legitimate activity)
  • Which rules catch nothing? (zero recall against real attacks of their technique)

Example finding from a real run: Suspicious Windows Service Tampering produced 66 false-positives on a benign corpus — every one a Ninite / TeamViewer installer, not an attack.

How it actually works

flowchart LR
    R[SigmaHQ rules] -->|partition high/critical| C[compile to one Zircolite ruleset]
    C --> E[Zircolite engine]
    A[(attack corpus<br/>sub-technique-labeled)] --> E
    B[(benign corpus<br/>Nextron + OpTC)] --> E
    E --> S[score: recall per technique<br/>+ precision/FP label-aware]
    S --> G[honesty gates<br/>floor · positive-control · no-self-review]
    G --> O[report.md + manifest]

The pipeline is one module (sigmaforge.pipeline); the CLI and the scripts/run*_backtest.py runs call the same code — there is no weaker shipped path. Two verbs, split by honesty (you cannot compute recall/precision without labels):

# pip-runnable: rules x ARBITRARY logs -> hits only (no labels -> precision/recall = unmeasured).
# Needs only the engine, no corpora.
sigmaforge hunt --rules my_rules/ --logs /path/to/logs

# the real measurement: rules x LABELED corpora -> per-technique recall + label-aware
# precision + honesty gates + report.md + manifest.json. Needs the corpora (else it
# prints a teaching error and points you at `hunt`).
sigmaforge backtest --rules my_rules/ --config sigmaforge.yaml

--rules takes a single .yml or a directory (auto-compiled). The engine + corpora are not bundled (see Reproduce a backtest); the committed reports/run*.md are inspectable without running anything.

Status

Area State
Recall (per sub-technique, no sibling dilution) Working — 338/609 rules measurable, 70 fire (run5)
Precision / false-positives (label-aware, gated) Working — 7/609 measurable on current benign corpus (run6)
Honesty gates (floor, positive-control, no-self-review) Working
Reproducible manifest (run_hash, corpus SHAs, provenance) Working
One-command CLI (sigmaforge backtest + hunt) Working — same pipeline as the scripts (extracted to sigmaforge.pipeline); hunt is pip-runnable without corpora
Self-generated benign corpus Kit ready (scripts/selfgen/), needs a Windows VM run

[!IMPORTANT] The log corpora are not shipped. They are large, separately licensed, and gitignored. pip install sigmaforge installs the harness code, not the data — a full end-to-end backtest needs the corpora and a local Zircolite checkout (also not bundled). The package is useful as a library / reference; the runnable pipeline needs the local setup documented in scripts/.

Install

pip install sigmaforge

Installs the harness package and the sigmaforge CLI. The detection engine (Zircolite) and the log corpora are obtained separately (see above).

Corpora used (all verified, portfolio-safe licenses)

Corpus Role License
splunk/attack_data recall (sub-technique-labeled attacks) Apache-2.0
DARPA OpTC precision (real enterprise benign week) Public domain
NextronSystems/evtx-baseline precision (goodware baseline) Apache-2.0
Self-generated (scripts/selfgen/) precision (targeted admin/LOLBin noise) your own lab

Reproduce a backtest from a clone

The pip package is the library/CLI; a full end-to-end backtest needs the engine and corpora, which are not bundled (engine = large third-party tool; corpora = large and separately licensed). To go from a fresh clone to a runnable backtest:

uv sync --group backtest          # script deps (pyyaml, evtx, gdown)
bash scripts/setup_engine.sh      # fetch Zircolite 3.7.6 + its runtime deps

Then obtain the corpora (see the table above) into ~/sigmaforge-v0/ and build the combined samples with the scripts/build_*_benign.py / scripts/build_*_corpus.py helpers, compile the ruleset, and run a backtest:

uv run python scripts/compile_loaded_ruleset.py   # SigmaHQ rules -> one Zircolite ruleset
uv run python scripts/run7_backtest.py            # -> reports/run7.md (+ manifest)

Run scripts from the repo root (the engine working dir defaults to the current directory; override with SIGMAFORGE_HOME if you keep Zircolite/ elsewhere). The reports/run*.md + *_manifest.json are committed so the results are inspectable without re-running.

Development

Built with the Shipwright dev framework.

uv sync --dev
uv run pytest        # 113 tests (engine-dependent tests skip without Zircolite)
uv run ruff check .

License

MIT © Christian Huhn. Corpus data retains its upstream license (see table above).

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sigmaforge-0.4.0.tar.gz (53.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sigmaforge-0.4.0-py3-none-any.whl (39.8 kB view details)

Uploaded Python 3

File details

Details for the file sigmaforge-0.4.0.tar.gz.

File metadata

  • Download URL: sigmaforge-0.4.0.tar.gz
  • Upload date:
  • Size: 53.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for sigmaforge-0.4.0.tar.gz
Algorithm Hash digest
SHA256 881ac92697381b4820d8a793cf4d9fffa78f7c106938f9b3b026431b8e1b799d
MD5 c668e5e25fae19ec783b3e40a52a86f2
BLAKE2b-256 28bd17db4b6e25edabebe8976421bd1cf671a92aa79593225e2a61ed28e9221e

See more details on using hashes here.

Provenance

The following attestation bundles were made for sigmaforge-0.4.0.tar.gz:

Publisher: release.yml on duathron/sigmaforge

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sigmaforge-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: sigmaforge-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 39.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for sigmaforge-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 01d08b8c5f10dcfaee46f3c6ad9968658f4fbe3b035f16968bbe336c97160a6d
MD5 834bfe24df8fa47b2c813c9074407187
BLAKE2b-256 10e34b66557324ae95c9ebd916750f15ee78399524c7af259df92dfd1a90ec9a

See more details on using hashes here.

Provenance

The following attestation bundles were made for sigmaforge-0.4.0-py3-none-any.whl:

Publisher: release.yml on duathron/sigmaforge

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page