You trip the kill switch on an agent at 2 a.m. Next morning someone asks: did it actually stop, and can you show me?
You can point to three things, and each proves something different:
→ You pressed stop: the operator credential issued the command
→ The gateway signed a refusal: it refused that call, at that moment
→ Nothing new reached the tools: through the gateway you were watching
We built a test for the cMCP kill switch that fails when the switch is broken: 27 checks through trip, restart and recovery, plus two deliberately broken builds. Both get caught at exactly the check that should fail. An outside evaluator reran the whole package on his own machine with his own keys and every result matched ours.
The limit: a signed refusal is historical. In our test an old refusal still verified after the gateway was recovered. Nothing in the protocol asks the gateway a fresh, time-bound question, and a tool reached around the gateway is invisible to it.
A receipt from yesterday is not a check today.
medium.com/@isiddique/who-ch…
A supplier shares pricing data under "internal forecasting only". The retailer's agent hands off to a second agent, which emails a slice of it to a vendor. Six months later the supplier asks: was that allowed?
I spent August looking for the standard that answers it. Every piece already has one. ODRL 2.2 writes the terms. OAuth token exchange covers acting for someone else. The IETF Attenuating Agent Tokens draft narrows authority at each hand-off. RATS and EAT say what was running. SCITT, now RFC 9943, gives receipts anyone can check.
Each one passes at its own door:
→ the first token was fine
→ the delegation chain verifies offline
→ the attestation result is valid
None of them knows about the others. "Internal forecasting only" does not survive the hand-off. The chain never points back to the agreement. The attestation belongs to the machine, not to that email.
So the fourteenth row on my table, the whole action end to end, has nothing under it. No adopted profile says what a complete record holds, or how a checker tells a missing link from a passing one.
Two limits stay whatever you build: the agent token work is still an Internet-Draft, and a location claim is a signed assertion, not proof of where something ran.
A missing record and a passing record look the same when nobody is counting.
medium.com/@isiddique/every-…
Imran Siddique retweeted
When you consult, you know it won’t last forever.
So I picture how it ends. My clients ringing the NASDAQ bell. Or maybe an acquisition. It's not my company, so the best I can hope for is that one day we all look back and agree I had some small part in their success.
Today I got my wish.
I’ve known @Roebot for more than 20 years. Today he announced that @opaquesys next leg of the journey is with Anthropic.
Aaron and Opaque’s founders took one of AI's most important privacy techniques, confidential computing, and made it work.
You can run AI on your most sensitive data without exposing that data to anyone, including the people who run the infrastructure.
Don’t take my word for it:
“Confidential Computing is super important.” – Jensen Huang, NVIDIA GTC 2026
That’s what it takes for enterprises to trust AI with the data that matters. Now @AnthropicAI helps carry that work forward.
Aaron, thank you for letting me tailgate on your road trip. I’m proud of you, and grateful I got to ride along for some of it.
And to @mosiddi , it’s been a lot of fun working with you, and I learned a lot from you. I wish you both the best in the next chapter.
I can’t wait to see what you do next.
P.S. If you’re building something with AI and could use some help, I can’t guarantee a bell at the NASDAQ. But I’d love to help you out. Send me a DM
My time at OPAQUE Systems is coming to a close. Next, I'm joining Anthropic.
I joined in June with one goal: move the company from confidential AI to verifiable AI. Confidential computing protects data while it runs. A customer, an auditor or a regulator still cannot see what the agent did with it.
Four and a half months:
→ OPAQUE 3.0 went GA on September 30, with agent controls next to confidential computing in one platform.
→ TRACE, a signed record of what an agent ran and what it did, became a Linux Foundation project on August 25, developed with AMD, Intel, Microsoft and TII.
→ 92 releases, 16 papers with DOIs, more than 670,000 PyPI downloads, and 119 people besides me with merged code.
Not finished: TRACE is proposed as an AAIF Sandbox project, not accepted. The open projects stay vendor-neutral at agentrust-io.com, and I keep maintaining them.
Aaron Fulkerson and Rishabh Poddar, thank you for the bet. Qiang Xu and the engineering team, thank you for picking the hard version every time.
linkedin.com/posts/imransidd…
An agent calls a tool. Six months later someone asks which policy allowed it, whether that was the approved agent, and whether the record can still be trusted.
Answering that needs three things to hold:
→ the policy decision happened before the call ran
→ nobody could quietly edit the record afterwards
→ you can show which agent actually ran
On 23 October at AGNTCon + MCPCon in San Jose I'm walking through how to get each one: Cedar policies evaluated before every MCP tool call, audit chains that make later edits detectable, and hardware attestation for what ran.
I'll cover the limits too. A signed receipt shows the record was not changed. It cannot tell you whether the agent's answer was correct.
Friday 4:05 PM PDT, Room 230C. COMMUNITY50 takes 50% off registration, courtesy of Demetrios.
events.linuxfoundation.org/a…
Your OpenTelemetry trace can tell you what your agent did. It cannot tell you whether it was allowed to.
→ The policy decision is in the policy engine's log
→ The approval is in a workflow database
→ The data classification is in a DLP product
Each system has its own id for the same run, and after an incident the join is a person with a spreadsheet.
agentrust-telemetry is one event contract for those governance facts, hash-chained under RFC 8785, sitting next to your GenAI spans rather than replacing them. Its OTel compatibility matrix claims exactly one exact mapping, the agent id. Everything else is marked extension, complementary, non-equivalent or deferred.
I re-ran its conformance suite today on 0.1.0-alpha.6. 18 of 18 pass, including a fixture whose prompt field reads "copy the production credential". The validator refuses it.
The limit: it checks that declared facts are well-formed. It cannot prove a producer's policy decision or cost figure is truthful.
medium.com/@isiddique/your-t…
The OSSA README now says the current stable release is 0.5.7 and gives the install line for it. npm has no 0.5.7. Yesterday the same README said 0.6.0, which npm does not have either.
→ The documented install fails with E404.
→ The version that does install, 0.5.6, exits 1 on Node 24: cannot find package commander, which it imports and never declares.
→ Last night the package manifest moved to 0.5.7, and nine minutes later the version file moved to 0.6.0 "to match the 0.6.0 package".
Both checks fit in a release script: resolve the documented install against the registry before tagging, and fail when any two files disagree on the version.
Checked this morning against the registry, a clean install and the branch head on GitLab. If 0.5.7 is published later today, the first line stops being true and the rest does not.
A provenance record can only name the contract an agent was held to if the contract has one name.
imransiddique.com/notes/2026…
Proof-of-Control says it is the evidence half of agent assurance, not runtime enforcement. Its own Level 3 threshold requires a gateway that holds each action until the record is written.
→ No Proof-of-Control claim without that gateway
→ Appendix C, the normative threat model, has 32 rows and none for the gateway being compromised or bypassed
→ The Level 4 coverage check reconciles gateway action counts against evidence counts. Both numbers come from the gateway, so an action that goes around it balances
I think the gateway requirements are right. The missing piece is the row. Issue 78 asks for two, gateway compromise and gateway bypass, with the gateway operator named as a trust assumption.
Limit: I read the text. I have not run a conformant deployment against it. The arithmetic does not depend on one.
Evaluating a system that claims Proof-of-Control? Reconcile the tool side's own request logs against the evidence store, never the gateway's counts.
Public comment is open until 30 October.
imransiddique.com/notes/2026…
A finance lead approves an AI agent to pay invoices for 90 days. On day three, a supplier gets flagged for fraud. The approval record still says approved.
→ Signed and valid.
→ Still in date.
→ Out of date, with no way of knowing.
Our Agent Manifest checks four things about a human approval, and all four can pass after the reason for it is gone. In agent-manifest 0.13.0 the verifier says "I can't tell" instead of staying quiet.
What it still cannot do is decide whether an approval applies today. That needs evidence about the present that no verifier has yet.
An approval is a claim about today, not a receipt from last month.
medium.com/@isiddique/approv…
The App Defense Alliance AI Agent Specification defines three kinds of lab evidence, then sets a default: a requirement that does not say which kind is Functional Observation, meaning black-box testing through the running agent.
None of its 37 Evidence blocks says which kind.
→ 2.4.2, tool allowlists and pinned identities, starts by reviewing the allowlist configuration. Neither the user interface nor the tool interface exposes it.
→ 5.2.1 asks for system log files, which is the taxonomy's own example of Attestation.
→ So a lab report saying 2.4.2 passed does not tell you whether the assessor saw the allowlist or took the developer's word for it.
Tagging every block was recommended in August and held out of PR 427. I filed it today as issue 514: a type line on each Evidence block, with the named artifact wherever it is not Functional Observation.
The 2.4.2 control itself is good. This is a reading of the text, word-boundary greps at commit 97c9f94, not an assessment I have run.
The pass is valid. What it was bought with is not in it.
imransiddique.com/notes/2026…
TRACE is building an open standard for verifiable AI agents, and @o1_labs has proposed composable ZK assurance.
Agent execution → ZK proof → TRACE evidence → public verification
This raises an interesting question:
Could Mina serve as a programmable verification layer for this not to run the AI agent, but to cryptographically verify what it did?
Mina’s recursive ZK architecture feels naturally aligned with this model.
Would love to see this explored further.
@linuxfoundation @mosiddi @zktrivo
Big moment for verifiable AI.
TRACE, developed with AMD, Intel, Microsoft, OPAQUE and TII, is officially joining the Linux Foundation.
o1Labs is proud to be contributing to the AgenTrust ecosystem, and our team recently contributed an RFC exploring how zero knowledge proofs can extend TRACE with privacy-preserving, independently verifiable proofs.
More to come 👀
Set the MCP TypeScript SDK's new body limit to 20 MB, build the server the way the SDK documents, send it 110 KB, and you get a 413. As an HTML page.
1.30.1 shipped on 23 September with two caps: 4 MiB per request body, 100 messages per JSON-RPC batch. I ran both against a live server.
→ 101 message batch: 400 from the transport, a JSON-RPC error, onerror fires once.
→ 110 KB body: 413 from Express's JSON parser at its 100 KB default. The MCP handler runs zero times, onerror zero times.
→ The 20 MB transport setting: validated at construction, never read.
The batch cap holds wherever the transport runs. The byte cap only holds where the transport reads the body itself, and the SDK's own Express factory parses it first.
The v2 Express package has a jsonLimit option. The 1.x factory, in the package npm counted 40.3 million downloads of last week, has no way to set it.
Neither is a vulnerability. Both caps work where they are checked, and downloads are not deployments.
imransiddique.com/notes/2026…
Imran Siddique retweeted
An enterprise wants an agent answering questions over sensitive records on its own infrastructure. The model provider wants its confidential weights usable only by an approved serving application. Both reasonable. The deployment question is how to make access to the model conditional on a verifiable release policy.
A look at Weight Custody Manifest, an open pre-1.0 spec that keeps the release conditions beside the model. A manifest identifies the weights and carries a policy signed by builder and custodian. A runtime presents attestation evidence before the broker releases the key, and channel binding ties the release to the runtime that supplied the evidence.
The practical distinction for agent-platform teams: permission to call an inference endpoint is not the same as permission for its runtime to unlock a particular model. Keep both decisions explicit.
Full post by Imran Siddique: bit.ly/4yOQweM
One Internet-Draft says the approver field has three legal values. The section that tells you how to verify it says two.
I read the editor's source for draft-mih-scitt-agent-action-capsule-04 this morning, then ran the reference implementation against the frozen vectors:
→ Disposition: "a closed enum, exactly human, policy, or counterparty"
→ Class 1 verification: "an approver value outside {human, policy} is non-conforming by construction"
→ 90 of 90 conformance vectors pass, including the one that expects counterparty to verify
The changelog records the edit that caused it. The enum was extended, the first section was updated, the second was not. The same changelog spells out the consequence: an old verifier meeting a counterparty capsule "would reject the Capsule outright".
So an implementer building a Class 1 verifier from the verification section builds the old verifier on purpose, from the current text, and it rejects exactly the cross-party records the revision added.
The code already disagrees with the text. Python, Go, TypeScript and Rust all hard-code three values. I resealed a blocked capsule with approver counterparty and it verified clean.
My limit here: I read the Go, TypeScript and Rust verifiers, I only ran the Python one. And this is a one-word edit, not a design argument.
Filed this morning as agent-action-capsule issue 108. The sentence is still in the unsubmitted -05 source, which merged a few hours earlier.
cMCP runs the policy engine for agent tool calls inside a TEE, and binds its code, policy bundle and config into the attestation report before it serves a single call. It also writes the record of what it did. We got that second half wrong.
It logs when a session that read sensitive data calls a tool outside that domain. In 0.4.1:
→ the check matched against pii, phi, pci, restricted
→ the runtime labelled data public, pii, confidential, hipaa_phi, mnpi, trade_secret
→ the two sets overlapped on pii alone
A session that read HIPAA PHI and then called an external tool recorded no crossing. The claim was signed, the attestation was valid, and the event was not in it. Fixed in 0.5.0 by deriving the set from one vocabulary.
Worth doing on any control plane, ours first: find every literal set of category names, find where those categories are actually defined, and compute the intersection by hand.
medium.com/@isiddique/every-…
Docker Sandboxes has had five CVEs this year. None of them is in the microVM. The latest two landed on 15 September at CVSS 9.4 and 8.7, and v0.42.0 fixes both.
All five sit in the two controls its README sells: file access between host and sandbox, and network access control. Three of them fail the same way.
→ ICMP egress was blocked by a check applied when the network was created, and never re-applied after a daemon restart.
→ The socket relay validated a path, then reconnected by name. A symlink swap in between reached an arbitrary host Unix socket.
→ The virtio-fs server reopened files from a stored path and followed a swapped symlink out of the workspace.
Each check was right when it ran. Each answer was treated as good for longer than it was.
So for every door a sandbox advertises, ask when the decision gets made again: at creation only, on every open, after a restart? Bind it to the object you act on, or re-check at the moment of use and fail closed.
What I did not do: reproduce any of the five. This is the CVE records, the README and the release notes read side by side, and the fix pull requests sit in repos I cannot open.
An enforcement decision has a lifetime.
imransiddique.com/notes/2026…
Agent Mesh will not let you create an agent unless you name a human who is answerable for it. The sponsor argument is positional and required, and a non-email raises before any key material is generated. That part is enforced.
Then I ran the accountability half against agentmesh 5.0.0 on my own machine:
→ sponsor_verified is False on creation. Nothing in the shipped module sets it, and no trust decision reads it
→ REVOCATION_PROPAGATION_TARGET = 5 appears exactly once, at its own definition, and is never read
→ I registered a revocation listener that raises, revoked a credential, and revoke() returned True
The local credential really was invalidated. Whatever was supposed to hear about it was not told, and nothing said so.
What I would still use it for today: identity, signature verification and short-lived scoped credentials. Tamper with a byte and verification fails, sign with another agent's key and it fails. That layer is real, and one conditional would make the sponsor layer real too.
A sponsor nobody verified is a well-formed string.
medium.com/@isiddique/agent-…
Can someone outside your organization verify your agent’s evidence?
On Sept 22, I’m joining Steven Mih and Mark Hinkle for a live TRACE Registry demo: signed checkpoints, a public witness, offline verification, and the limits of what that proves.
event.webinarjam.com/462og/r…
Two commits, four hours apart, same repo, 11 September. One replaced a regex read-only SQL check with a parser. The other answered the same bypass class by adding more keywords to a regex.
I installed the published MySQL gate and called it directly:
→ one space between the two words of a keyword is blocked
→ two spaces, a tab, or a newline is not
→ both the keyword scan and the injection check return empty, which is the entire rejection path
The fix is already in the same repo. The Oracle and SQL Server detectors join keyword words on a whitespace class instead of escaping one literal space. It is a two line copy.
Honest limit: this is a gate-completeness defect, not a demonstrated exploit. I tested the gate, not a live server, and the statement I checked needs a privilege the customer has to have granted. It went to AWS security, not a public issue.
A parse tree cannot be fooled by whitespace, because it is not reading text. A keyword list can be, and every separator costs an advisory to find out about.
imransiddique.com/notes/2026…









