DEV Community

Imran Siddique
Imran Siddique

Posted on • Originally published at Medium on

The best agent detector in production catches 67%. Plan for the rest.

Last week two of the strongest engineering organizations in this industry open-sourced their agent security stacks three days apart. Uber released ADR, the detection and response system it has run in production for ten months. Perplexity released Numbat, an Apache-2.0 agent security suite already deployed across thousands of its own endpoints. Both are real, running, well-built software, and if you operate agents at any scale you should read both this week.

Then read ADR’s paper, because it contains a number that almost nobody quoting the release has repeated. On ADR-Bench, Uber’s own benchmark of 302 tasks, 17 attack techniques and 133 MCP servers drawn from real telemetry, ADR detects 67% of attacks at zero false positives. That result beats ALRPHFS, GuardAgent and LlamaFirewall by two to four times on F1. It is, as far as the public record goes, the best agentic attack detection anyone has published.

State of the art, ten months in production, benchmarked against its own real-world telemetry, and roughly one attack in three gets through.

67% is not a failure. It is the ceiling.

I want to be precise about the compliment here, because it matters. Uber published that number. They built the benchmark that exposes their own limit, put it in a paper, put the sensor and the detector and the benchmark on GitHub, and let you check. That is proof rather than promises, and it is rarer than it should be.

The number is not an indictment of ADR. It is a property of the category. A detector is a bet on the attacks you thought of. ADR-Bench encodes 17 techniques, which is 17 more than most teams have enumerated, and the honest reading of 67% is that even an excellent detector, tuned against real traffic by a team with production scar tissue, cannot close the set. The residual is not sloppiness you can engineer away with better rules. It is the part of the threat space that was not in the training distribution, and it will exist in every version of this product forever.

So the operational question is not how do we get to 100%. It is what do you have left when the detector does not fire?

If the answer is your logs, you do not have much. Logs are written by the host, on the host, and they are editable by whoever just took the host. The single most common shape of a serious incident is that the record of the incident is controlled by the party you are investigating.

Detection is a probability. Evidence is a record. You need both, and only one of them still works after you lose.


Controls act only to the left of the ceiling. The record is drawn undivided because it does not depend on classification.

RufRoot is what the other third looks like

While those two releases were landing, the agent ecosystem produced a near-perfect illustration.

CVE-2026–59726, which Noma Security named RufRoot, is a CVSS 10.0 in Ruflo, an agent meta-harness in very wide use. Every version before 3.16.3 shipped an unauthenticated MCP bridge, open to the network by default, exposing 233 tools, including shell execution, database operations, agent management and memory storage. One unauthenticated HTTP request gets remote code execution. It was disclosed on June 30 and, to the maintainer’s credit, patched inside 24 hours.

Here is the part that should change how you think about your own deployment. The remediation guidance does not stop at upgrade. It tells you to rotate every LLM API key, close ports 3001 and 27017, inspect MongoDB for tampering, and audit the AgentDB pattern store for malicious entries, because a patched redeploy alone does not undo the poisoning.

Read that again as an operator. The researchers demonstrated writing attacker-controlled entries into the agent’s persistent memory, so that future responses incorporate attacker instructions. You patch to 3.16.3. Your scanner goes green. Your dependency report is clean. And your agent is still compromised, because the compromise is no longer in the code. It is in the state.

Detection did not catch this, because there was nothing anomalous to catch: an authorized tool wrote to an authorized store. Patching did not clean it. And nothing in the ordinary stack can tell you whether that store is the one you started with.


The redeploy replaces the measured image and never reaches the pattern store, so the poisoned entry survives the patch.

Unmeasured is not empty

The mistake underneath all of this is treating agent memory as a cache.

If memory were retrieval, RufRoot would be a nuisance and you would flush and move on. But agent memory is accumulated state that changes future behavior, which makes its integrity a security property of the running system, exactly like a policy bundle or a tool catalog. We already accepted this for code. Nobody ships a container without a digest. Then we hand the same agent a persistent store that shapes every subsequent decision, and we measure nothing.

A store you never measured is not a clean store, and it is not a corrupted store. It is a store about which you can say nothing at all.

Which is why “no evidence of tampering” is a statement about your instrumentation rather than about your agent. The fix is not exotic and it is not new thinking. It is what we do everywhere else: measure the state, bind the measurement to hardware, and make a change that nobody recorded detectable rather than invisible. If the pattern store’s digest is measured into an attestation and anchored in an append-only registry, an attacker who poisons it either leaves an entry you can find or breaks a chain you can verify. The poisoning stops being a silent non-event.

What attestation does not do

This newsletter is called Proof not Promises, so here is the part that cuts against me.

Attestation does not stop the action. Numbat’s pre-action hook does something a signed record fundamentally cannot: it evaluates a proposed command before it reaches the operating system and refuses it. Fifty-two rules across eleven behavior categories, expressed in CEL, running in a Go binary on the endpoint. That is a real-time no. Evidence arrives afterward, and afterward is not always good enough. Anyone telling you attestation replaces controls is selling you something.

The two layers do different jobs and you want both. Controls reduce the probability. Evidence removes the deniability. ADR and Numbat are strong work in the first category. What I am arguing is that the second is not optional once your detector’s honest number is 67%.

And the harder admission: the memory half of this is not built. We have measured policy bundles and tool catalogs into hardware attestation for a while now. Persistent agent memory, the pattern stores and long-term state that RufRoot went after, is open work in our stack as much as anyone’s. I am writing that down in public deliberately rather than filing it away, because I would rather it get built than owned.

Where the evidence layer already is

The receipt half exists today, in the open, and you can run it.

  • TRACE produces a signed, hardware-rooted, offline-verifiable record of what ran: which model, under which policy version, on what hardware, with the full tool transcript. github.com/agentrust-io/trace-spec
  • cMCP enforces policy inside a hardware-attested enclave at the MCP boundary, the same boundary RufRoot left unauthenticated. The policy bundle is measured into the attestation report before any code runs, so a compromised host cannot quietly swap it. github.com/agentrust-io/cmcp
  • Agent Manifest binds what an agent is, its prompt, policy, tool schemas, model identity, provenance and delegation chain, to hardware, so that not being sure what was running stops being an available answer. github.com/agentrust-io/agent-manifest
  • AGT covers the deterministic allow and deny layer at the action and tool-call boundary, against 10 of 10 of the OWASP Agentic Top 10. github.com/microsoft/agent-governance-toolkit

Two invitations, both real. If measuring agent memory state is your problem, come build it with us, because it is the gap I would most like closed this year. And if you run agents in production, read the ADR paper and the Numbat rules properly, adopt what fits, then ask the question the 67% forces: when the detector stays quiet, what will I be able to prove?

Detect what you can. Record what you cannot. And measure the state, because unmeasured is not empty.

Sources

Ruflo v3.16.3 security release: github.com/ruvnet/ruflo/releases/tag/v3.16.3

Top comments (0)