I pointed my agent security tool at myself and four of the bugs were mine

blitzcrieg11 pts0 comments

I pointed my agent security tool at myself. It found five bugs, and four were mine. | Agentmetry← NotesI build Agentmetry, a local-first flight recorder for AI coding agents. It sits at the tool boundary, records what Cursor and Claude Code actually did, and runs sequence detection over the result: credential access followed by network egress, a denied approval that ran anyway, a download cradle piped into a shell.<br>It has been installed on the machine where I write it, recording my real work rather than a demo or a fixture. This week I finally sat down and read what it had captured.<br>It found five bugs. Four of them were in Agentmetry.<br>This is a post about those four, because the ones a security tool gets wrong about itself are more instructive than the ones it gets right about somebody else.<br>The recorder was not recording<br>The first thing I found was not a detection. It was an absence.<br>The hooks fire inside the IDE and post each tool call to a local orchestrator. If the orchestrator is unreachable, the hook writes the event to a spool file instead of dropping it, and the spool is replayed on the next start. That design is correct. I wrote it after an earlier version silently lost events on every restart.<br>What I had not written was anything to keep the orchestrator running.<br>So the orchestrator went down, and the hooks kept working. For five days they wrote into a spool that reached 1,880 events and 4.6 MB. The dashboard showed a healthy feed. The trail verified. The doctor command reported no problems. Nothing anywhere said that capture had not reached the trail since Monday.<br>There was a deadline attached, too. Spooled events older than seven days are not replayed, because injecting a week-old tool call into today's correlation window produces false sequences. The oldest entries were five days old when I found them.<br>I had roughly 45 hours before a flight recorder started deleting its own black box.<br>Two fixes. The recorder now installs itself as a supervised background service that restarts within a minute of dying, which turned out to have three separate failures of its own. And doctor now fails loudly when the spool is backed up. An empty feed and a stopped recorder used to look identical. That ambiguity is the whole bug.<br>Draining the spool destroyed events<br>Then I drained the backlog, and the drain deleted data.<br>The original code read the whole spool file, replayed every event, then unlinked the file. Replaying 1,880 events takes minutes, and the hooks keep appending the entire time. So the unlink destroyed every event captured during the drain, silently, and worst on exactly the busy machines the spool exists to protect.<br>The fix is the standard log rotation shape: move the file aside first, so hooks immediately start a fresh spool and only the rotated copy is ever deleted.<br>I caught this because I took a snapshot before draining, on the general principle of not trusting my own code with the only copy of something. Ten events had been lost by the time I looked. I appended them back.<br>The one that would have embarrassed me in front of an auditor<br>This is the bad one.<br>The hook never sent a timestamp. The orchestrator stamped each event with its own clock at ingest, which is accurate to the millisecond while ingest is live. It is wrong by up to a week when it is not.<br>So when I replayed five days of spooled events, all 1,880 of them were recorded as having happened inside a three minute window that afternoon.<br>Two consequences. The first is loud. Every sequence rule keys on "A then B within N minutes", so events days apart became correlated, and the drain produced twelve detections including two criticals. I started investigating one of them, a credential read followed by a git push, and had assembled half a story before I checked the reconstruction. Those two events were four days and six hours apart. The other flagged session spanned a day and a half. Neither described anything that happened.<br>The second consequence is quiet and much worse. A record whose entire purpose is to say when things happened was saying it wrongly, and it would have said it wrongly to an auditor with a straight face.<br>The hook now stamps the time at capture. Replay backfills from the spool's own write time for older entries, and never overwrites a timestamp the hook supplied.<br>The mis-stamped events are still in the trail. It is append-only and hash-chained, and rewriting history to hide my own bug is not a thing this product gets to do. The twelve detections are dispositioned as false positives with the root cause written into each one, which is what the disposition mechanism is for.<br>Two false positives, both aimed at exactly the wrong people<br>The remaining two are ordinary detection quality bugs, and they share a shape.<br>A critical alert on curl http://127.0.0.1:8000/api/v1/audit/status | python. That is the exact shape of a download cradle and none of the substance. Nothing crossed the network. The payload was my own orchestrator's status...

events spool tool orchestrator days four

Related Articles