Sigma Rule Formatter
Reorder a Sigma rule’s top-level keys to the conventional sequence.
Paste a rule on the left.
How it works
Sigma does not require any particular key order, so rules accumulate whatever order their authors happened to
type. A rule set where every rule opens with title and closes with level is markedly
easier to review in a pull request, because the diff shows the change rather than the rearrangement.
The order applied
title → id → related → status → description → references → author → date → modified → tags → logsource → detection → fields → falsepositives → level
A key not in that list keeps its relative position after the ones that are, rather than being dropped or alphabetised. Custom keys exist for reasons a formatter cannot see.
It moves blocks, it does not rewrite them
Each top-level block is lifted whole — its indentation, quoting, block scalars and comments intact — and the blocks are re-emitted in order. Re-parsing the rule and writing it back out would be simpler, and would normalise every quote style and delete every comment. In a detection rule the comment above a filter is often the only record of which incident it was written for, so that is not a trade worth making.
Comments travel with the key above them
A block runs from its key to the next key, so a comment on its own line belongs to whichever key precedes it. A comment written as a heading for the key beneath it will move with the wrong one. Inferring the intent from blank lines would guess, and a formatter that guesses about a detection rule is worse than one with a stated rule.
The result is checked before you see it
The reordered text is parsed again and compared against the original, ignoring key order. If the two disagree by so much as a value, the tool returns nothing and says so rather than handing back a rule that reads correctly and is not. Reordering should be lossless by construction; the check is there for the case where it is not.
Example
The sample opens with level and detection, buries title in the middle, and
carries two blank lines and a comment. Formatting it lifts the metadata to the top in the conventional sequence,
collapses the blank run, and leaves the comment attached to status — the key above it. Every value,
quote and indent inside the blocks is unchanged.
Frequently asked questions
Does reordering change what the rule detects?
No. YAML mappings are unordered, so moving top-level keys cannot change what the rule parses to. The tool proves it rather than asserting it: the reordered text is parsed again and compared against the original ignoring key order, and a mismatch returns nothing instead of a rule that reads correctly and is not.
Why does it not normalise indentation too?
Because doing that safely means re-parsing the rule and writing it back out, which normalises every quote style and deletes every comment. In a detection rule the comment above a filter is often the only record of which incident it was written for. Blocks are lifted whole instead, indentation and all.
What happens to a key that is not in the conventional list?
It keeps its relative position after the keys that are. Custom keys exist for reasons a formatter cannot see, so they are neither dropped nor alphabetised.
Why did my comment end up under the wrong key?
A block runs from its key to the next key, so a comment on its own line belongs to whichever key precedes it. A comment written as a heading for the key beneath it moves with the key above. Inferring intent from blank lines would be guessing, which is worse than a stated rule.
Related tools
Sigma Syntax Viewer
Read a Sigma detection rule as structured logsource and detection blocks.
LocalYARA Rule Formatter
Reformat a YARA rule to consistent indentation and section order.
LocalATT&CK Technique Lookup
Find a MITRE ATT&CK technique by ID or name from a bundled dataset.
LocalHash Identifier
Narrow an unlabelled hash down to the algorithms that could have produced it.
LocalCVSS Calculator
Build or decode a CVSS v3.1 vector and see which metric drives the score.
LocalUser-Agent Parser
Read a User-Agent string, with the token behind every claim and the spoofing tells named.
Local