Your AI agent runs with all your permissions. I built a cage for each tool call, in Rust
A subagent got a simple task: read a project's docs and say how to run it. It read docs/readme.txt , found "make run", and then asked for one more file: ~/.ssh/id_rsa . Why it asked doesn't matter. A hidden instruction in something it read, a buggy third-party tool, a model that "thought" the key w

A subagent got a simple task: read a project's docs and say how to run it. It read docs/readme.txt, found "make run", and then asked for one more file: ~/.ssh/id_rsa.
Why it asked doesn't matter. A hidden instruction in something it read, a buggy third-party tool, a model that "thought" the key would help. What matters is what happens next, and in most setups today the file is read. Not because anyone granted the subagent access to the key, but because nobody granted anything to anyone: the tool runs as your user, and your user can read your key.
There's an old name for this: ambient authority. The kernel doesn't know about agents. It sees user ana and processes of ana. It can't ask "was this Ana, Ana's agent, or the tool her agent's subagent downloaded yesterday?".
I wanted something one level down: per tool call, decided by a permission that can only shrink as it is handed on, and proved afterwards.
CleiMesh is a Rust node (MIT or Apache-2.0) that puts five pieces together:
# Reading the inbox brings in outside content; writing to the outbox acts on the world cleimesh token issue <agent> --tool file_read --read ~/inbox --taints -o read.json cleimesh token issue <agent> --tool file_write --write ~/outbox --clean-only -o write.json Enter fullscreen mode Exit fullscreen mode A real model, a poisoned mail I ran OpenClaw with a local Qwen3 4B on Ollama and a mail carrying a hidden instruction to write a secret to a file.
That first act is the honest limit: CleiMesh only contains what goes through it. cleimesh doctor reads Claude Code's and OpenClaw's config and warns when the agent still has its own file or shell tools. And it doesn't "solve" prompt injection: the model can still be fooled, and an allowed action can still be the wrong one. What the node adds is a rule outside the model that the model can't argue with.
curl -fsSL https://github.com/cleitonaugusto/cleimesh/releases/latest/download/install.sh | sh # or from source: cargo build -p cleimesh-cli CLEIMESH = target/debug/cleimesh examples/demo/demo.sh Enter fullscreen mode Exit fullscreen mode The demo runs in a fresh /tmp directory with a fake project, a fake ~/.ssh and throwaway keys. It's alpha: the threat model in the repo lists what it protects, what it doesn't, and the gaps before 1.0.
Repo: https://github.com/cleitonaugusto/cleimesh
I'd like opinions on two things: grouping receipt fsyncs without weakening "no receipt, no run", and the guest ABI (core module now, Component Model before 1.0).
I also wrote up the design, the attacks and the mistakes in a book, AI Agents in a Cage.