A Sigma rule is an abstract description of bad behavior. Something has to turn it into a query your SIEM will run, and that conversion has two independent halves. Get one right and the other wrong and you ship a rule that runs cleanly and returns nothing, forever.
The two halves
- Backend - the target query language: Splunk SPL, Elasticsearch, Microsoft Sentinel KQL, and others.
- Pipeline - the mapping layer. It rewrites Sigma's generic field names into whatever your data actually calls them, and adds the scope condition (index, table, channel, Event ID) that points the query at the right rows.
With sigma-cli, list what you actually have installed rather than trusting any article's names:
sigma list targets
sigma list pipelines
sigma convert -t splunk -p sysmon rules/proc_creation_win_encoded_powershell.yml
A process-creation rule converted for Splunk over Sysmon data comes out shaped roughly like this:
Image="*\\powershell.exe" (CommandLine="*-enc*" OR CommandLine="*-EncodedCommand*")
Why the same rule needs a different pipeline per data source
Sigma's generic Windows field names come from Sysmon. Almost nothing else uses them:
- Process path - Sysmon
Image, Security 4688NewProcessName, ECSprocess.executable, Defender advanced huntingFolderPath. - Command line - Sysmon
CommandLine, ECSprocess.command_line, DefenderProcessCommandLine. - Parent - Sysmon
ParentImage, Security 4688ParentProcessName, ECSprocess.parent.executable, DefenderInitiatingProcessFolderPath.
The pipeline also supplies the scope. Nothing in the rule body says "only Sysmon Event ID 1" - the pipeline adds that. Convert with no pipeline and you get a syntactically valid query aimed at fields that do not exist in your index.
The four failure modes
- The silent zero. The query references
Image; your index storesprocess.executable. Zero results, no error. A rule that cannot fire and a rule with nothing to find look identical on a dashboard. - Case sensitivity. Sigma matching is case-insensitive by default; several backends and field types are not. Check how yours treats
PowerShell.exeversuspowershell.exebefore you rely on it. - Escaping.
|containsbecomes*value*, and Windows paths carry backslashes that must survive both YAML and the query language. Read the generated query and look for mangled separators. - Mapped but not collected. The pipeline happily maps
Hasheseven though your Sysmon config never logs it. Mapping is not collection.
Prove the conversion, every time
Convert, then run the query over a window where you know the behavior occurred: an old incident, a lab replay, or a purple-team execution you just performed. One confirmed hit is the whole difference between "deployed" and "working".
Then keep the generated query out of your source of truth. The YAML is the rule; the SIEM query is a build artifact you can regenerate.
