Open source · by Mandu Security

Your agent sees the dumpling, never the filling.

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.

LinuxNo rootNo changes to your agentNo account, no telemetry
Works with Claude CodeCodexOpenCodeOpenClawGoose
~/proj/.env
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

To use your secret, the agent reads it.

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

> how much did we charge on Stripe last week? ● Read(.env) STRIPE_KEY=sk_live_•••••••••••• ● Bash(curl api.stripe.com/v1/charges \ -u sk_live_••••••••••••:) ● Last week: $12,480 across 37 payments.

API keys, tokens, passwords, SSH keys, cloud credentials. Once read, the key travels to the vendor in every later request.

Personal documents

> summarize my blood test, draft a note ● Read(~/Documents/health/lab-results.md) Patient: J. Doe · born 1988-04-12 HbA1c 7.9 % (above range) Insurer: member no. 4471-02 ● Here is a summary and a draft note…

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

> draft the all-hands update from the memo ● Read(~/work/board-memo-q4.md) # Q4 board memo · CONFIDENTIAL Project Falcon: acquisition at $42M Runway: 14 months at current burn ● Here is a draft of the update…

Contracts, plans, financials, customer lists. Company policy often says no outside model, or only the one the company runs.

Three ways a secret leaves your machine

1In every model requestThe secret sits in the agent's context and goes out with each call.the model vendor
2In a command the agent runscurl with the key, to whatever host the command names.any server: a gist, a webhook, a tunnel
3On someone else's ordersA hidden instruction in an issue, a README or an email tells the agent where to send it.someone else

Mandu stops the secret from leaving, whoever asked for it.

Why Mandu

Today you pick a useful agent or a safe secret.

Other tools keep the secret by taking work away from the AI. Mandu does its best to keep both.

ApproachHow it worksThe agent does the taskThe secret stays private
Trust the agentClaude Code, Codex as installedRun it as is. It reads .env, your lab results, the board memo, whatever helps.YesNoThe vendor gets it, and any host a command names.
Lock it outNVIDIA OpenShell, nono, Microsoft PurviewBlock 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 maskCommands 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.
ManduPlaceholders for the AI; real values only at the right exit.YesYes

It keeps your secrets for you

  • Finds your secret keys on its own: .env, ~/.aws, ~/.ssh, secret-named variables. You name your documents.
  • The AI gets a placeholder, never the secret.
  • A secret leaves only for a host you bound it to, or with your OK.
  • When in doubt, it blocks. It fails closed.

It keeps your AI useful

  • The key still works: psql, ssh and bound hosts get the real value.
  • Files keep their shape, so scripts and variable names still work.
  • A document is read by the model you allow instead of being blocked.
  • Measured: 36 of 36 tasks done. The shell mask managed 19.

How it works

A placeholder carries everything but the secret.

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.

$MDU:Prefix, easy to find in any text
nomodel_Level: no model may read the value
ReadThe tool that produced it
[9bbd]Id, meaningless outside Mandu
.STRIPE_KEYField, so the agent knows which secret it holds

A secret key turns real only at the right exit

curl api.stripe.com/v1/charges \
  -u $MDU:nomodel_Read[9bbd].STRIPE_KEY:
✓A host you bound it to. The egress proxy puts the real key in the request to api.stripe.com, and only there.
✓A program you allow. psql reads ~/.pgpass; only the ssh that git started reads your key.
✓You. The agent's replies show you real values; its context keeps the placeholders.
?Anywhere else, it waits for you on the dashboard. Allow onceAlways allowBlock

You choose which models read each document

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.

See it on your own machine

A recorded terminal session of mandu demo: the agent reads a .env file and sees placeholders, while the user sees the real values.
mandu demo plays this on your computer, offline, with no API key.

Evidence

Measured on six everyday secret-key tasks.

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.

Secret kept from the model

Mandu36/36
Claude Code mask32/36

Task done

Mandu36/36
Claude Code mask19/36

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

Put mandu in front of your agent. That is the whole change.

Your agents, unchanged

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.

Nothing to migrate

Your secrets stay where they are, in the format they have. There is no vault to move them into.

No root

Everything runs as your user. Kernel hardening (seccomp, Landlock, a sandbox for commands) turns on wherever your kernel allows it without root.

No account, no telemetry

There is no Mandu server. All state lives in ~/.mandu, readable only by you.

Fails closed

If a part cannot decide, the secret stays a placeholder or the action is blocked. It never falls back to the real value.

Your own model, too

Declare an Ollama or vLLM as yours, and it may read what outside models may not. It can be the main model too.

Limits

What Mandu does not do.

Knowing exactly what is covered is part of the product.

It does not stop prompt injection

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.

It protects the secrets it knows

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 first

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 injection defense 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

Four commands.

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

Built in the open, so you can check every promise.

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.

One rule, at every boundary

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.

BoundaryOn the way inOn the way out
Model contextSecrets in tool results become placeholders before the model sees them.Tool calls carry placeholders; they turn real only at the exits below.
NetworkOutbound traffic passes the egress proxy and the connect guard.The real value goes only to a bound host, approved one placeholder at a time.
FilesystemA secret file opens as a placeholder copy.Allowed readers get the bytes; files they write inherit the label.
CommandsA secret reader's output reaches the model as a placeholder.A secret reader may connect only to hosts the secret is bound to.

Kernel hardening without root, on by default

Bubblewrap command boxPID, IPC, UTS, cgroup namespacesAll capabilities droppedseccomp deny-filterseccomp 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.

Every promise names the test that breaks

200+test suites in one manifest; a test file no entry claims fails the build
47replay drills: the real agent CLIs against a scripted model
5suite kinds on every push, in a throwaway KVM guest
1script runs exactly what CI runs, on your laptop

The oracle: a canary secret is absent from every model-facing surface, verbatim or encoded.

Find your way around

arbiter/The hub: placeholder table, policy, events
interceptors/Model, egress and reply proxies (TypeScript); kernel guards (Rust)
launcher/The mandu command and all the wiring
fs-sync/The two-view workspace on git worktrees
dashboard/Approvals, rules and a full trace inspector
tests/End to end, sandbox, drills, conformance

Research

Built on two papers

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.

github.com/compsec-snu/dualview

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

The company behind Mandu.

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
$MDU:…

Open source · free

Mandu

  • Every guard: model context, network, files, commands
  • The dashboard, approvals and rules
  • Kernel hardening without root
  • AGPL-3.0-or-later, on your machines, no account

Now · beta

Design partners

We are working with a small group of early teams whose agents run next to real credentials. If that is you, write to us.