Skip to content
Guard AI agents

AI Jail

Run an AI coding agent inside filesystem and namespace walls with the guardrail still screening it, so a hijacked agent cannot read what was never mounted.

AI Jail

For: anyone about to let an AI agent run commands on a machine that has real credentials on it.

The guardrail screens what an agent runs. AI Jail limits what it can reach. They are different jobs and they are better together:

Jail = walls. Limit what the agent can touch. Guard = brain. Screen every command it runs. Together: prevent and detect.

One command:

innerwarden contain -- claude

Linux uses bubblewrap, macOS uses sandbox-exec. Windows containment is not supported today, and the product says so rather than pretending otherwise.


Why it helps, concretely

Screening alone has an honest limit: it decides about commands it is shown. An agent that is hijacked by a prompt injection, or that finds a path around the hook, is still a process with your user's permissions and your user's files.

Walls do not depend on the agent cooperating. A file that was never mounted cannot be read, whatever the agent decides to try. That is the whole argument for running the two layers at once, and it is why the hook stays armed inside the jail rather than being replaced by it.

The one thing the jail protects hardest is InnerWarden's own configuration. ~/.config/innerwarden is never bound into the jail and is always shadowed, so the 0600 LLM key cannot be read by the agent you are containing. The hook does not need that config to keep working: blocking uses the rules compiled into the binary. In-jail enrichment from a language model is simply switched off, and a deny still denies.

When to use it

Reach for it when the honest answer to "what could this agent read if it went wrong?" is uncomfortable:

  • An agent running unattended, or on a long autonomous task.
  • A machine that also holds SSH keys, cloud credentials or customer data.
  • Any agent you did not write, or a new version of one you did.
  • Reproducing a report from someone else's repository.

You do not need it for a throwaway container that holds nothing. Say that plainly rather than jailing by reflex.

How to use it

# Records what it screens, never blocks. This is the default, on purpose.
innerwarden contain -- claude

# Only the project directory is writable.
innerwarden contain --project ~/work/api -- claude

# Hide one more path from the agent.
innerwarden contain --deny-read '~/notes/**' -- claude

# Print the jail that would be built, and run nothing.
innerwarden contain --dry-run -- claude

# Opt in to blocking.
innerwarden contain --enforce -- claude

--monitor is the default and it records rather than blocks, so a first run cannot break your workflow. Enforcement is a deliberate second step, the same discipline the kernel controls use.

What is walled off, and what is not

Never exposed to the jailed agent:

  • ~/.config/innerwarden, shadowed, so the LLM key stays unreadable.
  • .ssh, .aws, .gnupg, and on macOS the Mail, Messages and Safari stores.
  • Anything you add with --deny-read.

Still visible, and you should know it: the jail inherits the host environment, like a normal shell. Credentials you have already exported, OPENAI_API_KEY, AWS_* and their neighbours, are visible inside. The agent needs its own key to run at all, so a blanket scrub would break the thing you are trying to contain. An opt-in environment allowlist is the next version of this. Until then, if a secret is in your shell's environment, treat it as inside the jail.

Walls are not a kernel-enforced execution guarantee either. That is the paid Execution Gate's job, and the dashboard reports the two separately rather than blurring them.

Seeing it on the dashboard

A contained run stamps its own session on everything it screens, so the dashboard can tell the difference between an agent inside walls and one running loose. The AI Jail card reads that and reports one of three things:

What the card saysWhat it means
AvailableA contained run is recorded on this host
Not configuredThe host looked, and no agent has been run inside a jail
UnknownThe local decision record could not be read; nothing is inferred from the gap

It is evidence rather than proof, and the card publishes that limitation instead of burying it: an operator who overrides the session name is jailed and will not be counted here.