Checking SigmaHQ rules against real field lists
2026-07-08. Commands to reproduce at the end.
I ran detsema check over the Sysmon-backed part of
SigmaHQ/sigma (fe2a6e8: 20 rule categories, 2,054 rules)
using two field lists as ground truth:
- What Sysmon emits per event type, from the OSSEM-DD data dictionaries.
- The process_creation field table in the Sigma taxonomy appendix (v2.1.0), which defines the field names rules on the official repo may use.
Against Sysmon’s fields: 19 findings, one root cause
19 findings across 13 rules, under 0.7% of the corpus. Every one is the same problem: the rule
filters on process context that its event type doesn’t carry. Sysmon network, image-load and
file events have no CommandLine or ParentImage; remote-thread events have no
SourceCommandLine or TargetParentProcessId. These rules depend on an enrichment step,
usually an EDR, joining process information onto the event.
Where the missing field sits in the rule decides the failure mode:
- In the selection: the rule goes quiet.
file_event_win_exchange_webshell_droprequiresCommandLine|contains: 'MSExchange'on a file event, so on unenriched Sysmon its selection is unsatisfiable and the rule never fires. - Handled deliberately:
net_connection_win_susp_binary_no_cmdlinecarries the comment# e.g. Sysmon has no CommandLine field in network events with ID 3and a null filter for that case. The dependency is real enough that the author tracked it by hand. - In a filter: the rule gets louder.
create_remote_thread_win_susp_uncommon_source_imageexcludes known-good activity viaTargetParentProcessId; the filter never matches on plain Sysmon, so the exclusions don’t apply and the rule fires more often than intended.
The rules are correct for the enriched pipelines they were written on. Which of them work on a given pipeline is a schema question, and schema questions can be answered in CI rather than during triage.
One detsema fix came out of the run: check used to claim a missing field “can never match”
in all cases. For field: null tests the opposite holds (an absence test on a never-present
field always passes), and the finding text now distinguishes the two.
Against the taxonomy’s field table
The 1,182 process_creation rules, checked against the table that defines their allowed field names:
| Field | Rules using it | Emitted by Sysmon | In the taxonomy table |
|---|---|---|---|
OriginalFileName |
580 (49%) | yes | no |
Hashes |
39 | yes | no (only the split md5/sha1/sha256/imphash forms) |
ParentUser |
2 | yes | no |
Fix submitted: sigma-specification#215.
Reproduce
go install github.com/Big-Comfy/detsema/cmd/detsema@latest
git clone --depth 1 https://github.com/SigmaHQ/sigma /tmp/sigma
git clone --depth 1 https://github.com/OTRF/OSSEM-DD /tmp/ossem
# build a field list for process_creation (Sysmon event 1) from OSSEM
go run github.com/Big-Comfy/detsema/contrib/ossem2inv@latest \
-ossem /tmp/ossem/windows/sysmon/events/event-1.yml \
-source "OSSEM-DD sysmon event 1" -out proc_creation.json
detsema check --rules /tmp/sigma/rules/windows/process_creation \
--schema proc_creation.json --format jsonl --fail-on never
Notes: rule directories are trusted to match their declared logsource categories (true in
SigmaHQ). OSSEM-DD lags the newest Sysmon event types, so events 24-25 and 27-29 were declared
by hand from Sysmon’s documentation. Without the envelope fields most pipelines add to every
event (EventID, Provider_Name, Channel, Computer) the count is 23 findings rather
than 19.