A sandbox is only worth what can be proved to run inside it: the boundary that matters is not the container’s, it is the set of tools that actually execute within it, and in every deployment studied that set was smaller than the team assumed.

The mechanism

Start with the failure, because it is the one thing on this page most teams get wrong. MATRA threat-modelled an agent runtime under two configurations: default, and Docker with network=none. The customer-data exfiltration scenario scored Very High under both, so sandboxing changed nothing.

The reason is structural. Only the exec-based tools ran inside the container. The messaging tool and the browser ran on the gateway host, so their exfiltration paths were never inside the boundary. The rendered-markup channel needs no network call from the agent at all, because the client fetches the image URL. What did move that scenario down to Moderate was an outbound email allowlist plus output sanitisation that strips URLs carrying encoded data. Both operate at the layer where the harm actually travels. (That is an author-scored risk matrix on one deployment, so read it as a well-argued finding, not a measurement.)

So the test is: enumerate which tools execute inside the container before crediting the sandbox with anything. Most architecture diagrams draw one box around “the agent.” The runtime does not.

Code execution is the case sandboxing genuinely answers. Agents generate code that exists only at runtime, out of reach of static review and signature-based controls. OWASP treats an agent running LLM-generated code as arbitrary code execution by definition, not as a risk to assess but as a capability classification. The worked case is an agent talked into generating code that queries a backend database and returns the results, succeeding because the execution environment was never isolated from the rest of the estate.

Two facts about defaults are worth holding onto.

MCP servers run outside any sandbox their clients provide. In the common desktop clients they run with the user’s own privileges: filesystem, environment variables containing credentials, network, everything the user can reach. The protocol’s own security guidance tells clients they should warn that servers run with client privileges and should execute them sandboxed: SHOULDs, not MUSTs, and the fact that this appears as a recommendation is itself the evidence. Claude Code is now a counterexample, shipping OS-level isolation for Bash commands and their child processes with per-domain network approval. Desktop clients generally are not, and this is moving fast enough that any claim here needs a date on it.

Sandboxing is documented least where citizen developers build. Across thirty indexed agent products, nine document sandboxing or VM isolation, and among enterprise platforms most describe guardrail options with no containment at all. Those are documentation findings rather than audits, so treat nine of thirty as a floor. Containment has to come from the firm’s own architecture, because the product probably lacks it.

One more caution, from a study testing MCP clients against a tool description carrying a curl … | bash payload. Two of seven executed it, but the five that refused mostly did so at the model layer rather than at the sandbox layer, and the two that ran it had crude domain filtering that rejected an obviously hostile hostname and passed a plausible one. The paper’s conclusion is the sharper argument here than the raw score: the ecosystem relies on model behaviour where it should rely on client-side sandboxing and network controls.

What to do

The cheap version. Run agent code execution and agent browsing in disposable containers with no shared filesystem, no inherited host environment variables, and no host credentials. Read-only root filesystem, write access only to a designated working directory, CPU/memory/disk quotas, and a network allowlist rather than a blocklist. Destroy or reset the sandbox after each tool execution, since a long-lived sandbox accumulates exactly the persistence it was built to prevent.

Keep credentials out of the sandbox entirely, provisioned per action rather than resident on the agent’s machine. That is the difference between a sandbox and a sandbox that survives contact with an attacker; see secrets management.

The thorough version climbs the isolation ladder deliberately. OS containers (Docker, Podman) are the reasonable default. Micro-VMs (Firecracker, QEMU/KVM) buy a separate kernel. WebAssembly buys memory safety for constrained workloads; sandboxed interpreters and managed cloud sandboxes fill the middle. Kernel-level isolation via gVisor, a userspace kernel that intercepts syscalls, is a real boundary. One name that circulates in the same lists belongs at the weak end of the ladder: Firejail is a SUID-root binary, so the sandbox itself is privileged attack surface, and it carries a history of local privilege-escalation CVEs.

Then harden per agent rather than per application: each agent in its own namespace, syscall filtering with seccomp or AppArmor/SELinux, read-only mounts, ephemeral tmpfs storage, and memory cleared at session end.

Isolate the environment, not just the process. Isolation covers data, UI surface and network as much as compute, which matters for the browser-driving agent a non-engineer builds first, where the real boundary is which UI elements the agent may touch. Test on non-production data: a sandbox sharing the production database is a compute boundary with no data boundary.

Watch for self-widening configurations. Anthropic’s own sandbox documentation warns that with filesystem isolation disabled and commands auto-allowed, a sandboxed command can write shell startup files or the client’s settings and broaden its own access on the next run. A sandbox whose configuration is writable from inside it is a sandbox with a hinge.

How you’d know it’s working

Run the enumeration. List every tool the agent can invoke and mark which execute inside the boundary. If messaging, browsing or rendering sit outside, the containment story has a hole the size of MATRA’s finding.

Test escape-oriented rather than function-oriented. From inside the sandbox, what is reachable on the host, on the network, and in the credential store? The answer should be short enough to write down in full.

Check that the sandbox is actually ephemeral. Look for state surviving between executions: cached files, session data, tokens. If anything persists, so does an attacker.

What this doesn’t solve

Sandboxing contains execution, not data leaving through channels the agent legitimately needs. The design-patterns literature says it plainly: sandbox the code execution and information can still leak from the database, because the database has to remain reachable for the tool to work. The same paper notes that reconnaissance of the sandbox itself and extraction through the analysis output path both survive. See egress control and data access governance.

It does nothing about judgment. A perfectly isolated agent still produces confidently wrong output a human acts on (unreliable output).

This workload was never what current sandboxes were designed for, and the most credible admission of that comes from a model developer with every reason to say otherwise: existing sandboxing systems may not be well suited to bounding highly capable agents. That was written in December 2023, before MCP and before most of the isolation tooling now in use, so treat it as an honesty boundary rather than a current assessment, though nobody has retracted it either.

Sandboxing underwrites a policy layer rather than making it trustworthy; it is what makes the policy layer’s assumptions hold. An agent with code execution can spawn processes and make raw calls a policy engine never observes. That makes this infrastructure-level work rather than configuration. Enforced compliance is an architectural assumption, not a proven invariant.

Finally, isolation costs capability. Firms running local models with no external connectivity for confidential work accept measurably weaker models as the price. That trade is legitimate and should be made explicitly, per workload, rather than discovered after the pilot disappoints.

See also