Skip to content

fix: OR/AND precedence inversion widens emitted queries in SPL and SPL2 backends - #77

Merged
thomaspatzke merged 2 commits into
SigmaHQ:mainfrom
cristianchiriac:fix/or-and-precedence
Sep 19, 2026
Merged

thomaspatzke merged 2 commits into
SigmaHQ:mainfrom
cristianchiriac:fix/or-and-precedence

Conversation

@cristianchiriac

@cristianchiriac cristianchiriac commented Sep 17, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Fixes #73.

Both the classic SPL backend (splunk.py) and the SPL2 backend (spl2.py) declared their operator precedence as (ConditionNOT, ConditionOR, ConditionAND) — i.e. OR binds tighter than AND. But:

  • splunk.py emits AND as juxtaposition (and_token = " "), which in SPL binds tighter than an explicit OR.
  • spl2.py emits explicit AND/OR tokens, which follow standard boolean precedence (AND binds tighter than OR).

In both cases the declared precedence was inverted relative to the language actually being emitted, so compare_precedence concluded that an OR nested inside an AND does not need group_expression parentheses, and omitted them. The resulting query is broader than the rule: the AND-ed conjuncts apply only to the first disjunct, and every later disjunct matches unscoped.

from sigma.collection import SigmaCollection
from sigma.backends.splunk import SplunkBackend
from sigma.pipelines.splunk import splunk_windows_pipeline

RULE = """
title: OR group ANDed with a scope predicate
logsource:
    category: process_creation
    product: windows
detection:
    selection_img:
        - Image|endswith: '\\net.exe'
        - OriginalFileName: 'net.exe'
    selection_cli:
        CommandLine|contains: ' localgroup'
    condition: selection_img and selection_cli
"""
print(SplunkBackend(splunk_windows_pipeline()).convert(SigmaCollection.from_yaml(RULE))[0])

Before: Image="*\\net.exe" OR OriginalFileName="net.exe" CommandLine="* localgroup*" — SPL parses this as (Image=...) OR (OriginalFileName=... AND CommandLine=...), so a bare Image match fires with no CommandLine requirement at all.

After: (Image="*\\net.exe" OR OriginalFileName="net.exe") CommandLine="* localgroup*" — matches the rule's condition. The SPL2 backend had the identical bug for the same underlying reason and is fixed the same way.

Fix

Reorder the precedence tuple to (ConditionNOT, ConditionAND, ConditionOR) in both splunk.py and spl2.py, matching the actual precedence of the language each backend emits.

A few existing tests encoded the same bug in their expected output (an ungrouped OR nested in an AND, e.g. the CIDR-expansion and data-model tests) — those are updated to the correct, parenthesized form. A couple of others (the multi-valued-field IN(...) cases, and an AND nested in OR that no longer needs its parens) gain or lose harmless-but-no-longer-necessary grouping; updated their expected output too.

Test plan

  • Added test_splunk_or_nested_in_and_expression, reproducing the issue's example directly against the SPL backend.
  • pytest — full suite passes (128 passed).

… query

The backend declared operator precedence as (NOT, OR, AND) while
emitting AND as juxtaposition (' '), which in SPL binds tighter than
an explicit OR. Because the declared precedence was inverted relative
to the emitted language, compare_precedence omitted the parentheses
an OR needs when nested inside an AND, so the AND-ed conjuncts only
applied to the first disjunct and every later disjunct matched
unscoped.

Reordering the precedence tuple to (NOT, AND, OR) fixes the grouping.
Several existing tests encoded the same bug in their expected output
(an ungrouped OR nested in an AND) and are updated to the correct,
parenthesized form; a couple of others gained harmless (but no longer
necessary) grouping around already self-contained IN(...) expressions.
spl2.py declared the same inverted precedence as splunk.py (OR before
AND), but SPL2's AND/OR tokens follow standard boolean precedence
where AND binds tighter than OR. An OR nested inside an AND was
missing its required parentheses for the same reason as SigmaHQ#73.
@cristianchiriac cristianchiriac changed the title fix: OR nested inside AND was not parenthesized, widening the emitted query fix: OR/AND precedence inversion widens emitted queries in SPL and SPL2 backends Sep 17, 2026
@thomaspatzke
thomaspatzke merged commit cd64c39 into SigmaHQ:main Sep 19, 2026
4 checks passed
thomaspatzke pushed a commit that referenced this pull request Sep 27, 2026
The Splunk search command evaluates OR before AND (parentheses, NOT, OR, AND), unlike eval/where. Group every AND nested in an OR (rule and extended correlation conditions) so the emitted query is correct under either precedence reading, keeping the OR-under-AND grouping from #77. Only hoist leading terms in front of the rex/eval pipeline when the search expression has no top-level OR.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Splunk backend precedence declares OR tighter than AND, dropping required parentheses (queries are broader than the rule)

2 participants