The code you didn't write is already running
September 2025. A small MCP server on npm, postmark-mcp, doing something dull and useful: sending email for AI agents. About 1,500 downloads a week. Then version 1.0.16 shipped with one extra line. Every email the server sent, it also blind-copied to an address the author controlled.
Nobody who installed it wrote that line. Everybody who installed it ran it, with their email credentials, against their real inboxes. Koi Security caught it, the first malicious MCP server documented in the wild.
Now swap one noun and the story runs again.
An npm package instead of an MCP server: the Nx "s1ngularity" compromise, August 2025, 2,349 credentials exfiltrated, with the victims' own AI CLIs pressed into service to do the reconnaissance. A code-editor extension instead of a package: an Amazon Q update shipped to roughly a million VS Code users in July 2025 carrying a prompt that tried to wipe home directories. A syntax error is the only reason it didn't. A tool's own description instead of its code: hidden instructions the model reads and you never see, now catalogued as OWASP MCP03:2025.
The protocol keeps changing. The shape of the problem does not: an agent runs code, and follows instructions, that you did not write, with real access, at machine speed.
This post is about that problem, and then, concretely, about what we built for it.
One problem, four costumes
None of the costumes is "MCP." MCP is just the one with the most public incidents this year.
Code you install. postmark-mcp is the clean example. So is mcp-remote (CVE-2025-6514, ~437,000 downloads): connecting your client to a malicious server was enough to get remote code execution on the client itself. You did not run anything reckless. You connected.
Content that turns your own trusted agent against you. EchoLeak (CVE-2025-32711, CVSS 9.3) was a zero-click prompt injection that exfiltrated data out of Microsoft 365 Copilot. CamoLeak (CVE-2025-59145, CVSS 9.6) pulled data out of Copilot Chat through GitHub's own image proxy; the fix was to turn image rendering off. Note what class this is: the agent was yours, built and blessed by you. After the injection lands, it is executing instructions you did not write. Authorship was never the threat model. Access is.
The supply chain the agent lives inside. The Shai-Hulud npm worm, self-replicating, serious enough for a CISA alert on September 23, 2025. GlassWorm, October 2025, hid malware inside editor extensions using invisible Unicode characters, which is to say it was unreviewable by a human by construction.
And the base rate. In one offensive sample, Equixly found 43% of the MCP servers it tested had command-injection flaws. That is a vendor's sample, not a census, but it rhymes with what Backslash found: hundreds of MCP servers bound to 0.0.0.0 with no authentication at all.
The buyers already feel it. A 2026 CISO survey put 99% of organizations as having been hit by some SaaS-or-AI-ecosystem incident in 2025. A separate study found 69% of enterprises deploying agents and only 21% with the visibility to secure them. Adoption is not waiting for anyone to be ready.
Why the usual answers only get you part way
Review and approval. GlassWorm's invisible Unicode defeats human review by definition. And the MCP "rug pull" defeats approval on a different axis: the tool behaves during review, gets approved, then quietly swaps its behavior afterward, with no re-consent.
Allowlists and design-time defenses. These are real and getting better. The strongest published work on prompt injection constrains what an agent is allowed to express before it runs, and language-level runtimes are absorbing more of the sandboxing surface every quarter. We want them to. They shrink what can happen.
But they act on the plan and the inputs, before or around the model. None of them contains what a tool's implementation actually does on the host once it runs. Read the fine print of one such runtime and it says so itself: a well-built sandboxed shell (vercel-labs/just-bash) protects untrusted scripts, and trusts the host it runs on, its dependencies, and the network underneath. Its egress guard only governs traffic that flows through its own code. A third-party binary makes its own kernel network calls and never touches it.
Which leaves one question every one of these good tools eventually hands you: when the runtime becomes the sandbox, who checks the runtime?
"Sandboxing" is three jobs pretending to be one
Pull the word apart and it holds three different jobs with three different owners.
- Constrain your own agent. A controlled runtime genuinely does this. If you built the agent, you can shape what it is able to do. This job is getting solved, and not by us.
- Contain someone else's untrusted code. A runtime cannot do this for the same reason a lock cannot frisk a locksmith: the foreign code attacks exactly the surfaces the runtime has to trust. Your only real move is to run it inside a cell it does not control, and watch.
- Produce an independent record of what actually happened, one that someone who does not trust you can re-check. A runtime cannot do this at all, because the thing keeping the record and the thing being recorded are the same thing. That is the producer grading its own homework.
Control is not evidence. Making an agent's actions controllable-by-you is not the same as making them provable-to-someone-who-does-not-trust-you. Flight recorders, external auditors, and certificate-transparency logs all exist even though the operator fully controls the system. Somebody still wanted an independent record.
Probity is jobs two and three. And job three is not only about strangers' code: your own agent, once something has been injected into it, is running instructions you did not write either. So the record matters even when the code is entirely yours.
What Probity actually is
Plainly: it runs your AI agent in a sealed box, attacks it, and hands you a signed pass or fail. Before you ship it, and while it runs in production.
One box, two doors.
The first door is the Gate. One line in CI:
probity gate ./server.oci
That boots the workload inside its own hardware-isolated micro-VM, drives a precompiled battery of exploit probes at it, fails the build if anything is caught, and emits a signed verdict bundle. Zero config on the first run. It is shipped today.
The second door is the Runtime: the same sealed box kept wrapped around the agent in production, always on, so a boundary crossing gets caught and signed whenever it happens, not only at review time. The containment substrate is built; the always-on productized form (streaming verdicts, hosted multi-tenant) is on the roadmap, and we will say which is which every time.
The boundary sits outside the code, and it does not care about the protocol. Observation happens at the wall of the VM, host-side, not from an agent living inside the guest. File operations go through host-side hooks. Every last byte of egress goes through a host proxy in a per-VM network namespace, with look-alike domain names normalized and a sinkhole posture that keeps the network card live but never actually dials out: capture the attempt, drop it, write down that it happened. Secrets are swapped in flight, so the real credential never enters the VM at all; the code only ever touches a decoy. Across eleven different ways to steal a secret, zero real secrets have left the box.
Because the box only ever watches file operations and bytes on the wire, it does not care what produced them. That is why an MCP tool and an agent mesh are both live today, and why the next protocol is an adapter, not a rebuild.
A note on who does what, because it matters for a verification company. We build the attack corpus, hunt new attacks, sign the results, and disclose. The box boots, blocks, catches, and decides the verdict, with no human in that path: same input, same verdict, every time.
What it looks like when it fires
Claims are cheap. Signed artifacts are not. Two real runs, on real hardware.
The kill switch. June 25, 2026. An MCP server's destructive branch actually fired: a raw TCP connection to primary-db.internal:5432 carrying the literal bytes DROP TABLE customers; --. The sinkhole captured it and dropped it, the box emitted a host-signed record naming exactly which sink was blocked, and froze the VM at the instant of the catch, binding the frozen memory to the signed record.
Four credential-theft attempts, four catches, and four deliberately unsigned scorecards. June 26, 2026. Four real third-party servers (Slack, Google Maps, Sentry, Brave Search), each seeded with a decoy credential, each of which tried to exfiltrate it, each caught. The scorecards for those runs are left unsigned on purpose. We do not own that code, and our own rule forbids putting our signature on a verdict about software we do not own. That constraint sells the point harder than any green checkmark: the signature means something precisely because we withhold it when we should.
And the property underneath all of it: the trace is the authority, not the tested code's own report. A server that manages to achieve code execution and then forges clean-looking responses still cannot fake a pass, because the verdict is written from what the substrate observed at the boundary, not from anything the code says about itself.
What a pass is, and what it is not
Here is the sentence we will not soften: a Probity certificate states observed behavior under a bounded test. It never says "safe forever."
A pass is coverage-bounded provenance. We threw these attacks; these were contained. That is all it claims, and saying so is the product, not a disclaimer.
The clean illustration is a logic bomb hidden behind a one-in-a-billion random branch. No battery of tests rolls the billionth roll. Which is exactly why a Gate certificate is a snapshot, and exactly why the durable answer is the same box kept around the agent in production, where the billionth roll fires inside the wall and gets caught and signed anyway.
And you do not have to take our word for any of it. The verdict bundle is a signed, standards-based artifact you can re-verify yourself, offline, with a short Python script: no network, no model, no dependency on us. The one honest boundary of that chain: it assumes the host doing the observing is itself honest. Hardware-attested hosting, which removes even that assumption, is on the roadmap. Naming the limit is the credibility move, not a footnote.
The larger inversion
Everything above is one instance of a bigger shift. Agents made executing work cheap and abundant. What got scarce, almost overnight, is trustworthy evidence that the execution did the right thing. Why verification, not intelligence and not raw capability, is the actual bottleneck is the argument in the next post.
We are not alone in seeing it, and that is the good news. Two research groups published the same principle this June, independently of us and of each other: the Unfireable Safety Kernel makes the case that an agent's safety enforcement has to live outside the agent's own reach, and Sello argues that an execution record only counts as evidence when the recorder is not the thing being recorded. On the shipping side, Dapr 1.18 now signs its own workflow history, and a signed history the workload writes about itself is still self-report with a signature on it. When separate teams keep arriving at the same principle the category is real; what none of them do is attest the substrate the signer runs on. Signed receipts are necessary and not sufficient; the ground the evidence stands on has to be verifiable too, byte for byte, and that, plus the hardware anchor on our roadmap, is the layer we build.
If you are on the hook for an AI agent, yours or someone else's, you can run the Gate on a single server today, or ask us for access and we will help you point it at the thing you are worried about.