# Enodia Sentinel Specification This document defines Enodia Sentinel as an IDS, IPS, and EDR system, not only a signature IDS. The current implementation is a local Linux sensor with evidence capture, integrity monitoring, anti-rootkit checks, a dashboard, alert delivery, and dry-run prevention/response planning. The intended product is a defensive control plane for a host or small fleet: detect compromise, prevent or contain known-bad behavior through explicit operator workflows, 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 six functions: | Function | Purpose | |---|---| | Detection | Find active compromise behavior: reverse shells, fileless execution, new listeners, suspicious egress, persistence edits, and privilege-escalation artifacts. | | Prevention | Recommend and, after explicit review, apply containment actions such as stopping malicious processes, blocking C2 peers, disabling persistence, or quarantining files. | | 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: Local IDS/IPS/EDR ### 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. | | `input_snooper` | Non-allowlisted process holding keyboard/input/HID devices open. | | `credential_access` | Non-allowlisted process reading credential databases, private keys, browser stores, or secret profiles. | | `stealth_network` | Non-allowlisted raw, SCTP, DCCP, packet, MPTCP, TIPC, XDP, or vsock activity. | | `memory_obfuscation` | Non-allowlisted executable anonymous/memfd/deleted mappings, RWX memory, or mapped process-hiding libraries. | | `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 Optional bcc eBPF monitors feed event rule engines. The `execve` stream closes the polling gap for short-lived commands and supports custom TOML rules without code changes. The syscall stream watches short-lived memory and anti-analysis behavior: RWX `mprotect`/`mmap`, `memfd_create`, sensitive `ptrace`, seccomp, cross-process memory access, and memory locking. Failure is fail-safe: if a 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, processes hidden from `ps`, hidden modules, hidden TCP/UDP/raw/special-protocol sockets, promiscuous interfaces, known rootkit modules, raw ICMP/SCTP-style channels, and kernel/module taint. | ### 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/export, triage, status/watchdog, and response planning. | | Logs | Durable local evidence under `/var/log/enodia-sentinel`. | | Dashboard | HTTPS-only read-only web view for status, incidents, timelines, alert browsing, posture findings, event tail, and response-plan previews. | | Push | ntfy, Pushover, and generic webhook notifications. | | Red-team harness | Safe drills for testing signatures and demos. | CLI-generated response plans are durable artifacts: `respond plan` writes the reviewed dry-run plan under `response-plans/` and appends a JSONL `response-audit.log` record. Dashboard/API previews remain read-only and do not create artifacts. Current IPS scope is explicit prevention workflow, not transparent inline enforcement. Sentinel can recommend evidence preservation, process freeze/termination, outbound IP blocks, systemd unit disablement, suspicious-file quarantine, package-owner lookup, and follow-up verification. It does not execute those commands until a future audited `--apply` workflow is designed, tested, and documented. ## 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 ` and `incident export ` 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.