Skip to content

Commit 42e820f

Browse files
committed
feat: add expr optional chaining (field?.filed) supprt
1 parent 8f1a0df commit 42e820f

File tree

2 files changed

+26
-2
lines changed

2 files changed

+26
-2
lines changed

sigma/backends/golangexpr/golangexpr.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,12 @@ class GolangExprBackend(TextQueryBackend):
4747
field_quote_pattern_negation : ClassVar[bool] = True # Negate field_quote_pattern result. Field name is quoted if pattern doesn't matches if set to True (default).
4848

4949
### Escaping
50-
field_escape : None #ClassVar[str] = "\\" # Character to escape particular parts defined in field_escape_pattern.
50+
# CAUTION: the following could be considered as a slightly hacky solution
51+
# but since expr does not allow any "special" chars in its field names
52+
# absuing the escaping to add `?` to any `.` (https://expr-lang.org/docs/language-definition#optional-chaining) seems reasonable
53+
field_escape : ClassVar[str] = "?" # Character to escape particular parts defined in field_escape_pattern.
5154
field_escape_quote : ClassVar[bool] = True # Escape quote string defined in field_quote
52-
field_escape_pattern : ClassVar[Pattern] = re.compile("\\s") # All matches of this pattern are prepended with the string contained in field_escape.
55+
field_escape_pattern : ClassVar[Pattern] = re.compile(r"\.") # All matches of this pattern are prepended with the string contained in field_escape.
5356

5457
## Values
5558
str_quote : ClassVar[str] = '"' # string quoting character (added as escaping character)

tests/test_backend_golangexpr.py

+21
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import pytest
22
from sigma.collection import SigmaCollection
33
from sigma.backends.golangexpr import GolangExprBackend
4+
from sigma.pipelines.elasticsearch.windows import ecs_windows
5+
from sigma.processing.resolver import ProcessingPipelineResolver
46

57
@pytest.fixture
68
def golangexpr_backend():
@@ -402,6 +404,25 @@ def test_golangexpr_contains_all(golangexpr_backend : GolangExprBackend):
402404
""")
403405
) == ['lower(field) contains lower("value1") and lower(field) contains lower("value2") and (lower(field) contains lower("value1") or lower(field) contains lower("value2"))']
404406

407+
def test_golangexpr_FieldChain():
408+
piperesolver = ProcessingPipelineResolver()
409+
piperesolver.add_pipeline_class(ecs_windows())
410+
combined_pipeline = piperesolver.resolve(piperesolver.pipelines)
411+
assert GolangExprBackend(combined_pipeline).convert(
412+
SigmaCollection.from_yaml(r"""
413+
title: Test
414+
status: test
415+
logsource:
416+
product: windows
417+
service: security
418+
detection:
419+
selection:
420+
CommandLine|contains|all:
421+
- '"set'
422+
- '-f'
423+
condition: selection
424+
""")
425+
) == [r'lower(winlog?.channel) == lower("Security") and lower(process?.command_line) contains lower("\"set") and lower(process?.command_line) contains lower("-f")']
405426

406427
# NOT POSSIBLE IN Expr
407428
# def test_golangexpr_field_name_with_whitespace(golangexpr_backend : GolangExprBackend):

0 commit comments

Comments
 (0)