Post

Writing Portable Sigma Rules

Sigma is the closest thing threat hunters have to a universal rule language. Here's how to write Sigma detections that actually translate cleanly.

Writing Portable Sigma Rules

Portable Sigma logic moving from hunt finding through testing and maintained detection

Write a detection in your SIEM’s native query language and it lives exactly there, tied to that platform, until someone rewrites it from scratch for the next tool. Write it in Sigma and it can go almost anywhere—Splunk, Elastic, Sentinel, QRadar—with a conversion step instead of a rewrite. That portability is the entire reason Sigma matters, and it’s also the reason so many teams write it badly, because portable and platform-specific are two different mindsets.

I’ve reviewed a lot of Sigma rules that technically validate against the schema but fall apart the moment you try to convert them to a second backend. Usually it’s because the author was thinking in their SIEM’s query syntax first and just wrapped it in YAML, instead of thinking in Sigma’s actual logical model.

Field Names Are Where Portability Dies First

The single biggest reason Sigma rules break on conversion is inconsistent field naming. Sigma has a taxonomy—the field mapping conventions defined in its schema—and if you write CommandLine when the taxonomy expects CommandLine mapped correctly through Sysmon’s field set, or you invent your own field name because it’s what your SIEM calls it, the rule converts to garbage or fails outright on a different backend.

Use the official Sigma taxonomy and the established log source definitions (category: process_creation, product: windows, etc.) rather than guessing field names from memory. If you’re writing a rule against Sysmon Event ID 1 data, stick to the documented field mappings—Image, CommandLine, ParentImage, User—rather than whatever your SIEM happens to label that field internally. The conversion tooling (pySigma, sigmac’s successor) handles the SIEM-specific mapping for you, but only if your rule speaks the standard taxonomy in the first place.

Detection Logic: Specific Enough to Fire, Generic Enough to Travel

There’s a tension in every Sigma rule between precision and portability, and getting it wrong in either direction costs you. Too specific—hardcoding a particular file path with a particular casing, or a registry key format specific to one Windows build—and the rule breaks the moment the environment or OS version shifts slightly. Too generic, and you get flooded with false positives once it’s live.

A rule I like as an example of getting this balance right: detecting LSASS access from a non-standard process. Instead of hardcoding a specific tool’s exact command line (which changes constantly as tools get renamed or repacked), the better approach targets the behavior—a process other than a small allowlist of known-legitimate ones (lsass.exe itself, csrss.exe, services.exe, a few others) opening a handle to LSASS with access rights that allow memory reading. That’s specific enough to catch credential dumping techniques broadly, generic enough that it doesn’t care whether the tool calling itself is named mimikatz.exe or something renamed to look innocuous.

Test Against Multiple Backends Before You Trust It

Don’t write a Sigma rule, convert it once to your primary SIEM, confirm it fires in a test environment, and call it done. Run it through pySigma’s conversion for at least two or three different backends even if you’re only deploying to one right now—Splunk SPL, Elastic EQL/KQL, and Sentinel KQL cover most environments people actually run. If the conversion throws warnings or produces obviously malformed logic for a different backend, that’s a signal your original rule leaned on assumptions specific to your primary platform.

This matters more than it sounds like it should, because rules get shared. A rule your team writes today might end up contributed to SigmaHQ’s public repo, picked up by another team running a completely different stack, and if it only actually works on your SIEM, you’ve shipped something that looks portable but isn’t.

False Positive Notes Aren’t Optional Metadata

Sigma’s schema has a falsepositives field, and way too many rules leave it blank or write something unhelpful like “Unknown.” That field is doing real work for the next analyst—write it like you’re handing this rule to someone who’s never seen your environment. “Legitimate use by backup software during scheduled snapshot windows” tells the next hunter something actionable. “Unknown” tells them nothing and means they’ll rediscover the false positive the hard way, probably during an actual incident when they don’t have time for it.

Same goes for the level field—be honest about severity. A rule tagged critical that actually fires on relatively benign admin activity trains your SOC to ignore critical alerts from that rule specifically, and eventually from Sigma-sourced detections generally. Calibrate it against what the behavior actually indicates, not what feels appropriately dramatic.

Version Your Rules, Don’t Just Edit Them

One habit worth building: when you tune a rule based on false positives, don’t just silently edit the logic and lose the history. Sigma supports a modified date and rules can (and should) carry changelog notes in the description or a related-rule reference if you’re forking from an existing SigmaHQ rule. Six months from now, when someone asks why the LSASS rule excludes a particular process, you want that answer documented, not buried in someone’s memory or a Slack thread nobody can find.

Sigma isn’t magic—it doesn’t replace understanding the actual attack technique you’re detecting. But writing it correctly, with portability as a first-class concern rather than an afterthought, means the detection you build today still has value when your team changes SIEMs in two years. That’s a rarer property in this field than it should be.

This post is licensed under CC BY 4.0 by the author.