Source-scope incident fingerprints for ingested findings (before remote actuation) #1

Closed
opened 2026-09-10 12:19:17 +00:00 by jmz · 1 comment
Owner

From the M2 whole-branch review (deferred; pre-existing since the NATS findings ingest).

An incident fingerprint is default_fingerprint(check_id, subject) — source is excluded. A bus-authorized sensor can publish a finding whose (check_id, subject) collides with a local detector's or another sensor's incident; a status: ok collision would resolve/suppress that incident. Not a regression (legacy WARDEN_NATS_FINDINGS_SUBJECT had the same shape); acceptable while remediation is local, but MUST be resolved before remote actuation is driven off ingested findings.

Fix: source-scoped fingerprints for ingested findings, or a per-sensor allowlist of assertable check_ids. See nats_bus.decode_finding, model.default_fingerprint.

**From the M2 whole-branch review (deferred; pre-existing since the NATS findings ingest).** An incident fingerprint is `default_fingerprint(check_id, subject)` — `source` is excluded. A bus-authorized sensor can publish a finding whose `(check_id, subject)` collides with a local detector's or another sensor's incident; a `status: ok` collision would resolve/suppress that incident. Not a regression (legacy `WARDEN_NATS_FINDINGS_SUBJECT` had the same shape); acceptable while remediation is local, but MUST be resolved before remote actuation is driven off ingested findings. **Fix:** source-scoped fingerprints for ingested findings, or a per-sensor allowlist of assertable `check_id`s. See `nats_bus.decode_finding`, `model.default_fingerprint`.
jmz changed title from __probe__ delete me to Source-scope incident fingerprints for ingested findings (before remote actuation) 2026-09-10 12:20:57 +00:00
Author
Owner

Fixed on main (ships in v0.17.0). default_fingerprint gains an optional source arg: sourceless (local) digest is byte-identical to before and locked by a hardcoded-digest guard test; a non-empty source (ingested finding, source bound to the transport subject) gets its own fingerprint namespace via the existing null-byte separator. The wire fingerprint field is never read — always recomputed locally from validated (check_id, subject, source), so a sensor cannot forge another source’s fingerprint. Store-level test proves sensor-B’s ok cannot resolve sensor-A’s (or a local detector’s) incident. 588 tests.

Fixed on main (ships in v0.17.0). default_fingerprint gains an optional source arg: sourceless (local) digest is byte-identical to before and locked by a hardcoded-digest guard test; a non-empty source (ingested finding, source bound to the transport subject) gets its own fingerprint namespace via the existing null-byte separator. The wire fingerprint field is never read — always recomputed locally from validated (check_id, subject, source), so a sensor cannot forge another source’s fingerprint. Store-level test proves sensor-B’s ok cannot resolve sensor-A’s (or a local detector’s) incident. 588 tests.
jmz closed this issue 2026-09-10 14:50:07 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
public/warden#1
No description provided.