Skip to content

Commit cc1be75

Browse files
committed
feat(detector): emit time-separated detection episodes
1 parent 8898d2e commit cc1be75

6 files changed

Lines changed: 333 additions & 114 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,18 @@ All notable user-visible changes should be recorded here.
1010

1111
### Changed
1212

13-
- None yet.
13+
- Detector rules now emit separate findings for time-separated detection
14+
episodes within the same rule subject instead of collapsing each subject to a
15+
single best window.
1416

1517
### Fixed
1618

1719
- None yet.
1820

1921
### Docs
2022

21-
- None yet.
23+
- Documented detection episode semantics in the rule catalog and report artifact
24+
contract notes.
2225

2326
## v0.5.0
2427

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@ LogLens currently detects:
8484
- One IP trying multiple usernames within 15 minutes
8585
- Bursty sudo activity from the same user within 5 minutes
8686

87+
Each rule can emit multiple findings for the same subject when matching
88+
evidence appears in time-separated detector episodes. Report consumers should
89+
use `window_start`, `window_end`, and `evidence_event_ids` rather than assuming
90+
one finding per `rule_id` and subject.
91+
8792
LogLens currently parses and reports these additional auth patterns beyond the core detector inputs:
8893

8994
- `Accepted publickey` SSH successes

docs/report-artifacts.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ fixtures explicitly.
6161

6262
`evidence_event_ids` are deterministic local event identifiers derived from the source line number, formatted as `line:<number>`. They let reviewers trace a finding back to the normalized input events that satisfied the rule window without implying global event identity.
6363

64+
Consumers should not assume that `rule_id` plus `subject` is unique within a
65+
report. A rule can emit multiple findings for the same subject when matching
66+
evidence appears in time-separated detector episodes. Use `window_start`,
67+
`window_end`, and `evidence_event_ids` to distinguish episode-level findings.
68+
6469
`verdict_boundary` is a stable token that states what the finding must not be
6570
read as. It keeps machine-readable findings aligned with LogLens's triage
6671
scope:

docs/rule-catalog.md

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,29 @@ Metadata equivalent:
2626
- Default values below match the built-in detector configuration.
2727
- The checked-in `assets/sample_config.json` is a tested default-equivalent fixture.
2828

29+
## Detection Episode Semantics
30+
31+
Within each rule grouping key, LogLens sorts matching signals by timestamp and
32+
source line number. Consecutive signals separated by an idle gap greater than
33+
the rule window start a new episode candidate.
34+
35+
Inside each episode candidate, the detector keeps the best sliding window for
36+
the rule:
37+
38+
- `brute_force` and `sudo_burst`: highest event count
39+
- `multi_user_probing`: highest distinct username count, with event count as
40+
the tie-breaker
41+
42+
Each episode candidate that reaches the configured threshold emits one finding.
43+
The same `rule_id` and `subject` can therefore appear more than once in one
44+
report when the evidence contains time-separated bursts. Review
45+
`window_start`, `window_end`, and `evidence_event_ids` to distinguish those
46+
episodes.
47+
48+
Episode splitting is a detector reporting model, not an incident boundary. It
49+
does not infer compromise, attribution, causality between rules, or cross-host
50+
correlation.
51+
2952
## Finding Explainability Fields
3053

3154
JSON findings include both the finding conclusion and the rule context used to reach it:
@@ -89,7 +112,7 @@ Signals without a source IP are not grouped for this rule.
89112

90113
10 minutes by default.
91114

92-
The detector uses a sliding timestamp window within each source-IP group.
115+
The detector uses the episode semantics above within each source-IP group.
93116

94117
### Threshold
95118

@@ -155,7 +178,7 @@ Signals without a source IP are not grouped for this rule. Distinct username cou
155178

156179
15 minutes by default.
157180

158-
The detector uses a sliding timestamp window within each source-IP group.
181+
The detector uses the episode semantics above within each source-IP group.
159182

160183
### Threshold
161184

@@ -224,7 +247,7 @@ Signals without a username are not grouped for this rule.
224247

225248
5 minutes by default.
226249

227-
The detector uses a sliding timestamp window within each username group.
250+
The detector uses the episode semantics above within each username group.
228251

229252
### Threshold
230253

0 commit comments

Comments
 (0)