Skip to content

Add Sigma rule-logic evaluator + --check-rule#13

Merged
Gerrrt merged 1 commit into
mainfrom
feat/rule-logic-evaluator
Jul 24, 2026
Merged

Add Sigma rule-logic evaluator + --check-rule#13
Gerrrt merged 1 commit into
mainfrom
feat/rule-logic-evaluator

Conversation

@Gerrrt

@Gerrrt Gerrrt commented Jul 24, 2026

Copy link
Copy Markdown
Owner

Implements the core of the merged design doc: evaluate a command against a Sigma rule's real detection:/condition: logic, not just its ATT&CK technique tag.

The idea: opseclint has a command line, not a full host event, so it synthesizes the fields it can legitimately know (CommandLine, Image, OriginalFileName) and evaluates with three-valued (Kleene) logicFIRES / NO-FIRE / INDETERMINATE. A rule keyed on a field a static analyzer can't see (e.g. ParentImage, a hash) is INDETERMINATE (with the missing field named), so it abstains honestly rather than making a false claim.

$ opseclint script.sh --check-rule docker_socket.yml
sigma rule check: Docker Socket Access Via Curl Or Wget (85f46916-…)
  L1   curl   FIRES
  L2   wget   NO-FIRE
  L7   curl   INDETERMINATE
         (needs ParentImage)

What's in it (src/sigma_eval.rs):

  • field-match modifiers (contains/startswith/endswith/all + */? globs); unsupported modifiers (re/cidr/base64) → INDETERMINATE
  • search forms: field maps, list-of-maps (OR), keyword lists
  • a small recursive-descent condition parser: and/or/not/parens/N of/all of/them
  • --check-rule <RULE.yml> CLI surface; verified end-to-end against a real Sigma rule

+7 tests (39 total), fmt/clippy clean. Next step (separate PR): wire the evaluator into --sigma enrichment and add --coverage-gaps.

Implements the core of the merged design doc: evaluate a command against
a Sigma rule's detection/condition logic with three-valued (Kleene)
logic. Synthesizes an event (CommandLine/Image/OriginalFileName) from the
parsed command; fields it can't see (ParentImage, hashes, registry) make
the rule INDETERMINATE rather than a false claim.

- src/sigma_eval.rs: field-match modifiers (contains/startswith/endswith/
  all + wildcard globs), search forms (fields/list-of-maps/keywords), a
  recursive-descent condition parser (and/or/not/N-of/all-of/them), and
  FIRES/NO-FIRE/INDETERMINATE verdicts with missing-field reporting.
- --check-rule <RULE.yml>: per-command verdicts against one rule.
- +7 tests (39 total). Next: wire into --sigma for --coverage-gaps.
Copilot AI review requested due to automatic review settings July 24, 2026 03:35
@Gerrrt
Gerrrt merged commit a4af288 into main Jul 24, 2026
6 checks passed
@Gerrrt
Gerrrt deleted the feat/rule-logic-evaluator branch July 24, 2026 03:36

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a Sigma rule-logic evaluator to opseclint so a command line can be evaluated against a Sigma rule’s actual detection:/condition: logic using three-valued (Kleene) outcomes (FIRES / NO-FIRE / INDETERMINATE), and exposes it via a new --check-rule CLI mode.

Changes:

  • Introduces src/sigma_eval.rs implementing Sigma detection parsing + condition evaluation with three-valued logic.
  • Adds --check-rule <RULE.yml> mode to evaluate each parsed command in the input against a single Sigma rule and print per-line outcomes.
  • Documents the new mode and updates the project roadmap in README.md.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
src/sigma_eval.rs New Sigma detection/condition parser + three-valued evaluator with unit tests.
src/main.rs New --check-rule CLI option and execution path to run the evaluator as a distinct mode.
README.md Adds usage/docs for --check-rule and marks the evaluator feature as complete.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/sigma_eval.rs
Comment on lines +460 to +464
let terns: Vec<Ternary> = matching_ids(pat, searches)
.iter()
.filter_map(|id| searches.get(*id))
.map(|s| eval_search(s, event))
.collect();
Comment thread src/main.rs
Comment on lines +75 to +76
#[arg(long, value_name = "RULE.yml")]
check_rule: Option<String>,
Comment thread README.md

Beyond technique-tag matching, opseclint can evaluate a command against a Sigma
rule's actual `detection:`/`condition:` logic and report, per command, whether it
**FIRES**, **NO-FIRE**s, or is **INDETERMINATE** — the last meaning the rule keys
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.

2 participants