# Sigma rules for chainsaw

This directory holds the SigmaHQ rule pack that chainsaw evaluates
against endpoint event logs. Rules are NOT vendored in git; the
patch-zip build pipeline materialises them on demand by running
`fetch.ps1` (Windows) or `fetch.py` (Linux/CI), which queries the
GitHub Releases API and downloads the `sigma_all_rules.zip` asset
from a pinned SigmaHQ release.

## Why fetch the asset zip, not the source tree

SigmaHQ publishes pre-packaged rule asset zips on every release.
Those are the canonical artifact: stable filenames, audited
contents, immune to source-tree reorganisations. Earlier versions
of this fetcher tried to pull `/archive/refs/heads/main.zip` and
broke when SigmaHQ renamed branches. The release asset path is
the durable one.

## Refreshing the rule pack

The fetcher defaults to "latest release" if no tag is pinned:

```powershell
task sigma-rules
# Fetches whatever release is currently flagged "latest" on
# https://github.com/SigmaHQ/sigma/releases.
```

For production builds, pin to a specific release tag so the
shipped rule set is auditable + reproducible. Two ways:

**One-off (CLI override):**

```powershell
powershell -File pulse-patch\shared\sigma\fetch.ps1 -Tag r2025-01-15
```

**Persistent (edit script):**

Set `$script:DefaultTag` in `fetch.ps1` AND `DEFAULT_TAG` in
`fetch.py` to the same value. Commit both edits in one go so
Windows + Linux/CI build hosts stay in sync on which snapshot
they ship.

## Two fetchers, one output

- `fetch.ps1` -- Windows build hosts. Uses only Windows
  PowerShell 5.1 builtins. No Python required.
- `fetch.py`  -- Linux / macOS / CI build hosts. Stdlib only.

`task sigma-rules` dispatches by host OS; you don't pick which
runs. Both produce identical rule trees.

## What ships in `sigma_all_rules.zip`

Everything SigmaHQ has -- Windows event log rules, Linux auditd,
macOS, network, cloud, web. Chainsaw is only configured to hunt
Windows event logs so the non-Windows rules sit on disk but
never evaluate. The cost is ~3-5 MB extra in the patch zip plus
disk on each endpoint; the benefit is one canonical artifact
rather than the maintenance of a Windows-only subset filter.

If patch-zip size or per-endpoint disk becomes a problem, the
fetcher can be tightened to extract only `windows/` subtrees by
adding a path prefix filter in the extract loop. Left as a
future optimisation; for now, the simpler all-rules layout
matches what the SOC team is auditing manually.

## What to commit

- `fetch.ps1` + `fetch.py` -- yes (build pipeline calls them)
- `README.md` -- yes
- `windows/`, `linux/`, etc. rule trees -- NO (gitignored;
  re-fetched per build)

## Where rules end up on the endpoint

The patch-zip overlay extracts to `C:\Program Files (x86)\ossec-agent\`,
so this directory becomes:

```
C:\Program Files (x86)\ossec-agent\shared\sigma\
                                          \windows\...
                                          \linux\...
                                          \macos\...
                                          \cloud\...
                                          ...
```

`chainsaw.ps1` invokes `chainsaw.exe` with
`-s C:\Program Files (x86)\ossec-agent\shared\sigma` so the hunt
walks the whole tree.
