| Version | Supported |
|---|---|
| v0.1 (current) | Yes, on a best-effort basis |
| Anything earlier | No |
This repository is an educational/reference proof of concept. There is no release cadence and no backported security maintenance.
Report suspected vulnerabilities privately — through GitHub's Report a vulnerability form under the Security tab, or by email to the repository owner. Please do not open a public issue for anything that would give an attacker an advantage before a fix exists.
Useful reports include the affected component (audit-agent,
audit-collector, audit-verify, or the eBPF program), the version or commit,
and a description of the impact — ideally a way to reproduce it. Expect an
acknowledgement within a week; this is a spare-time project, not a product with
an on-call rotation.
Findings that show a way to modify, delete, or reorder stored audit data
without the verifier detecting it are the most valuable reports this project
can receive. That is its one claim. Note that a wholesale rewrite in which the
whole chain is recomputed is a known and documented limitation, not a finding:
see "Known limitations" below and docs/limitations.md.
The project provides:
A tamper-evident audit trail for Linux process execution events.
Concretely: process executions are captured in the kernel with eBPF, assigned
consecutive sequence numbers, and linked into a SHA-256 chain in which every
event's hash covers its predecessor's hash. They are shipped to a collector that
runs on a different trust boundary from the monitored host, re-validates each
event, and appends it to a per-host, append-only file. audit-verify recomputes
the entire chain from that file alone, trusting neither the agent nor the
collector.
If a stored event is modified, deleted, or reordered and the chain is not rebuilt, the verifier detects that the cryptographic chain is no longer valid.
That qualifier is load-bearing. The digests are plain SHA-256 with no key and no signature, so an adversary who can rewrite the log file can also recompute every hash in it and produce a file that verifies. The chain guarantees that partial tampering is caught; catching a full rewrite requires comparing the log against a checkpoint recorded by an earlier verification and kept where the writer of the log cannot reach it:
audit-verify -expect-hash <hash> -expect-events <n> <log>
Both halves are required. A hash alone means "the log must still end here",
which is only true of a snapshot that never grows; a count alone attests nothing
at all and is refused. Every successful run prints the checkpoint for the next
one, and the verifier says Trusted anchor: NOT CHECKED when none is supplied.
The security property is detection, not prevention, and it applies to data already collected. The threat model assumes the monitored host may become untrustworthy after some events have been delivered; it does not assume the collector or its storage can resist a determined root.
The full list is in docs/limitations.md. The ones that most often get misread as guarantees:
- an unkeyed hash chain cannot detect a wholesale rewrite; without an external anchor, a verified result means internally consistent, not unaltered;
- an agent that ends up out of step with the collector stops the host being audited; it exits non-zero rather than resynchronizing, because resynchronizing would require disclosing chain state to unauthenticated callers;
- root can stop or bypass the agent, and nothing after that point is captured;
- v0.1 storage is append-only by construction but not WORM — root can still rewrite the file;
- truncating the tail of a log leaves a self-consistent chain; only a checkpoint catches it, and a checkpoint attests only up to its own position;
- transport is plain HTTP with no agent authentication in v0.1;
allowed_hostsbounds which identities can be created, not who may submit for them; - events are dropped, not spooled, when the collector is unreachable, and a dropped event leaves no trace in the stored log;
- only
execveis audited; - command arguments routinely contain secrets, and they are stored verbatim (in escaped text form, recoverable byte for byte);
- timestamps come from the monitored host and are not authoritative;
- the Go standard library ships inside these binaries, so the toolchain is a
runtime dependency;
go.modrequires 1.26.6, which is where the reachablenet/httpvulnerabilities are fixed. Re-runmake vulncheckbefore releasing.
This repository is an educational/reference PoC and should not be used as the sole audit mechanism for production regulated environments.