Add false-positive triage via package-ownership provenance
A noisy IDS gets ignored. Adds explicit FP-handling built on provenance — a binary owned by the package manager is almost certainly legitimate (the OSSEC rootcheck / AIDE principle). - provenance.py: package_owner()/is_package_owned() via pacman/dpkg/rpm, cached; framed as confidence-raising, never proof-of-safety - triage.py: triage_alert() labels each detection likely-FP vs review with a reason (package-owned binary, loopback-only listener, allowlisted comm, …); reverse_shell/egress/exec rules are ALWAYS review (provenance can't clear a network shell); unattributable listeners are reviewed, not cleared - cli: `enodia-sentinel triage` summarizes captured alerts and suggests allowlist entries - new_listener: listener_allow_comms + optional suppress_package_owned_listeners gate (the best single knob for a desktop/seedbox running P2P apps) - tests: +10 (provenance injected); README + config documented. 65/65 pass Verified on a live seedbox: 12 detections, 11 auto-cleared as FP (qbittorrent / nicotine / kdeconnectd / the dashboard itself), 1 correctly held for review. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
c00fff224c
commit
07f5261d59
8 changed files with 332 additions and 0 deletions
37
README.md
37
README.md
|
|
@ -236,6 +236,43 @@ notify_ntfy_url = "https://ntfy.sh"
|
|||
notify_ntfy_topic = "enodia-7Hq2x" # keep this secret — it's the access control
|
||||
```
|
||||
|
||||
## False positives & triage
|
||||
|
||||
A host IDS that cries wolf gets ignored, so Sentinel ships explicit tooling to
|
||||
separate benign noise from real findings — built on **provenance**: a binary
|
||||
shipped by your package manager (`pacman`/`dpkg`/`rpm`) is overwhelmingly likely
|
||||
to be legitimate (the same idea behind OSSEC's rootcheck and AIDE).
|
||||
|
||||
```bash
|
||||
enodia-sentinel triage # classify captured alerts, suggest allowlist entries
|
||||
```
|
||||
|
||||
```
|
||||
12 distinct detections — 11 likely false-positive, 1 to review.
|
||||
|
||||
[FP ] new_listener x99 listener binary is package-owned (qbittorrent)
|
||||
[FP ] new_listener x1 loopback-only listener (not externally reachable)
|
||||
[REVIEW] new_listener x1 unrecognized listener *:1740 (?)
|
||||
...
|
||||
To suppress the false positives, add to your config:
|
||||
# listener_allow_comms += "qbittorrent"
|
||||
```
|
||||
|
||||
Triage is deliberately conservative: `reverse_shell`, `egress`, and the eBPF
|
||||
exec rules are **always** flagged review (provenance can't clear a network
|
||||
shell), and any listener it *can't* attribute to a process is reviewed rather
|
||||
than cleared. Suppression is never automatic — you choose what to allowlist.
|
||||
|
||||
Knobs to quiet known-good activity:
|
||||
|
||||
| Config | Effect |
|
||||
|---|---|
|
||||
| `listener_allow_comms` | never alert on listeners owned by these apps |
|
||||
| `listener_allow_ports` | never alert on these ports |
|
||||
| `suppress_package_owned_listeners` | drop `new_listener` when the binary is package-owned (best single knob for a desktop/seedbox) |
|
||||
| `egress_allow_cidrs` | trusted public ranges for the egress detector |
|
||||
| `suid_hot_dirs` / `exec_rules_file` | tune SUID criticality / add custom exec rules |
|
||||
|
||||
## Security model
|
||||
|
||||
Sentinel runs as root because it must read every process's `/proc`, the full
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue