Description
Sigma rule files can contain multiple YAML documents separated by ---. Rustinel currently parses all YAML documents, but for ordinary multi-document files it loads only the first document and silently ignores the rest.
Current code evidence:
src/engine/loader.rs parses with serde_yaml::Deserializer::from_str, so multiple documents are visible to the loader.
- If the first document has
action: global, the loader expands the remaining documents as global sub-rules.
- For all other multi-document files, the loader returns only
documents[0].
This silently drops valid rules when a file contains multiple independent Sigma documents.
Impact
This can cause detection loss without an operator noticing. A bundled or third-party Sigma file may appear to load successfully while most rules inside the file are never compiled.
The risky behavior is the silence. Either supported multi-document loading or a loud rejection would be acceptable, but silent partial loading is not.
Expected Behavior
One of these behaviors should be implemented deliberately:
- Preferred: load every independent Sigma document in the file as a separate rule.
- Acceptable fallback: reject non-global multi-document files with a clear error that explains the format is unsupported.
For action: global files, the existing expansion behavior should remain supported.
Current Behavior
For non-global multi-document files, only the first YAML document is loaded. Later documents are ignored without warning or error.
Suggested Fix Scope
- Decide whether Phase 1 supports independent multi-document Sigma files or rejects them loudly.
- If supporting them:
- Convert each non-empty document into a
SigmaRule.
- Include file path and document index in errors where possible.
- Preserve existing
action: global behavior.
- If rejecting them:
- Detect
documents.len() > 1 when the first document is not action: global.
- Return an explicit error that the file contains unsupported independent YAML documents.
- Avoid silently loading a partial file.
Test Expectations
Add regression coverage for:
- A single-document Sigma rule still loads.
- An
action: global multi-document rule still expands correctly.
- A non-global file with two valid independent documents either loads both rules or fails loudly.
- A non-global file with many documents does not silently load only the first rule.
- A malformed later document reports a useful error rather than being ignored.
Acceptance Criteria
Description
Sigma rule files can contain multiple YAML documents separated by
---. Rustinel currently parses all YAML documents, but for ordinary multi-document files it loads only the first document and silently ignores the rest.Current code evidence:
src/engine/loader.rsparses withserde_yaml::Deserializer::from_str, so multiple documents are visible to the loader.action: global, the loader expands the remaining documents as global sub-rules.documents[0].This silently drops valid rules when a file contains multiple independent Sigma documents.
Impact
This can cause detection loss without an operator noticing. A bundled or third-party Sigma file may appear to load successfully while most rules inside the file are never compiled.
The risky behavior is the silence. Either supported multi-document loading or a loud rejection would be acceptable, but silent partial loading is not.
Expected Behavior
One of these behaviors should be implemented deliberately:
For
action: globalfiles, the existing expansion behavior should remain supported.Current Behavior
For non-global multi-document files, only the first YAML document is loaded. Later documents are ignored without warning or error.
Suggested Fix Scope
SigmaRule.action: globalbehavior.documents.len() > 1when the first document is notaction: global.Test Expectations
Add regression coverage for:
action: globalmulti-document rule still expands correctly.Acceptance Criteria
action: globalbehavior remains covered by tests.