enodia-sentinal/docs/ROADMAP.md
Luna 457c7604ba
feat(gui): add optional tkinter and Qt6 desktop dashboards
Add two optional windowed frontends over the same local state the TUI and
web console read: `enodia-sentinel gui` (stdlib tkinter) and
`enodia-sentinel gui-qt` (PySide6, new `[qt]` extra).

Both share `gui/model.py`, a GUI-free presentation model over
`tui.collect_model`, so every formatter is unit-testable without a display
server. Only `app.py` and `qt_app.py` import GUI libraries, enforced by
import-guard tests mirroring the tray applet's boundary.

Tabs cover status, alerts, incidents, posture, integrity, response plans,
and the event tail, plus daemon-control buttons via systemctl. Response
plans are display-only; the GUIs never execute containment commands. Core
runtime dependencies stay empty.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JX86xeoBJVBb16qHkDf53K
2026-07-22 04:33:49 -07:00

329 lines
17 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Enodia Sentinel Roadmap
This roadmap moves Enodia Sentinel from a single-host IDS/IPS/EDR agent into a
fuller host security platform: detect, prevent, verify, investigate, respond,
and assure. Dates are intentionally not promised here; the sequence matters more
than calendar precision.
## Release Tracks
| Track | Goal |
|---|---|
| Sensor | Better host telemetry, event capture, and detection coverage. |
| Prevention | Safe containment and recovery actions that start as dry-run plans and require explicit review before any state change. |
| Integrity | Stronger proof that files, packages, baselines, and Sentinel itself were not silently modified. |
| Incident | Group alerts, build timelines, and export evidence. |
| Response | Add safe, auditable containment and recovery workflows. |
| Fleet | Let multiple hosts report to a small controller without making the local agent dependent on it. |
| Assurance | Move trust anchors off-box or below user space. |
## v0.8: Documentation, Posture, and Incident Shape
Purpose: make the current agent easier to operate and create the data model for
work that is bigger than single alerts.
- ✅ Add `incident_id` grouping around related alerts (process-lineage first,
time-window fallback) while preserving the existing alert JSON — `incident_id`
is added at snapshot-report level.
- ✅ Add an incident timeline generator: `incident show` builds a time-ordered
view across an incident's member snapshots (time, severity, signatures, PIDs).
Richer sources (package transactions, dedicated FIM-diff lines) can follow.
- ✅ Add `enodia-sentinel incident list/show/export`.
- ✅ Add host posture checks (`enodia-sentinel posture check`):
SSH root/password/empty-password login, passwordless and writable sudoers,
world-writable PATH components, loose sensitive-file permissions, disabled
package signatures, and enabled systemd units with writable unit files or
`ExecStart` binaries in writable/unsafe paths.
- ✅ Add a machine-readable `status --json` command for automation.
- ✅ Update the red-team harness so every current detection has a named drill and
expected `sid` (`sentinel-redteam --list`), with a PASS/MISS verification pass.
- ✅ Document incident response runbooks for reverse shells, persistence, trojaned
binaries, hidden listeners, and sensor tampering ([RUNBOOKS.md](RUNBOOKS.md)).
- ✅ Add Gonzalo/Peopleswar-style behavior coverage: input-device keylogging,
credential-store/private-key access, SCTP/DCCP/raw/packet-family traffic, and
raw ICMP/special-protocol rootcheck detection.
- ✅ Add process-hiding and memory-obfuscation coverage: `/proc` vs `ps`
cross-view checks plus memory-map scans for hide libraries, RWX memory, and
executable anonymous/memfd/deleted mappings, plus writable-path executable
library mappings that suggest userland process injection.
- ✅ Add event-driven memory telemetry for short-lived `mprotect`/`mmap` RWX,
`memfd_create`, `ptrace`, seccomp, cross-process memory access, and memory
locking syscalls.
Exit criteria:
- One alert can become one incident artifact.
- Operators can answer "what changed around this alert?" without reading every
raw snapshot manually.
- Posture checks report reviewable findings but do not block daemon startup.
## v0.9: Response and Recovery
Purpose: move from "tell me" to "help me act" without unsafe automation.
- ✅ Add response plan generation:
`enodia-sentinel respond plan <incident-id>`.
- ✅ Persist CLI-generated dry-run plans under `response-plans/` and append
`response-audit.log` records for review/handoff.
- ✅ Add dry-run first actions for evidence freeze, process freeze/terminate,
outbound IP block, systemd stop/disable, suspicious-file quarantine,
package-owner lookup, and follow-up verification.
- ✅ Add package reinstall/restore planning for pacman-owned file findings:
identify the owning package, verify signed package-cache metadata, reinstall
from trusted package media, re-run integrity checks, and re-anchor FIM only
after operator review. Debian/RPM support remains future work.
- ✅ Add an explicit apply boundary: `respond apply <plan-ref> --dry-run`
reloads a saved reviewed plan, prints the exact actions, and appends a
`response_apply_rehearsed` audit record without executing commands.
- Require a future explicit execution flag for state changes; default to
read-only plans and audited apply rehearsals.
- ✅ Extend response audit logs to the apply boundary with `executed: false`
records. Future state-changing execution must append the same audit trail.
- ✅ Add baseline reconciliation: accept legitimate FIM/package/listener/SUID
drift with a mandatory reason via `baseline accept/revoke/list`. Acks are
fingerprint-bound (content kinds re-alert on further change), support an
optional TTL, and are filtered at the daemon chokepoint, `fim-check`, and the
dashboard integrity API.
- ✅ Add richer false-positive suppression suggestions that can emit TOML snippets
but never modify config automatically.
- ✅ Add recovery checks:
"verify package", "re-run rootcheck", "confirm no persistence diff", and
"confirm heartbeat/dashboard visible from watchdog".
Exit criteria:
- An operator can go from alert to reviewed response plan with one command.
- Any state-changing action is explicit, logged, reversible where possible, and
testable in a safe fixture.
## v1.0: Stable Local Platform
Purpose: define a stable single-host product.
- ✅ Commit to stable JSON schemas for alerts, incidents, status, and response
audits.
- ✅ Add compatibility tests for schema evolution.
- ✅ Add documentation versioning and manpage-style command reference.
- ✅ Harden packaging for Arch first, then document Debian/RPM install paths.
- ✅ Add signed release artifacts and checksums.
- ✅ Improve dashboard from alert browser to local console:
incidents, posture, integrity state, response plans, and watchdog status.
- ✅ Add a local dashboard Settings menu with persistent themes for dark
console, light evidence review, high-contrast operation, LGBTQ, Trans,
Dracula, Solarized Dark/Light, and Twilight palettes.
- ✅ Add dashboard theme contrast/visual smoke checks so readable text and
meaningful status colors are preserved across every palette.
- ✅ Add an optional desktop tray applet (`enodia-sentinel-tray`, `[tray]`
extra): dashboard launcher, systemd daemon control, status at a glance, and
`check --json` quick checks, with GUI-free tested logic modules.
- ✅ Add an optional stdlib tkinter desktop dashboard (`enodia-sentinel gui` /
`enodia-sentinel-gui`): tabs for status, alerts, incidents, posture,
integrity, response plans, and events, plus daemon-control buttons and
threaded refresh. All testable logic is GUI-free; only `app.py` imports
tkinter.
- ✅ Add an optional Qt6 desktop dashboard (`enodia-sentinel gui-qt` /
`enodia-sentinel-gui-qt`, `[qt]` extra with `PySide6`): native tabs and
tables, severity row coloring, response-plan detail pane, keyboard shortcuts,
and safe threaded background refresh.
- Keep the dashboard read-only unless a separate authenticated write path is
designed and reviewed.
Exit criteria:
- The local agent can be installed, operated, upgraded, and integrated without
reading source code.
- JSON and command contracts are stable enough for downstream automation.
## v1.1: Event Coverage and Correlation
Purpose: reduce blind spots and connect related signals.
- ✅ Add the first typed host-event rule family beside exec/syscall rules:
`rules test` accepts `tcp_connect` event JSON and ships SID `100067` for
interpreter egress to unusual public ports, with a replayable fixture.
- ✅ Add a second typed host-event rule family for `listen` events: SID `100068`
flags interpreters opening listeners on unusual local ports, with local-port
match conditions and a replayable fixture.
- ✅ Continue generalizing the rule engine across more typed host events:
`file_write`, `chmod/chown`, `setuid/setgid`, `bind`, `accept`, `capset`,
and module-load now have built-in rules, typed event parsing, fixtures, and
rule-operation tests.
- Keep rules declarative and Snort-like:
`sid`, `msg`, `severity`, `classtype`, `event`, and match fields such as
process name, parent process, argv regex, path prefix, peer IP/port, UID/GID,
package ownership, and lineage.
- Add eBPF event sources:
`tcp_connect`, `bind`, `accept`, module load, privilege transitions, and
writes to watched persistence paths.
- Build process lineage across polling and event sources.
- ✅ Start correlating multi-stage behavior with a read-only incident
correlation engine: `exec_rule.web-rce` plus suspicious egress or an unusual
listener in a 10-minute incident window raises SID `100080`
`correlation.multi_stage_intrusion` while preserving the raw alerts.
- Continue expanding multi-stage behavior:
web service spawns shell, shell downloads payload, payload adds persistence,
listener appears, and FIM changes.
- Add configurable correlation windows and severity escalation rules, including:
- `exec_rule.web-rce` + suspicious egress + persistence within 10 minutes →
CRITICAL multi-stage intrusion.
- `new_listener` + `new_suid` in the same lineage/window → CRITICAL backdoor
with privilege-escalation artifact.
- `fim_modified` or `pkg_signature_mismatch` + `pkgdb_tamper` → CRITICAL
suspected trojaned binary with checksum cover-up.
- web/database service spawning shell + tool transfer (`curl|wget|sh`) →
CRITICAL likely RCE payload staging.
- Add additional high-signal living-off-the-land detections:
`curl|wget | sh`, Python/perl/bash reverse-shell argv variants,
`systemctl enable` from unusual ancestry, `chmod +s` outside package
transactions, and execution from writable directories.
- ✅ Add first-seen and rarity tracking for local network behavior:
first public destination per process name and first listening port per
process name are locally baselined in `first-seen.json` and alert after the
initial silent pass.
- Continue rarity coverage for:
interpreter connections to non-standard ports and long-lived low-byte
connections when socket sampling can support it.
- Keep polling as the oracle and fallback.
Exit criteria:
- Short-lived network and persistence actions are visible.
- Related alerts collapse into one incident with a readable timeline.
- Multi-stage correlation raises one higher-confidence incident without hiding
the underlying raw alerts.
## v1.1.1: Detection Quality and Rule Operations
Purpose: make detection coverage easier to audit, tune, and extend without
turning Sentinel into a noisy rules dump.
- ✅ Add `enodia-sentinel rules list` and `rules show <sid>` for built-in and
configured rules.
- ✅ Add `enodia-sentinel rules test <event-json>` so operators can validate
custom event rules against captured or fixture events.
- ✅ Generate rule documentation from source defaults: SID, signature, classtype,
event type, match fields, expected false positives, and drill coverage.
- ✅ Require a fixture or safe red-team drill for every built-in SID, including
event-only and correlation SIDs.
- ✅ Add compatibility tests for rule JSON/event schema evolution.
- ✅ Extend triage so false-positive suggestions are tied to SID/classtype and can
emit TOML snippets for allowlists, correlation windows, or severity overrides.
- ✅ Add post-alert enrichment consistently across detections:
package owner, executable hash, parent/ancestor chain, remote IP
classification, file mode/owner, recent writes by same lineage, and current
FIM/package/rootcheck status.
Exit criteria:
- Operators can inspect, test, document, and tune detection rules without
reading Python source.
- Every shipped detection rule has reproducible fixture/drill coverage and stable
operator documentation.
## v1.2: Fleet Mode
Purpose: support several personal or small-business Linux hosts without turning
the agent into a heavy enterprise platform.
- ✅ Add a fleet collector design note covering optional collector boundaries,
per-host enrollment, signed JSON payloads, HTTPS/tailnet transport, and
standalone-agent failure semantics ([FLEET_DESIGN.md](FLEET_DESIGN.md)).
- Add an optional collector service.
- Agents push signed JSON events and heartbeats over HTTPS or a tailnet.
- Collector stores host status, alerts, incidents, and package/integrity state.
- Add host enrollment with per-host tokens.
- Add fleet-wide views:
stale sensors, repeated signatures, hosts missing package signatures, and
integrity drift.
- Preserve local autonomy: detection and evidence capture must continue if the
collector is down.
Exit criteria:
- A small fleet can answer "which host is compromised or silent?" from one
console.
- The agent still works as a standalone local tool.
## v1.3+: Assurance and Hardening
Purpose: make tampering harder to hide from an attacker with high privileges.
- External baseline anchor:
mirror FIM and package DB fingerprints off-box with append-only semantics.
- ✅ Hash-chain `events.log` and snapshots locally with append-only
`enodia.hash_chain.v1` JSONL records, exposed through the integrity report.
- Optional snapshot signing with a host key.
- Investigate Linux IMA/EVM and TPM-backed attestation for supported machines.
- Replace bcc with a libbpf + CO-RE agent if the event layer becomes core to
the product.
- Explore minimal kernel-side enforcement hooks for response actions, while
keeping the default product inspect-only.
Exit criteria:
- A local root attacker has to tamper with both the host and an external or
hardware-backed trust anchor to hide compromise.
## Active Migration Track
- Suricata model assimilation design is complete, and Phase 0's additive
`enodia.event.v1` Python reference contract is implemented.
- Phase 1 under `go-agent/` now has a stdlib-only parallel sweep loop,
injectable process/file-descriptor/socket state, and all current Python poll
detectors ported: `reverse_shell`, `ld_preload`, `deleted_exe`,
`input_snooper`, `credential_access`, `stealth_network`, `egress`,
`memory_obfuscation`, `first_seen`, `new_listener`, `persistence`, and
`new_suid`. The shared fixture and `scripts/check-go-parity.py` check Go
output against the Python oracle. A new `provenance` package provides
pacman/dpkg/rpm ownership queries so the Go `new_listener` detector can
mirror Python's package-owned-listener suppression. Opt-in `--state-dir`
mode now builds listener/SUID baselines, applies the shared startup grace
gate, scans persistence paths, and retains first-seen network state. The Go
sidecar also has offline-replay parity for the exec rule family (built-ins
`100001``100004` plus configured `[[exec_rules]]`) and syscall rules
`100060``100066`, plus all typed host rules, the active rule catalog,
mixed-event JSONL routing, correlation SID `100080`, and sweep cooldown. The
first Phase 2 transports have landed as an opt-in `cilium/ebpf` execve
tracepoint source plus a filtered raw-syscall source for SIDs `100060`
`100066`, both with CO-RE parent lookup, shared cooldown/emission, and
fail-open probe status. The syscall source also routes `setuid`/`setgid` into
typed-host SIDs `100071`/`100072` and permission/ownership changes into SID
`100070`, including relative-path resolution. Confirmed interpreter
`write`/`writev`/`pwrite` variants,
successful TCP connect/bind/listen/accept calls, `capset`, and `finit_module`
now feed typed-host SIDs `100069`, `100067`/`100073`/`100068`/`100076`,
`100077`, and `100078`. Phase 2 now also includes an opt-in hardened systemd
validation unit, static build/install path, isolated baseline state, and
journal JSONL. A bounded rotating JSONL copy provides isolated retained event
history, and an atomic heartbeat gives external watchdogs a non-journal
liveness signal. Bounded Python-schema-compatible JSON/text alert snapshots
now provide truthful retained counts and basic process context. A private,
atomic `enodia.incident.v1` index now applies the shared lineage-first/time-
window grouping, assigns real snapshot `incident_id` values, and persists
correlation SID `100080`. The Python service remains the production default
until rich enrichment/assurance, management-console consumers, and broader
subsystem parity land.
## Backlog
Useful ideas that need design before implementation:
- Policy-as-code for host posture.
- YARA-compatible scanning for selected paths.
- Sigma-like host event rules.
- SBOM and package provenance reporting.
- Offline evidence bundle for outside analysis.
- Dashboard import of exported incident bundles.
- Support for non-pacman package managers in signed-package verification.
- Dedicated Debian/RPM packaging.
- Installer preflight checks and health diagnostics.
## Roadmap Rules
- Do not add dependencies to the base daemon without a specific security or
operator value that cannot be achieved with stdlib.
- Prefer read-only detection and dry-run response until the command contract is
tested and documented.
- Every new detector or response action needs a safe drill or fixture.
- Do not build stealth or self-hiding behavior.
- Keep the local agent useful without a dashboard, collector, or network.