Armed the gate on / on the live server. Aborted after about twenty
seconds. The box was never at risk — Caddy stayed sub-millisecond and
load never rose — but the gate blocked reads of an AI agent's session
transcript, reporting it as Linux.Coinminer.XMRig.
It was not wrong about the bytes. That transcript contains
"stratum+tcp://", "donate-level" and "xmrig" because the miner rule was
being written in that session. The rule matched a document ABOUT
malware.
Three bugs, none of which the tmpfs stage could have shown:
1. The miner rule had no file-type condition, so any text mentioning
mining tripped it: threat-intelligence reports, security blog posts,
support tickets, an antivirus's own logs. It now requires ELF magic,
as the rootkit rule always did. Two regression tests: a transcript
discussing the rule is clean, and an ELF carrying the same strings
still matches — the fix must not cost the detection it exists for.
2. The gate requested FAN_OPEN_PERM, so it held every OPEN, not every
execve. A matching file could not be read by anything. That is a
different product from the one advertised, and on a multi-tenant box
it is a denial of service against the operator rather than a defence.
Read events are no longer requested at all. FAN_OPEN_EXEC_PERM and
FAN_CLOSE_WRITE cover the threat: execution is refused before it
happens, and anything malicious written to disk is quarantined when
the write completes. An interpreted script is caught as it lands
rather than as it is read — the same protection, one step earlier.
`serve` also guards deny-on-exec explicitly, so re-requesting read
events later cannot silently restore the old behaviour.
3. Hound did not exclude its own state. /var/lib/hound and /run/hound
are now always excluded; the vault holds live malware by definition.
Henry asked whether the single watchdog rescue was queue pressure or
scan time. It was scan time: the gate inherited the on-demand 100 MB
limit and tried to read and match a multi-megabyte transcript inline
while holding a process. A gate's budget is a deadline, not a size, so
it now caps at 32 MB — anything larger is allowed through unread rather
than turned into a rescue, which is a process released unscanned and
worse than never having looked.
Dropping read events made everything faster, because most opens on a
running machine are reads:
latency +1.38 -> +0.79 ms per exec
throughput 2,680 -> 4,178 execs/sec (58% of ungated, was 36%)
events 1,179 in five seconds on an idle tmpfs -> 1
Re-verified on the tmpfs: an ELF miner is quarantined before it can even
be made executable, a document naming every one of its strings is
readable, and a clean binary runs.
297 tests pass. The gate stays off; stage 3 gets attempted again with
these fixes and fresh numbers.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>