Nightwatch
Inspiration
Nightwatch began with a practical question: can a personal Linux computer watch for suspicious activity while its owner is asleep, without making risky or destructive changes to the system? The goal was to build an understandable, host-specific monitor that runs in the foreground until Ctrl-C, records what happened, and highlights behavior worth investigating.
What it does
Nightwatch is a baseline-driven Linux security monitor. It observes processes, executables, interpreter-launched scripts, direct microphone and webcam device access, PipeWire capture streams, network sockets, kernel security posture, loaded kernel modules, and BPF programs.
A calibration period creates a protected fingerprinted model of the computer's
expected state and normal behavior. During a watch, Nightwatch compares live
observations with that baseline and produces explainable NOTICE and HIGH
findings. It runs passively: it does not terminate processes, block devices,
load modules, or alter network and security settings. When stopped, it prints
and securely saves a detailed report.
How we built it
Nightwatch is written in C++17 and builds with GNU Make without third-party C++
libraries. It collects process, file-descriptor, socket, and kernel information
from Linux /proc and sysfs. It uses pw-cli for PipeWire client attribution,
modinfo for kernel-module metadata, and bpftool for root-only BPF inventory.
The protected version-5 baseline stores SHA-256 hashes and security metadata for executables, scripts, and kernel modules, along with calibrated media, network, kernel-posture, and stable BPF identities. Reports and recovery journals are created with restrictive permissions and updated durably during a run. Parsing, fingerprint comparison, classification, and state transitions are covered by automated tests using safe synthetic data rather than loading real modules or executing untrusted samples.
Challenges we ran into
Linux desktop activity is noisy and highly dynamic. Short-lived system helpers, Snap refreshes, browser UDP behavior, Discord traffic, PipeWire routing, and volatile BPF program IDs can resemble suspicious changes without additional context. We had to distinguish a meaningful security signal from ordinary system lifecycle events without broadly trusting executable paths.
Other challenges included safely fingerprinting processes that can disappear mid-scan, preventing repeated expensive hashing, preserving useful reports after interruptions, normalizing network behavior without trusting remote IP addresses, recognizing interpreter script entrypoints, and keeping monitoring close to its requested one-second cadence. Root execution also required strict ownership, permission, file-size, symlink, timeout, and output-limit checks.
Accomplishments that we're proud of
- Built an explainable, read-only monitor that has completed multiple attended and unattended target-system validations on a Dell Latitude 5400.
- Added exact reviewed-executable fingerprints rather than a path-only allow list, including detection of changed binaries after package updates.
- Implemented script-entrypoint integrity monitoring to close the gap between a trusted interpreter and the code it actually launches.
- Attributed TCP, UDP, raw, and packet sockets to processes while grouping volatile connections into stable behavior patterns.
- Added kernel-posture, loaded-module, and stable BPF-program monitoring with a protected version-5 baseline.
- Completed a 28-minute normal-use validation with 1,589 snapshots, no skipped snapshots, and no kernel/BPF or file-integrity findings.
- Maintained automated regression tests while refining real findings from overnight and normal-use reports.
What we learned
A useful heuristic monitor needs context more than it needs a large number of alerts. Exact hashes and security metadata make trust decisions safer, but lifecycle, timing, and attribution are equally important. A short-lived process may disappear before it can be fingerprinted; a browser may legitimately hold an ephemeral UDP socket; and many BPF program IDs may reduce to a smaller set of stable code identities.
We also learned that calibration describes a known host state—it does not prove that the state is clean. Findings must remain explainable, reports must preserve the evidence needed for investigation, and limitations must be stated clearly. Repeated real-world validation was essential for finding performance issues, classification edge cases, and integrity gaps that isolated unit tests would not have revealed.
What's next for Nightwatch
The next major milestone is persistence monitoring for systemd units, scheduled tasks, login/startup entries, and other common Linux persistence locations. We also plan to add independent BPF attachment-site inventory, report signing, optional systemd service integration, and further long-duration validation.
Longer term, Nightwatch could add configurable policies and carefully reviewed response options while preserving its current strengths: passive operation, host-specific fingerprints, clear evidence, and conservative trust decisions.
Log in or sign up for Devpost to join the conversation.