Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 24 additions & 18 deletions sigma/cli/rules.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from pathlib import Path
from sys import stderr
import click
import yaml
from sigma.collection import SigmaCollection
from sigma.exceptions import SigmaCollectionError


def load_rules(input, file_pattern):
Expand All @@ -10,27 +12,31 @@ def load_rules(input, file_pattern):
"""
rule_collection = SigmaCollection([], [])

for path in list(input):
if path == Path("-"):
rule_collection = SigmaCollection.merge([
rule_collection,
SigmaCollection.from_yaml(click.get_text_stream("stdin"))
])
else:
rule_paths = SigmaCollection.resolve_paths(
[path],
recursion_pattern="**/" + file_pattern,
)
with click.progressbar(
list(rule_paths), label="Parsing Sigma rules", file=stderr
) as progress_rule_paths:
try:
for path in list(input):
if path == Path("-"):
rule_collection = SigmaCollection.merge([
rule_collection,
SigmaCollection.load_ruleset(
progress_rule_paths,
collect_errors=True,
)
SigmaCollection.from_yaml(click.get_text_stream("stdin"))
])
else:
rule_paths = SigmaCollection.resolve_paths(
[path],
recursion_pattern="**/" + file_pattern,
)
with click.progressbar(
list(rule_paths), label="Parsing Sigma rules", file=stderr
) as progress_rule_paths:
rule_collection = SigmaCollection.merge([
rule_collection,
SigmaCollection.load_ruleset(
progress_rule_paths,
collect_errors=True,
)
])
except yaml.YAMLError as e:
# Report YAML syntax errors like other Sigma errors instead of crashing with a traceback.
raise SigmaCollectionError(f"YAML syntax error: {e}") from e

rule_collection.resolve_rule_references()

Expand Down
16 changes: 16 additions & 0 deletions tests/test_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,22 @@ def test_check_cli_generates_junitxml(tmp_path):
assert tree.getroot().tag == "testsuites"


def test_check_yaml_syntax_error_junitxml(tmp_path):
"""A YAML syntax error is reported as check error and still produces the JUnit report."""
rules = tmp_path / "rules"
rules.mkdir()
(rules / "broken.yml").write_text("title: [unclosed\n")
out = tmp_path / "report.xml"
cli = CliRunner()
result = cli.invoke(check, ["--junitxml", str(out), str(rules)])
assert result.exit_code == 1
assert "Check error: YAML syntax error" in result.output
assert "broken.yml" in result.output
tree = ET.parse(str(out))
failures = tree.getroot().findall(".//failure")
assert any("YAML syntax error" in (f.text or "") for f in failures)


def test_check_unknown_collection_action(tmp_path):
"""Collection-level errors (not attached to any rule) must be reported and fail the check."""
(tmp_path / "typo.yml").write_text("action: repaet\ntitle: typo in action keyword\n")
Expand Down
9 changes: 9 additions & 0 deletions tests/test_convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,15 @@ def test_convert_invalid_rule():
assert "at least one condition" in result.stderr


def test_convert_yaml_syntax_error(tmp_path):
(tmp_path / "broken.yml").write_text("title: [unclosed\n")
cli = CliRunner()
result = cli.invoke(convert, ["-t", "text_query_test", str(tmp_path)])
assert result.exit_code == 1
assert "Error while converting: YAML syntax error" in result.stderr
assert "broken.yml" in result.stderr


def test_convert_stdin():
cli = CliRunner()
with open("tests/files/valid/sigma_rule.yml", "rt") as yml_file:
Expand Down
Loading