Mandu: Keeping your secrets from your AI coding agent
Coding agents like Claude Code and Codex read your .env, your SSH keys, your cloud logins, and your documents while they work. Once a secret is read, it rides along in every request to the AI provider, and an agent that holds a key can send it to any server a command names. Today I want to introduce Mandu (GitHub), an open-source tool that lets your agent work next to your real secrets while the AI only ever sees masked placeholders.

Take a simple question: "How much did we charge on Stripe last week?" The question has no secret in it. But to answer it, the agent reads .env for the Stripe key, and maybe a confidential board memo along the way. Only api.stripe.com needed the key, and the memo never had to leave your machine. Yet the AI provider gets both with every request, and so can any server a command names.
The problem with "just block it"
The obvious fix is to forbid the agent from reading .env. That keeps the key at home, but the agent can't use it either. It can't debug the failing Stripe call, push to GitHub, or move your configuration to a hosting platform. What we want is an agent that can use a secret without seeing it.
The same file, read two ways
Mandu keeps two views of the data the agent touches. The AI sees a placeholder. You, and the programs you allow, get the real value.
# ~/proj/.env, as the AI sees it
STRIPE_KEY=$MDU:nomodel_Read[9bbd].STRIPE_KEY
GH_TOKEN=$MDU:nomodel_Read[3e1a].GH_TOKEN
DEBUG=1
# the same file on your disk, for the programs and hosts you allow
STRIPE_KEY=sk_live_51Hq8xT2…
GH_TOKEN=ghp_7Qx2Lm9a…
DEBUG=1
The agent can pass the placeholder around, put it in a command, or write it into a file. The placeholder turns back into the real value only on its way out, and only where it belongs: for example, to api.stripe.com for the Stripe key. Anywhere else, the send waits for your approval on Mandu's dashboard.
The name comes from this design. A mandu is a Korean dumpling: the agent handles the wrapper, and the filling, your secrets, stays with you.
How it works

Each secret has a rule that answers two questions:
- Which AI may read it? No AI at all, only a model you run yourself (such as Ollama), any AI when it asks, or none of the above because it isn't secret.
- Where may it be sent? By default every send needs your OK. You can also bind a secret to a list of trusted hosts, or give each value in a
.envits own hosts.
# ~/.mandu/policy.yaml
paths:
- path: ~/proj/.env
level: no-model # No AI
bindings: [api.stripe.com] # the real key goes only there
- path: ~/work/board-memo-q4.md
level: local-model # Your own AI only
Mandu does not modify the agent. Instead, it sits at the points where data enters or leaves the agent's world. A model proxy masks secrets before tool results reach the AI. An egress proxy puts the real value back only for a host the rule allows. A file guard gives unlisted programs a masked copy of credential files. A reply filter shows you the real values in the agent's answers. Mandu runs as your user, without root, adds kernel hardening (seccomp, Landlock, and a no-network sandbox for read-only commands) where the kernel allows, and fails closed: if it can't decide, the value stays masked or the action is blocked.
Mandu works with Claude Code, Codex, OpenClaw, OpenCode, and Goose, uses your agent's own login, and needs no account or Mandu server. Nothing leaves ~/.mandu.
npm install -g @mandusec/mandu # needs Node 22.13 or newer
mandu claude # your agent, protected (or: mandu codex)
mandu dashboard # what was protected, and what waits for your OK
Does it actually work?
We ran fifteen everyday tasks that involve a secret, such as filing a bug report, going through an inbox, scrubbing a key from git history, debugging a payment error, and texting the dog sitter the house codes. Each task ran three times, live with Claude Code and Claude Sonnet 5.5, under Mandu, under eight other protections, and under no protection at all (450 runs in total). A run counts only if the secret was kept and the task got done.
| Setting | Kept the secret and did the task |
|---|---|
| Mandu, with a rule for each task | 43 of 44 |
| Mandu, fresh install, no setup | 41 of 45 |
| Claude Code credential mask, set up for each task | 27 of 45 |
| Claude Code deny rules, set up for each task | 14 of 45 |
| No protection | 2 of 44 |
With a browser agent (browser-use on Gemini 2.5 Flash), no secret was kept without Mandu (0 of 18), and every one was kept with it (18 of 18).
These numbers come with caveats: we chose the tasks, we tuned Mandu on earlier runs of them, and we tested one agent with one model. The full method, every competing tool, and all the caveats are in the comparison report.
Mandu also has a clear scope. It protects secrets. It does not stop indirect prompt injection: a malicious web page can still steer the agent, for example into leaking source code that isn't registered as a secret.
From research to a tool
Mandu builds on two lines of work from our lab: Prompt Flow Integrity and DualView, which we introduced on this blog in July. From DualView, Mandu carries forward the placeholder table and the policy engine. Mandu moves the protection from inside one agent framework down to the operating-system level, so it works with off-the-shelf agents without any plugin.
Mandu is free, open source under Apache 2.0, and currently in beta. Give it a try:
- Website: mandusecurity.com
- Code: github.com/mandusec/mandu
- Install:
npm install -g @mandusec/mandu - Demo videos with Claude Code, Codex, OpenCode, OpenClaw, and Goose: mandusecurity.com
If your team runs agents next to real credentials and wants to work with the Mandu team as a design partner, write to hello@mandusecurity.com.
