Agreed, and "outside the worker's control" is the part people get wrong even when they get the fingerprint right. If the approval sits in the same store the worker can read and write, a compromised worker mints its own permit and every downstream check passes honestly. The approval has to live somewhere the worker can only request from, never issue into.
In Airmsh the equivalent is that the credential never leaves the host that owns it, and the policy decision happens at the destination against a pinned identity, so the agent asking is not the thing deciding. Denied calls get written too, not only the allowed ones, which is the difference between a record and a receipt.
If it's useful, I can show you a live one: one query allowed, a second denied, both landing in the audit view, two minutes. I'd rather you poke at it than take my word for it.
"The audit trail is clean. The system is compromised." That's the sentence I'd put at the top of the article, because it's the one nobody pricing agent security has absorbed yet. Every audit product on the market answers "was this allowed?" and none of them answer "allowed according to what, signed by whom."
The strongest bit in your piece is the fingerprint of the exact text the owner saw, and that the approval gets consumed on write. Most people approve a tool. You're approving one specific action with one specific payload, which means the approval can't be reused for a neighbour. I pin MCP tool schemas by SHA-256 the same way, and any change forces a re-pin, precisely because "the tool" is not a stable object between approval and call.
One question on the implementation: does the approval fingerprint live inside the same record as the call, so the destination decision and the caller's claim are written together? Or is approval a separate table the worker can also read? The second version is the one that leaks, because a compromised worker reads its own permit.
The blast radius framing is right and the rollback rule is the part most people skip. One thing worth adding: scope the agent by what it can reach, not only by what you feed it. Context narrowing stops it wandering, and it doesn't stop an agent with a valid credential doing something wide by accident. Do you enforce that boundary anywhere outside the prompt?
The checklist problem is that every item assumes the model can tell instructions from data. Once both are in the same token stream it can't, so anything on the checklist that runs inside the model was never a control. What survives is the check the model can't talk past: the destination deciding whether this caller may take this action, and recording the deny. Is your practical pass landing on that, or are you still finding teams who think a good prompt is the boundary?
Over-scoping is the one I don't think I've solved, only bounded. If the issuer writes the envelope it can write too broad an action, and the destination can't tell intent from a wide request. The only defence I have is short expiry plus re-issue per task. Do you know a check that catches over-scoped at issue time, before it's ever sent?
Replay: audience plus nonce plus a short expiry, and the destination keeps seen nonces for the window. That's the standard shape and it is the part I got wrong first, because a version-only check on the policy bundle doesn't stop an older looser one being replayed. Binding the policy version into the envelope does.
That's the whole argument and you've just made it better than I did. Given versus looked up is the line. Once the scope travels with the request, the destination has nothing to resolve and nothing to keep current, which is also why the deny is cheap to record.
I've been building this for a while and I'd genuinely like a red-teamer's read on where it holds. Want me to send you the two-minute version, or would you rather I put the mechanism in front of you here first?
SPIFFE is the closest of those three and it still stops one step short. It proves which workload is calling, which is identity, and identity is what lets the callee look up a scope rather than receive it. So the callee ends up trusting its own mapping table instead of the caller's claim about what it's doing. I put the resource and the action inside the signed envelope, so the destination rejects an action it wasn't asked about, rather than resolving an identity into a permission set and hoping the map is right. Do you think SPIFFE plus a per-action extension gets there, or does the mapping table stay the weak point?
ambient authority is the whole bug. Allow a tool and you've usually allowed everything the token behind it can do, so the list is per tool while the blast radius is per credential. The fix has to move scope to the action: the destination knows which agent, which resource and which action, and refuses anything outside that even when the tool itself is permitted. Do you see anyone doing per-action scope at the callee yet, or is everyone still scoping at the tool?
Your framing that most leaks are a log line nobody looked at twice is right, and redaction catches the ones that pass through. The ones that survive sit in a token the agent read off disk and used without logging it anywhere. I keep service credentials off the agent's filesystem entirely and enforce at the destination, so there's nothing to redact on the way out. Does evlog redact before the drain as well as the console, or only what you print?
The token in the repo file is the part people miss. An agent's permission set is every credential it can read, so listing them is a discovery problem that never ends. The other option is not having them readable at all: keep the credential on the host that owns the service and let the agent ask that host through policy. Then the answer to your first question is a short list you control. Did the PocketOS writeup say how the token ended up in that file?
@VictorJanni@anrayama@mjmj275 Same shape as yours: signed bundle, version, expiry, host verifies on load. Version alone doesn't stop a replay though, because a replayed bundle is internally consistent and the signature still
Do you bind version into the token or check it separately at load?
Receipt on land is the stronger rule, and it moves the write to the far side. The runner can only honestly say what it sent; the host is the only thing that knows what arrived, so that's where I'd have the receipt written and signed. Makes resume-from-last-confirmed fall out for free. Are your skills writing that receipt themselves, or does the runtime do it around them?
The reachability is the whole incident, and the backups being on the same credential turns it from an incident into a loss. I'd add that making environment and scope a precondition only works if it's enforced somewhere the agent can't edit. We scoped secrets to one host and check identity at that host for exactly that reason. Did they isolate the backups afterward?
Read-only from the agent side is the right instinct. The remaining question is who can write to the policy service, because that one caller can widen every rule at once. I moved the decision to the destination and made policy changes signed requests the host verifies, so there's no single writable place. Does your signed path cover reads too, or only the writes?