Skip to content

fix(sigma): generated IOC rules now OR across observable types - #13

Merged
SkxOverKill merged 2 commits into
SkxOverKill:mainfrom
nkbeast:fix/sigma-rule-selection-logic
Aug 11, 2026
Merged

fix(sigma): generated IOC rules now OR across observable types#13
SkxOverKill merged 2 commits into
SkxOverKill:mainfrom
nkbeast:fix/sigma-rule-selection-logic

Conversation

@nkbeast

@nkbeast nkbeast commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

What changed

Two fixes to the Sigma rule generator (src/lib/sigma/generate.ts):

  1. Generated IOC rules no longer require all types to match in one event. The network, file-hash, and host-artifact generators put every observable type into a single flat selection map with a 1 of selection* condition. In Sigma, one selection map ANDs its fields — so the network blocklist rule only fired when a single event contained a matching domain and IP and URL at once (effectively never). Each type is now emitted as its own selection_* sub-selection so 1 of selection* means "any type matches", which is what a blocklist rule intends.

  2. MD5/SHA1 hash rules use Sysmon's Hashes field. The old rules emitted md5|contains / sha1|contains — not standard Sigma fields for Windows process creation, so they match nothing in most backends. All three hash types now match Hashes|contains with the ALGO=<hex> value.

Plus a small consistency fix: the T1505.003 web-shell entry declared a webserver logsource at the map level while its build() emits file_event — the outer value was dead config and is now aligned.

How verified

  • Added src/lib/sigma/generate.test.ts (5 tests) asserting sub-selection structure, Hashes field usage, and YAML output.
  • npm run test: 175 passed (12 files).
  • npm run lint / npm run typecheck: no new issues vs main (the remaining extract.ts typecheck errors and unused-var warnings are pre-existing on the base branch).

Generated rules put every observable type into one flat `selection` map with
a `1 of selection*` condition. In Sigma a single selection map ANDs its
fields, so a network blocklist rule only fired when one event contained a
matching domain AND IP AND URL simultaneously — which almost never happens,
silently neutering the rules. The same applied to hash and host-artifact
rules.

Split each generator into `selection_*` sub-selections (DNS/IP/URL,
SHA256/MD5/SHA1, mutex/filename/regkey) so `1 of selection*` means "any
type matches", and switch MD5/SHA1 to Sysmon's `Hashes` field (plain
`md5`/`sha1` fields are not standard Sigma fields and match nothing in
most backends).
The web-shell entry declared a `webserver` logsource at the map level but
its build() emits `file_event`, so the outer value was dead config that
disagreed with the generated rule. Align it to what the rule actually uses.
@nkbeast
nkbeast requested a review from SkxOverKill as a code owner August 11, 2026 14:27
@SkxOverKill
SkxOverKill merged commit 4afbff8 into SkxOverKill:main Aug 11, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants