You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Spun out of SEP #212. The mechanism was raised by @fwosar (let a rule declare the standard it adheres to, so compatibility is explicit and lintable) and given a concrete shape by @thomaspatzke (a top-level attribute naming the spec version a rule uses), refined in his review on this issue to the sigma-version name, a fixed-floor default, and major-version granularity.
Revision history:
2026-06-03: initial proposal. A top-level rule attribute declaring the Sigma specification version a rule targets, defaulting to the latest version the consuming tool supports. Motivated as the general compatibility valve for breaking spec changes, with array matching (SEP SEP: Array Matching in Sigma #212) as the first concrete consumer.
2026-06-03: per @thomaspatzke's review: renamed the attribute from version to sigma-version (it avoids reading as a rule revision number and the risk of colliding with version in private rules); changed the absent-default from "the latest the tool supports" to a fixed floor (the current major, 2), so existing rules keep their semantics and are never silently reinterpreted; reduced granularity to the major version (breaking changes occur only at major bumps); and made declaring sigma-version recommended in all rules, with rules that reference each other required to share a major. The open questions are resolved (see Resolved Questions).
(The change is a single additive top-level attribute. It has cross-cutting interpretive effects, because tools consult it to choose version-sensitive parsing, but it introduces no new detection logic, modifier, or logsource category.)
Abstract
Sigma does not let a rule state which version of the specification it was written against, so a rule means whatever the consuming tool decides whenever the spec is silent or evolving. This blocks deterministic cross-backend interpretation and leaves no clean way to introduce breaking changes.
This proposal adds an optional top-level attribute, sigma-version, to a Sigma document. Its value is the Sigma specification major version (for example 3), because breaking changes occur only at major bumps. When absent, the document targets a fixed floor (the current major, 2), a constant defined by the specification rather than "the latest the tool supports", so every existing rule keeps its current semantics and no rule is silently reinterpreted by a future breaking change. Tools gate version-sensitive interpretation on the declared (or floor) major: a rule on a newer major is read with that major's semantics, an older rule keeps the older semantics where they differ.
This is one field that gates every future breaking change at once, instead of a per-feature escape. The first concrete consumer is array matching (SEP #212, the next major, 3): a rule that declares sigma-version: 3 reads field[any] as a selector, while a rule on major 2 (declared, or by the absent floor) reads brackets literally. The change is fully backward compatible (additive, absent resolves to the fixed floor) and is the spec-governance counterpart to SEP #212's per-feature bracket escaping.
Problem Statement
A Sigma rule today carries no statement of which specification version it targets. The rule fields that look version-like are not this: id and related identify the rule, modified is an edit timestamp, and there is no top-level attribute for the spec the author wrote against. As a result:
Non-deterministic interpretation. Where the specification is silent or where engines have diverged, a rule means whatever the consuming tool decides. This is the same portability gap that motivates SEP SEP: Array Matching in Sigma #212: two backends can read the same rule differently and both believe they are correct.
No clean path for breaking changes. Any change to existing syntax (array-matching bracket semantics being the immediate example) risks reinterpreting rules written before the change. Without a version marker, the only options are a per-feature opt-in escape (the declined |array modifier on SEP SEP: Array Matching in Sigma #212) or silently changing what existing rules mean. A per-feature escape does not scale: every future breaking change would need its own escape hatch.
Compatibility is not lintable. A tool cannot ask "this rule targets version X, do I support X?" and act on the answer, because the rule never states X. Authors cannot pin a rule to the semantics they tested against, and consumers cannot detect a rule that needs a newer engine than they run.
The goal of this SEP is to give a rule a single, explicit place to declare the specification version it targets, so interpretation is deterministic, breaking changes are gated by version rather than per feature, and compatibility is checkable by tools.
Use Cases
Deterministic cross-backend interpretation. A detection engineer authors a rule against a known specification version and wants every converter and evaluator to read it with exactly those semantics, rather than each backend filling spec gaps differently. Declaring sigma-version: 3 pins the interpretation to the major-3 semantics.
Gating a breaking change (array matching). A rule author adopts SEP SEP: Array Matching in Sigma #212 array matching and declares sigma-version: 3, so connections[any] is read as a selector. A rule that omits sigma-version resolves to the floor (major 2) and keeps the pre-array-matching reading of brackets, so neither rule changes meaning on the other's engine.
Lintable engine/tool compatibility. A SIEM administrator runs a converter that supports up to major X. A rule declaring major Y greater than X is flagged at lint or convert time, with a clear "this rule needs a newer engine" error, instead of being silently mis-converted. Conversely, a rule that uses major-3 syntax (the array-matching brackets) without declaring sigma-version: 3 is interpreted at the floor, where those brackets are literal, so a tool can flag the likely mistake.
Detailed Specification
1. The attribute
A Sigma document MAY carry a top-level attribute sigma-version whose value is the major version of the Sigma specification the document targets:
title: Inbound connection to suspicious networksigma-version: 3logsource:
category: network_connectiondetection:
selection:
connections[any]:
protocol: "TCP"ip|cidr: "123.1.0.0/16"condition: selectionlevel: medium
The attribute lives at the top level of the document, alongside title, logsource, and detection. It is the version of the specification, not a revision number for the rule's own content (see Naming and Scope below). The hyphenated name matches Sigma's existing hyphenated keys such as group-by.
2. Value grammar
The value is the Sigma specification major version, an integer:
sigma_version_value = major
major = digit+
A bare integer (sigma-version: 3) is the canonical form. The major alone determines interpretation, because breaking changes occur only at major bumps (per @thomaspatzke); minor and patch releases are backward compatible and never change how an existing rule is read. A tool that is given a full release string ("2.1.0") MUST consider only its major component.
3. Default resolution: the fixed floor
When sigma-version is absent, the document targets the fixed floor: major 2, the v2.x line that is current immediately before this attribute and the first versioned breaking change. The floor is a constant defined by the specification, not "the latest the tool supports", so an absent attribute means the same thing on every tool. Consequences:
Every existing rule (none of which carry the attribute) keeps exactly its current, major-2 semantics, and is never reinterpreted by a future breaking change.
A rule that wants a feature introduced in a later major (array matching, major 3) MUST declare that major explicitly (sigma-version: 3). This is the deliberate trade @thomaspatzke preferred over defaulting to the latest: new features cost one line, in exchange for a clean, deterministic default and zero silent reinterpretation.
Declaring sigma-version is recommended in all new rules, including those that use only floor features, so the targeted semantics are explicit and forward-compatible.
The floor is chosen over "the latest the tool supports" precisely because "latest" differs across tools and reintroduces the cross-tool non-determinism this proposal removes. A fixed floor keeps an unversioned corpus deterministic and stable.
4. Scope: per document, consistent across references
sigma-version applies to the Sigma document that carries it. Sigma rules, correlation rules, and filters are separate document types with their own top-level structure, and each MAY carry its own sigma-version. Per @thomaspatzke:
The attribute SHOULD be declared in all rules, so each document's targeted semantics are explicit rather than relying on the floor.
Documents that reference each other MUST agree on the major version. A correlation rule and the rules it aggregates, and a filter and the rules it targets, share one major, because the referencing document's semantics depend on a consistent reading of the referenced ones. Tools SHOULD reject or warn when cross-referenced documents in the same scope declare different majors.
5. Enforcement and version-sensitive interpretation
Let declared be the resolved major (the attribute value, or the fixed floor 2 when absent) and supported be the highest major the tool implements.
declared greater than supported (rule needs a newer engine). The tool MUST NOT silently interpret the rule under its older semantics. It MUST either reject the rule with an error or skip it, and SHOULD report which major is required versus supported. This is the lintable behavior @fwosar asked for.
declared less than or equal to supported (tool can interpret the rule). The tool interprets the rule under the semantics of declared wherever the specification has a version-sensitive behavior. Where semantics have not changed across majors, the version has no effect.
The first version-sensitive behavior is array-matching bracket interpretation (SEP #212):
Under declared major 3 or higher (the array-matching release), an unescaped, well-formed trailing [...] on a field path is an array selector (field[any], field[0]), and a literal bracket in a field name is written escaped as \[ / \].
Under declared major 2 (declared, or by the absent floor), brackets are not selectors; a field name containing [ or ] is read literally and the array-matching constructs are unavailable.
This gives the spec a general valve: each future breaking change ships in a new major, and sigma-version selects which major a given rule is read under. Per-feature escaping (SEP #212's \[ / \]) and this version field are complementary: escaping writes a literal bracket within the array-matching major, while sigma-version selects whether brackets are selectors at all.
Tools SHOULD document the matrix of version-sensitive behaviors they implement (which major introduced each, and what the pre-change reading was), so rule authors can predict how a given sigma-version value is interpreted.
Naming and Scope
This attribute is the rule declaring the Sigma specification version it targets (a published major such as 3). It is not semantic versioning of the rule's own content (a MAJOR.MINOR.PATCH for rule revisions). The two are different concepts and could coexist later as two separate fields (a spec-version field and a rule-revision field); this proposal covers spec-version targeting only.
The name is sigma-version, resolving the earlier version lead candidate per @thomaspatzke. A bare version reads as a rule revision number rather than a specification target, and risks colliding with a version key already used in private (non-SigmaHQ) rule sets; sigma-version is unambiguous about what it versions and is far less likely to clash. It also reads naturally as "Sigma version 3".
Syntax Examples
A rule that targets major 3, so the brackets are array selectors:
A rule on the floor major (2), where a field name with literal brackets is read literally and needs no escaping, because brackets are not selectors at this major:
title: Legacy field name with literal bracketssigma-version: 2logsource:
category: applicationdetection:
selection:
"args[0]": "literal-field-name"# major 2: brackets are not selectorscondition: selectionlevel: low
A correlation document carrying its own sigma-version, which must match the major of the rules it references:
title: Repeated failed logonssigma-version: 2correlation:
type: event_countrules:
- failed_logon # this referenced rule must also target major 2group-by:
- usertimespan: 10mcondition:
gte: 10
A rule that omits sigma-version (resolves to the fixed floor, major 2, so brackets are literal and array matching is unavailable):
title: OAuth grant includes high-privilege scopelogsource:
product: oktaservice: systemdetection:
selection:
debugContext.debugData.scopes|contains: "admin"condition: selectionlevel: high
Backward Compatibility
Impact: Fully backward compatible.
The attribute is additive and optional. No existing rule carries it, so no existing rule changes shape.
Absent resolves to the fixed floor (major 2), a constant defined by the specification, so the existing corpus is interpreted exactly as it is today, identically on every tool, with no required edits and no cross-tool divergence.
The attribute itself introduces no new detection semantics. It selects which major's semantics apply, which only has an observable effect once a version-sensitive behavior exists (array matching, major 3, being the first).
The fixed floor removes the silent-reinterpretation risk entirely: a breaking change ships in a new major, and absent (or major-2) rules stay on the floor, so they are never reinterpreted. Opting into new behavior requires explicitly declaring the new major. For array matching specifically, no current rule declares major 3, so none gains array-matching bracket semantics by surprise; a field name with literal brackets continues to be read literally.
The attribute is itself additive, so it can be introduced in a minor release on the v2.x line (letting authors and tools begin declaring sigma-version: 2) ahead of the major release that first uses it for gating.
Implementation Areas
YAML structure changes
Sigma conversion tools (pySigma)
Backend updates
Documentation
Submitter Checklist
I have searched existing issues and SEPs to avoid duplicates (this is split out of SEP SEP: Array Matching in Sigma #212, which is referenced).
I have provided concrete examples and use cases.
I have considered backward compatibility implications.
I have thought about implementation complexity (default resolution, enforcement matrix, and a reference implementation).
Array matching is the first breaking change this mechanism gates, and the two proposals were deliberately separated. SEP #212's bracket escaping (\[ / \]) stays as the way to write a literal bracket within the array-matching major; this sigma-version attribute is the orthogonal, general compatibility valve that selects whether brackets are selectors at all. A rule opts into array matching by declaring sigma-version: 3 (the next major); an absent or major-2 rule reads brackets literally. SEP #212 already notes the rule-level spec-version idea as a related, out-of-scope direction and points to this proposal.
Reference implementation
rsigma, a Rust Sigma toolkit that is both a direct evaluator and a multi-backend converter, intends to implement this end-to-end:
The parser reads an optional top-level sigma-version on a Sigma document and resolves it (the declared major, or the fixed floor 2 when absent), exposing it to both evaluation and conversion.
Evaluation and conversion gate version-sensitive interpretation on the resolved major. The array-matching bracket interpretation (selector at major 3 or higher, literal at major 2) is the first such switch.
Linting surfaces the diagnostics in this proposal: an error or skip when a rule declares a major newer than rsigma supports, a warning when a rule uses array-matching syntax without declaring sigma-version: 3 (it would otherwise be read literally at the floor), and a warning when cross-referenced documents declare different majors.
Because rsigma is not tied to one query language, it can act as a neutral check that the floor resolution and enforcement rules behave consistently. Findings will be fed back into this proposal and, if the design holds, into pySigma and the specification.
pySigma support mirrors this: parse the top-level sigma-version on SigmaRule (and correlation/filter documents), default to the fixed floor, expose it to Backend and processing, add a validator for an unsupported major and for cross-reference major mismatches, and gate the same bracket-interpretation switch once array matching lands there.
Proposed spec changes (if accepted)
Sigma rules specification: add the optional top-level sigma-version attribute to the document definition, with its value grammar (the specification major version) and the default-resolution rule (absent resolves to the fixed floor, major 2).
A normative note on enforcement: tools reject or skip a rule whose declared major exceeds what they support, and interpret version-sensitive syntax under the declared major.
A consistency note: cross-referencing documents (correlation rules and the rules they aggregate, filters and the rules they target) share a major.
A versioning-policy note tying breaking spec changes to major releases, with array matching (major 3) as the worked first example.
Attribute name. Resolved as sigma-version (not version). A bare version could be read as a rule revision number and risks colliding with a version key in private rule sets; sigma-version is unambiguous. A separate field for rule-content versioning is not part of this SEP but is not precluded.
Default policy. Resolved as a fixed floor (major 2) rather than "the latest the tool supports". The floor keeps the unversioned corpus deterministic and never silently reinterprets it; the cost is that rules using a new major's features must declare that major, which is acceptable.
Granularity. Resolved as the major version only. Breaking changes occur only at major bumps, so the major alone determines interpretation; minor and patch releases are backward compatible.
Migration. Resolved by the fixed floor: the existing corpus carries no sigma-version, resolves to the floor (major 2), and keeps exactly its current semantics, so no current rule is reinterpreted. The same policy applies to every future breaking change (it ships in a new major; absent rules stay on the floor).
Per-document scope. Resolved: sigma-version SHOULD be declared in all rules, and documents that reference each other MUST share the same major. Tools SHOULD reject or warn on a cross-reference major mismatch.
Remaining Questions
Whether the attribute should be introduced in a v2.x minor release (so authors and tools can adopt sigma-version: 2 before the first gated major ships) or only alongside the major it first gates.
Whether a cross-reference major mismatch is a hard error or a warning, and whether tools should attempt to interpret each document at its own declared major regardless.
SEP: Rule-Level Specification Version Declaration
Author(s)
Mostafa Moradian et al.
SEP Type
New Rule Fields (metadata, configuration options)
(The change is a single additive top-level attribute. It has cross-cutting interpretive effects, because tools consult it to choose version-sensitive parsing, but it introduces no new detection logic, modifier, or logsource category.)
Abstract
Sigma does not let a rule state which version of the specification it was written against, so a rule means whatever the consuming tool decides whenever the spec is silent or evolving. This blocks deterministic cross-backend interpretation and leaves no clean way to introduce breaking changes.
This proposal adds an optional top-level attribute,
sigma-version, to a Sigma document. Its value is the Sigma specification major version (for example3), because breaking changes occur only at major bumps. When absent, the document targets a fixed floor (the current major,2), a constant defined by the specification rather than "the latest the tool supports", so every existing rule keeps its current semantics and no rule is silently reinterpreted by a future breaking change. Tools gate version-sensitive interpretation on the declared (or floor) major: a rule on a newer major is read with that major's semantics, an older rule keeps the older semantics where they differ.This is one field that gates every future breaking change at once, instead of a per-feature escape. The first concrete consumer is array matching (SEP #212, the next major,
3): a rule that declaressigma-version: 3readsfield[any]as a selector, while a rule on major2(declared, or by the absent floor) reads brackets literally. The change is fully backward compatible (additive, absent resolves to the fixed floor) and is the spec-governance counterpart to SEP #212's per-feature bracket escaping.Problem Statement
A Sigma rule today carries no statement of which specification version it targets. The rule fields that look version-like are not this:
idandrelatedidentify the rule,modifiedis an edit timestamp, and there is no top-level attribute for the spec the author wrote against. As a result:|arraymodifier on SEP SEP: Array Matching in Sigma #212) or silently changing what existing rules mean. A per-feature escape does not scale: every future breaking change would need its own escape hatch.The goal of this SEP is to give a rule a single, explicit place to declare the specification version it targets, so interpretation is deterministic, breaking changes are gated by version rather than per feature, and compatibility is checkable by tools.
Use Cases
sigma-version: 3pins the interpretation to the major-3 semantics.sigma-version: 3, soconnections[any]is read as a selector. A rule that omitssigma-versionresolves to the floor (major2) and keeps the pre-array-matching reading of brackets, so neither rule changes meaning on the other's engine.sigma-version: 3is interpreted at the floor, where those brackets are literal, so a tool can flag the likely mistake.Detailed Specification
1. The attribute
A Sigma document MAY carry a top-level attribute
sigma-versionwhose value is the major version of the Sigma specification the document targets:The attribute lives at the top level of the document, alongside
title,logsource, anddetection. It is the version of the specification, not a revision number for the rule's own content (see Naming and Scope below). The hyphenated name matches Sigma's existing hyphenated keys such asgroup-by.2. Value grammar
The value is the Sigma specification major version, an integer:
A bare integer (
sigma-version: 3) is the canonical form. The major alone determines interpretation, because breaking changes occur only at major bumps (per @thomaspatzke); minor and patch releases are backward compatible and never change how an existing rule is read. A tool that is given a full release string ("2.1.0") MUST consider only its major component.3. Default resolution: the fixed floor
When
sigma-versionis absent, the document targets the fixed floor: major2, the v2.x line that is current immediately before this attribute and the first versioned breaking change. The floor is a constant defined by the specification, not "the latest the tool supports", so an absent attribute means the same thing on every tool. Consequences:3) MUST declare that major explicitly (sigma-version: 3). This is the deliberate trade @thomaspatzke preferred over defaulting to the latest: new features cost one line, in exchange for a clean, deterministic default and zero silent reinterpretation.sigma-versionis recommended in all new rules, including those that use only floor features, so the targeted semantics are explicit and forward-compatible.The floor is chosen over "the latest the tool supports" precisely because "latest" differs across tools and reintroduces the cross-tool non-determinism this proposal removes. A fixed floor keeps an unversioned corpus deterministic and stable.
4. Scope: per document, consistent across references
sigma-versionapplies to the Sigma document that carries it. Sigma rules, correlation rules, and filters are separate document types with their own top-level structure, and each MAY carry its ownsigma-version. Per @thomaspatzke:5. Enforcement and version-sensitive interpretation
Let
declaredbe the resolved major (the attribute value, or the fixed floor2when absent) andsupportedbe the highest major the tool implements.declaredgreater thansupported(rule needs a newer engine). The tool MUST NOT silently interpret the rule under its older semantics. It MUST either reject the rule with an error or skip it, and SHOULD report which major is required versus supported. This is the lintable behavior @fwosar asked for.declaredless than or equal tosupported(tool can interpret the rule). The tool interprets the rule under the semantics ofdeclaredwherever the specification has a version-sensitive behavior. Where semantics have not changed across majors, the version has no effect.The first version-sensitive behavior is array-matching bracket interpretation (SEP #212):
declaredmajor3or higher (the array-matching release), an unescaped, well-formed trailing[...]on a field path is an array selector (field[any],field[0]), and a literal bracket in a field name is written escaped as\[/\].declaredmajor2(declared, or by the absent floor), brackets are not selectors; a field name containing[or]is read literally and the array-matching constructs are unavailable.This gives the spec a general valve: each future breaking change ships in a new major, and
sigma-versionselects which major a given rule is read under. Per-feature escaping (SEP #212's\[/\]) and this version field are complementary: escaping writes a literal bracket within the array-matching major, whilesigma-versionselects whether brackets are selectors at all.Tools SHOULD document the matrix of version-sensitive behaviors they implement (which major introduced each, and what the pre-change reading was), so rule authors can predict how a given
sigma-versionvalue is interpreted.Naming and Scope
This attribute is the rule declaring the Sigma specification version it targets (a published major such as
3). It is not semantic versioning of the rule's own content (aMAJOR.MINOR.PATCHfor rule revisions). The two are different concepts and could coexist later as two separate fields (a spec-version field and a rule-revision field); this proposal covers spec-version targeting only.The name is
sigma-version, resolving the earlierversionlead candidate per @thomaspatzke. A bareversionreads as a rule revision number rather than a specification target, and risks colliding with aversionkey already used in private (non-SigmaHQ) rule sets;sigma-versionis unambiguous about what it versions and is far less likely to clash. It also reads naturally as "Sigma version 3".Syntax Examples
A rule that targets major 3, so the brackets are array selectors:
A rule on the floor major (
2), where a field name with literal brackets is read literally and needs no escaping, because brackets are not selectors at this major:A correlation document carrying its own
sigma-version, which must match the major of the rules it references:A rule that omits
sigma-version(resolves to the fixed floor, major2, so brackets are literal and array matching is unavailable):Backward Compatibility
Impact: Fully backward compatible.
2), a constant defined by the specification, so the existing corpus is interpreted exactly as it is today, identically on every tool, with no required edits and no cross-tool divergence.3, being the first).3, so none gains array-matching bracket semantics by surprise; a field name with literal brackets continues to be read literally.sigma-version: 2) ahead of the major release that first uses it for gating.Implementation Areas
Submitter Checklist
Implementation Assistance
Yes, I can help with implementation.
Additional Context
Relationship to array matching (SEP #212)
Array matching is the first breaking change this mechanism gates, and the two proposals were deliberately separated. SEP #212's bracket escaping (
\[/\]) stays as the way to write a literal bracket within the array-matching major; thissigma-versionattribute is the orthogonal, general compatibility valve that selects whether brackets are selectors at all. A rule opts into array matching by declaringsigma-version: 3(the next major); an absent or major-2 rule reads brackets literally. SEP #212 already notes the rule-level spec-version idea as a related, out-of-scope direction and points to this proposal.Reference implementation
rsigma, a Rust Sigma toolkit that is both a direct evaluator and a multi-backend converter, intends to implement this end-to-end:
sigma-versionon a Sigma document and resolves it (the declared major, or the fixed floor2when absent), exposing it to both evaluation and conversion.3or higher, literal at major2) is the first such switch.sigma-version: 3(it would otherwise be read literally at the floor), and a warning when cross-referenced documents declare different majors.Because rsigma is not tied to one query language, it can act as a neutral check that the floor resolution and enforcement rules behave consistently. Findings will be fed back into this proposal and, if the design holds, into pySigma and the specification.
pySigma support mirrors this: parse the top-level
sigma-versiononSigmaRule(and correlation/filter documents), default to the fixed floor, expose it toBackendand processing, add a validator for an unsupported major and for cross-reference major mismatches, and gate the same bracket-interpretation switch once array matching lands there.Proposed spec changes (if accepted)
sigma-versionattribute to the document definition, with its value grammar (the specification major version) and the default-resolution rule (absent resolves to the fixed floor, major2).3) as the worked first example.Resolved Questions
All five questions from the initial draft are resolved by @thomaspatzke's review:
sigma-version(notversion). A bareversioncould be read as a rule revision number and risks colliding with aversionkey in private rule sets;sigma-versionis unambiguous. A separate field for rule-content versioning is not part of this SEP but is not precluded.2) rather than "the latest the tool supports". The floor keeps the unversioned corpus deterministic and never silently reinterprets it; the cost is that rules using a new major's features must declare that major, which is acceptable.sigma-version, resolves to the floor (major2), and keeps exactly its current semantics, so no current rule is reinterpreted. The same policy applies to every future breaking change (it ships in a new major; absent rules stay on the floor).sigma-versionSHOULD be declared in all rules, and documents that reference each other MUST share the same major. Tools SHOULD reject or warn on a cross-reference major mismatch.Remaining Questions
sigma-version: 2before the first gated major ships) or only alongside the major it first gates.