Secret keys
API keys, tokens, passwords, SSH keys, cloud credentials. Once read, the key travels to the vendor in every later request.
Open source · by Mandu Security
Mandu keeps your secrets for you, and keeps your AI agent useful. Claude Code, Codex and other coding agents work with placeholders for your keys and private files, while you and the programs that need them still get the real values.
DATABASE_URL=$MDU:nomodel_Read[4c1e].DATABASE_URL STRIPE_KEY=$MDU:nomodel_Read[9bbd].STRIPE_KEY GH_TOKEN=$MDU:nomodel_Read[71a0].GH_TOKEN DEBUG=1
Opaque placeholders. The AI can pass them around, put them in a command, and tell which variable is which. The values never reach the model.
The problem
Whatever a coding agent reads goes into the model's context and to the model vendor, with every request after that. Stripe will not answer without the key, so the agent has to use it, and to use it, it reads it.
Secret keys
API keys, tokens, passwords, SSH keys, cloud credentials. Once read, the key travels to the vendor in every later request.
Personal documents
Health records, tax returns, a lease, a diary. The agent needs the content to do the job. The question is which model may read it.
Company documents
Contracts, plans, financials, customer lists. Company policy often says no outside model, or only the one the company runs.
curl with the key, to whatever host the command names.any server: a gist, a webhook, a tunnelMandu stops the secret from leaving, whoever asked for it.
Why Mandu
Other tools keep the secret by taking work away from the AI. Mandu does its best to keep both.
| Approach | How it works | The agent does the task | The secret stays private |
|---|---|---|---|
| Trust the agentClaude Code, Codex as installed | Run it as is. It reads .env, your lab results, the board memo, whatever helps. | Yes | NoThe vendor gets it, and any host a command names. |
| Lock it outNVIDIA OpenShell, nono, Microsoft Purview | Block the files with a sandbox policy, or a sensitivity label the AI may not process. | NoNo psql, no deploy, no summary of the memo. | Yes |
| Mask in the shellClaude Code's credential mask | Commands see a stand-in; a proxy swaps the real key into allowed HTTP calls. | PartlyHTTP APIs only; psql and ssh break. | PartlyThe model's own file reads still see it. |
| Mandu | Placeholders for the AI; real values only at the right exit. | Yes | Yes |
.env, ~/.aws, ~/.ssh, secret-named variables. You name your documents.psql, ssh and bound hosts get the real value.How it works
Mandu keeps two views of the same files. The AI works in one where secrets are placeholders. You and your programs work in the other, with the real values. Only Mandu's local table maps a placeholder back, and the agent can neither read nor change that table.
curl api.stripe.com/v1/charges \
-u $MDU:nomodel_Read[9bbd].STRIPE_KEY:
api.stripe.com, and only there.psql reads ~/.pgpass; only the ssh that git started reads your key.publicAnyone. Ordinary files.any-modelAny model; never leaves the machine.local-modelOnly a model you run, such as Ollama.no-modelNo model. Only you and the programs you name.# ~/.mandu/policy.yaml paths: - path: ~/work/board-memo-q4.md level: local-model # your Ollama - path: ~/Documents/health/ level: no-model - path: ~/proj/.env level: no-model bindings: [api.stripe.com] models: - { name: ollama, local: true, … }
With any-model, a quarantined helper can summarize the memo while neither the file nor the summary reaches the main model.
mandu demo plays this on your computer, offline, with no API key.Evidence
Use a .env without seeing it, run a deploy script, use a cloud profile, commit and push, dry-run a package publish. Sonnet 5 and Opus 5.5, three runs each: 36 sessions per side.
Mandu in its default secrets mode against Claude Code's sandbox.credentials mask. All four leaks went through the model's own Read, which the shell mask does not cover. The check looks for the secret verbatim, in base64, hex, reversed and rot13. Benign tasks, no attacks. Method and raw numbers are in the repository's design docs.
Fits the way you work
mandu in front of your agent. That is the whole change.Claude Code, Codex, OpenCode, OpenClaw, Goose and programs built on the Claude or Codex SDK. No plugin; Mandu stands outside the agent and uses its own login.
Your secrets stay where they are, in the format they have. There is no vault to move them into.
Everything runs as your user. Kernel hardening (seccomp, Landlock, a sandbox for commands) turns on wherever your kernel allows it without root.
There is no Mandu server. All state lives in ~/.mandu, readable only by you.
If a part cannot decide, the secret stays a placeholder or the action is blocked. It never falls back to the real value.
Declare an Ollama or vLLM as yours, and it may read what outside models may not. It can be the main model too.
Limits
Knowing exactly what is covered is part of the product.
In the default secrets mode, a web page or someone else's file reaches the AI as written. A hidden instruction can still steer the agent, for example into sending out source code you never named as a secret.
Secret keys are found for you; secret documents once you name them. Everything else is ordinary data. mandu doctor --secrets lists what the scan could not check.
Linux x64, tested on Ubuntu 24.04 and 26.04. 64-bit ARM is built but not yet tested on hardware; WSL2 is tested in simulation only; macOS is experimental.
The modes that also mask untrusted text, injection and full, stay in the code as experimental, behind MANDU_EXPERIMENTAL_INTEGRITY=1.
Get started
Mandu finds your secret keys on its own and uses your agent's login. It needs no API key of its own; a Claude Pro or Max plan works.
Mandu is in an invited beta. Invited accounts download the latest release from GitHub and run sh install.sh (no sudo). At the public launch this becomes npm install -g @mandusec/mandu. To join the beta, write to us (see Company).
# check this machine: Node, git, your agent, your secrets $ mandu doctor # your agent, protected (or: mandu codex) $ mandu claude mandu: mode secrets (14 credential files masked, 3 env vars masked) mandu: dashboard http://127.0.0.1:38121/ # approvals, rules, what was protected $ mandu dashboard # the recorded tour, offline, no API key $ mandu demo # make it the default $ alias claude="mandu claude"
Open source
Security software that guards your secrets should be readable by the people it guards. Mandu is AGPL-3.0-or-later. The Rust arbiter client is Apache-2.0, so other runtimes can integrate freely.
Replace a secret with a placeholder wherever it enters the agent's world; put the real value back only where it leaves to where it belongs.
| Boundary | On the way in | On the way out |
|---|---|---|
| Model context | Secrets in tool results become placeholders before the model sees them. | Tool calls carry placeholders; they turn real only at the exits below. |
| Network | Outbound traffic passes the egress proxy and the connect guard. | The real value goes only to a bound host, approved one placeholder at a time. |
| Filesystem | A secret file opens as a placeholder copy. | Allowed readers get the bytes; files they write inherit the label. |
| Commands | A secret reader's output reaches the model as a placeholder. | A secret reader may connect only to hosts the secret is bound to. |
connect(2) guardLandlock files and TCP portsno_new_privs
Each layer turns on where the kernel supports it and is skipped with a notice where it does not. Anything that needs host root or changes the host for other users is out by design.
The oracle: a canary secret is absent from every model-facing surface, verbatim or encoded.
arbiter/The hub: placeholder table, policy, eventsinterceptors/Model, egress and reply proxies (TypeScript); kernel guards (Rust)launcher/The mandu command and all the wiringfs-sync/The two-view workspace on git worktreesdashboard/Approvals, rules and a full trace inspectortests/End to end, sandbox, drills, conformanceResearch
Prompt Flow Integrity (arXiv:2503.15547) isolates an LLM agent from untrusted data and guards against privilege escalation. DualView (arXiv:2607.03821) follows it with a defense that keeps two views of an agent's data and routes every action to one of them.
Mandu is the operating-system generalization of that work. It carries DualView's placeholder table, policy engine and two-view workspace forward, and attaches them at the boundaries of the OS instead of inside one agent.
Cite
@misc{dualview2026,
title = {DualView: Preventing Indirect Prompt
Injection in Personal AI Agents},
author = {Kim, Juhee and Choi, Woohyuk and
Kang, Taehyun and Kim, Youngmin and
Lee, Byoungyoung},
year = {2026},
eprint = {2607.03821},
archivePrefix = {arXiv},
primaryClass = {cs.CR}
}
@misc{pfi2025,
title = {Prompt Flow Integrity to Prevent
Privilege Escalation in LLM Agents},
author = {Kim, Juhee and Choi, Woohyuk and
Lee, Byoungyoung},
year = {2025},
eprint = {2503.15547},
archivePrefix = {arXiv},
primaryClass = {cs.CR}
}
Mandu Security
Mandu Security builds Mandu and keeps it open. We started from systems-security research on keeping AI agents away from data they should not hold, and we are turning that research into something you can install next to the agent you already use.
A mandu is a Korean dumpling: you see the wrapper, and the filling stays inside. That is the product. The agent handles the wrapper; your secrets stay with you.
hello@mandusecurity.com
Write to us
Open source · free
Now · beta
We are working with a small group of early teams whose agents run next to real credentials. If that is you, write to us.