enodia-sentinal/docs/SPECIFICATION.md
Luna a56d72edd6 Add incident grouping (roadmap v0.8: incident list/show/export)
Collapse related alerts into one incident, process-lineage first with a
time-window fallback. Each alert batch's flagged PIDs are walked up the
/proc PPid chain into a lineage set (excluding pid 0/1 so everything
doesn't correlate through init); batches whose lineage sets intersect —
sharing a process or a common ancestor like the web server or SSH
session — join the same incident. PID-less batches (FIM drift, package
tamper, hidden modules) fall back to the most recently active open
incident within incident_window.

snapshot.capture now computes lineage and records each snapshot into a
JSON incident index (incidents.json), writing incident_id into both the
report JSON (report level, so the per-alert schema is untouched) and the
text header. New commands:

  incident list              incidents newest-first, with signatures
  incident show <id>         summary + time-ordered snapshot timeline
  incident export <id>       JSON bundle: record + inlined snapshots

The lineage/assign cores are pure functions; record() serializes the
index under a lock (capture runs from sweep + eBPF threads) and is
best-effort so an index problem never loses a snapshot. 17 new tests
(lineage, assign, record, and an end-to-end capture→group→CLI path).
Config: incident_tracking / incident_window / incident_lineage_depth.
Docs + sample config updated; closes the last v0.8 roadmap item.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 17:52:42 -07:00

209 lines
9.5 KiB
Markdown

# Enodia Sentinel Specification
This document defines Enodia Sentinel as a host security platform, not only a
signature IDS. The current implementation is a local Linux sensor with evidence
capture, integrity monitoring, anti-rootkit checks, a dashboard, and alert
delivery. The intended product is a defensive control plane for a host or small
fleet: detect compromise, prove what changed, preserve useful evidence, guide
response, and make sensor tampering visible.
## Product Definition
Enodia Sentinel is a zero-runtime-dependency Linux host security agent. It runs
as a local daemon, observes high-signal host behavior, records forensic context
when something suspicious happens, and exposes the result through local files,
JSON, a read-only dashboard, push notifications, and command-line tools.
The long-term product should combine five functions:
| Function | Purpose |
|---|---|
| Detection | Find active compromise behavior: reverse shells, fileless execution, new listeners, suspicious egress, persistence edits, and privilege-escalation artifacts. |
| Integrity | Prove whether important files, packages, baselines, and Sentinel's own footprint changed. |
| Evidence | Capture enough context for incident response without forcing the operator to reproduce a live state after the attacker is gone. |
| Response | Provide safe, explicit operator workflows for triage, containment, and recovery. |
| Assurance | Make the agent itself measurable: heartbeat, dead-man's switch, tamper-evidence, and future remote attestation. |
## Design Principles
1. **High-signal first.** Prefer detections that are cheap to observe and costly
for attackers to avoid, even if that means a smaller rule set.
2. **Evidence over noise.** Every alert should carry enough context to answer
"what happened, where, and what should I inspect next?"
3. **Zero dependency core.** The base daemon must run with the Python standard
library only. Optional layers such as bcc/eBPF may degrade cleanly.
4. **One local trust boundary is not enough.** On-box checks are useful but
root can tamper with them. Important anchors should move to signed package
metadata, immutable filesystem controls, external watchers, or future
remote attestation.
5. **Operator control.** Sentinel should recommend response actions before it
takes them. Destructive containment must be opt-in and auditable.
6. **Bash prototype remains the oracle.** The original shell implementation and
red-team harness preserve behavioral compatibility for core signatures.
## Current Scope: v0.7
### Poll Detectors
The daemon builds one `SystemState` per sweep and runs pure detector functions
against cached process and socket data:
| Detector | Signal |
|---|---|
| `reverse_shell` | Interpreter with a network socket on fd 0/1/2. |
| `ld_preload` | Non-empty `/etc/ld.so.preload` or writable-path `LD_PRELOAD`. |
| `deleted_exe` | Process executing from a deleted file or `memfd:` image. |
| `new_listener` | Listening socket absent from the startup baseline. |
| `new_suid` | New SUID/SGID binary, critical in writable locations. |
| `persistence` | Changes to cron, systemd units, SSH keys, shell rc files, and similar persistence locations. |
| `egress` | Interpreter with an established connection to a public IP. |
### Event Detection
An optional bcc eBPF `execve` monitor feeds a declarative rule engine. This
closes the polling gap for short-lived commands and supports custom TOML rules
without code changes. Failure is fail-safe: if the probe cannot load, polling
continues.
### Integrity and Tamper-Evidence
Sentinel includes several integrity layers:
| Layer | Current behavior |
|---|---|
| FIM baseline | SHA-256 baseline for critical files and Sentinel's own footprint. |
| Package verification | Optional `pacman -Qkk` verification for package-owned files. |
| Package DB anchor | Detects out-of-band edits to `/var/lib/pacman/local`. |
| Signed-package anchor | Compares on-disk files to `.MTREE` hashes from cached signed packages. |
| Heartbeat | Writes daemon liveness for local dashboard and external watchdog use. |
| Rootcheck | Cross-view checks for hidden processes, hidden modules, hidden ports, and promiscuous interfaces. |
### Evidence Capture
When a fresh alert survives cooldown, Sentinel writes:
- A human-readable snapshot.
- A JSON snapshot suitable for automation and SIEM import.
- Relevant process tree, sockets, environment hints, file descriptors, and
response guidance.
- Event log entries and dashboard-visible status.
### Operator Interfaces
| Interface | Role |
|---|---|
| CLI | Run daemon, one-shot checks, baseline management, FIM checks, package DB checks, rootcheck, posture audit, incident review, triage, watchdog. |
| Logs | Durable local evidence under `/var/log/enodia-sentinel`. |
| Dashboard | Read-only web view for status, alert browsing, and snapshot inspection. |
| Push | ntfy, Pushover, and generic webhook notifications. |
| Red-team harness | Safe drills for testing signatures and demos. |
## Target Scope: Host Security Platform
The next product shape should make Enodia useful before, during, and after an
incident.
### Prevent
- Configuration posture checks for risky SSH, sudo, systemd, cron, kernel,
package manager, firewall, and service settings.
- Baseline drift reports for newly exposed services, new SUID files, new
autostarts, new users/groups, and sensitive permission changes.
- A policy mode that can fail CI or package build checks for unsafe host images.
### Detect
- More event sources: `tcp_connect`, `bind`, `accept`, file-write events for
persistence paths, module loading, privilege transitions, and LSM hooks.
- Correlation across signals: "web service spawned shell" + "new listener" +
"persistence write" should become one incident, not three unrelated alerts.
- Optional YARA-style and Sigma-like local rules if they can stay dependency
light and operator-readable.
### Investigate
- Incident timeline files derived from event log, snapshots, FIM diffs,
package transactions, process lineage, and network observations.
- Stable incident IDs that group related alerts over time.
- `enodia-sentinel incident show <id>` and `incident export <id>` workflows.
### Respond
- Safe containment actions behind explicit flags:
stop a process, disable a systemd unit, remove a persistence entry, block an
IP with nftables, quarantine a file, or freeze evidence.
- Dry-run by default, with JSON plans that can be reviewed before execution.
- Response playbooks that are code-reviewed data files, not shell snippets
pasted into documentation.
### Recover
- Package restore guidance: identify owning package, verify cache signature,
reinstall package, and re-run integrity checks.
- Baseline reconciliation workflow after confirmed legitimate changes.
- Post-incident report generation from captured evidence.
### Assure
- External anchor storage for baselines and package DB fingerprints.
- Signed snapshots or hash-chained event logs.
- Remote watchdog improvements and eventually fleet controller support.
- Optional TPM/IMA integration for machines that can support measured boot.
## Data Model
The current `Alert` object is the public detection unit:
| Field | Meaning |
|---|---|
| `sid` | Stable signature ID for tuning, documentation, and downstream rules. |
| `severity` | `MEDIUM`, `HIGH`, or `CRITICAL`. |
| `signature` | Stable machine-readable detection name. |
| `classtype` | Snort/Suricata-style category. |
| `key` | Cooldown and deduplication identity. |
| `detail` | Human-readable explanation. |
| `pids` | Process IDs for snapshot deep dives. |
Incident grouping adds an `incident_id` at the snapshot-report level (not inside
each `Alert`), so it groups one or more alerts without changing the alert JSON
schema. Grouping is process-lineage first, with a time-window fallback for
PID-less alerts; see the [command reference](COMMAND_REFERENCE.md) and
[roadmap](ROADMAP.md).
## Configuration Model
Configuration is a TOML file loaded at startup. Unknown keys are ignored so
newer config templates remain tolerable on older agents, but documentation
should clearly mark version-specific fields. Existing defaults should prefer
detection correctness over suppression. Convenience suppression knobs should
remain explicit and reviewable.
## Security Model
Sentinel runs as root because it must inspect root-owned files, process state,
file descriptors, and sockets. The systemd unit should continue to keep the
root process narrow: read-mostly, constrained writable paths, no new privileges,
restricted namespaces, and only the capabilities needed for the enabled layers.
Local root can eventually defeat any purely local sensor. Sentinel's answer is
layering: signed package metadata, immutable files, off-box watchdogs, external
anchors, and future kernel/attestation features.
## Non-Goals
- Replacing a full enterprise SIEM.
- Silent self-hiding or rootkit-like persistence.
- Automatic destructive remediation without explicit operator approval.
- Shipping a broad dependency tree in the default agent.
- Claiming complete protection against a custom kernel implant.
## Acceptance Criteria For New Platform Features
A feature is ready when it has:
- A stable `sid`/signature or documented command contract.
- Unit tests for pure logic and a safe integration path where practical.
- JSON output or a durable artifact suitable for automation.
- Configuration documented in the sample TOML and README or relevant docs.
- Failure behavior that does not take down the daemon.
- Clear operator guidance for false positives, limitations, and response.