Every comparison of local agent sandboxes argues about the kernel, and the kernel has never been the thing that failed. All four of these now deny egress by default and make you name domains, so that column decides nothing. What still differs by a factor of everything is whether your GitHub token is reachable from inside the box — three of the four keep it out, by three different mechanisms, and the fourth is the one most people are already running, because it ships with Claude Code and it allows filesystem reads everywhere by default.
At a glance
All four run on a developer's own machine. They are not four implementations of one idea: one is an OS-level process wrapper, one is a policy layer that wraps a container or VM, and two are microVM runtimes.
| Project | Isolation | Egress default | Where the credential lives |
|---|---|---|---|
Anthropic srt (sandbox-runtime) |
OS-level, no container: Seatbelt on macOS, bubblewrap on Linux, a dedicated local user plus WFP on Windows (alpha) | Deny; an empty allowedDomains means no network at all |
On the real filesystem. Reads are allowed everywhere until you write a denyRead list |
| NVIDIA OpenShell | Policy layer over Docker, Podman or host virtualisation; Helm for Kubernetes, where the CNI must enforce NetworkPolicy |
Every outbound connection passes a policy check before it leaves | Outside. Agents never see real credentials; a provider attaches them only to approved endpoints |
Docker Sandboxes (sbx) |
A microVM per agent with its own kernel and its own Docker daemon | Deny through a host-side gateway; raw TCP, UDP and ICMP including DNS are blocked | Outside, by topology — only the workspace you mount crosses in, at the same absolute path |
| microsandbox | microVM via libkrun; macOS on Apple Silicon, Linux with KVM, Windows with WHP; no long-running daemon | Allowed hosts and ports, per sandbox | Outside. Secrets are scoped to a host and, in the project's words, never enter the VM |
The egress question has the same answer four times
Two years ago this was the whole comparison, because agent sandboxes shipped with a default route to the internet and a container was sold as a network control. That is over. srt removes the Linux network namespace outright and forces traffic through host-side proxies on Unix sockets, with an HTTP proxy for HTTP and HTTPS and a SOCKS5 proxy for other TCP; an empty allowlist means no network. sbx routes everything through a host gateway, blocks raw TCP, UDP and ICMP including DNS, and makes you run something like sbx policy allow network "*.npmjs.org,*.pypi.org,files.pythonhosted.org" to get a build working. OpenShell checks every outbound connection against a policy before it leaves and can change network rules at run time while filesystem and process rules stay locked at sandbox creation. microsandbox takes allowed hosts and ports per sandbox.
So if your evaluation criterion is "does it restrict the network", every option passes and you have learned nothing. The useful version of the question is narrower and it is about the matcher, not the policy: a domain allowlist is a string comparison performed on a name the agent chose. We will come back to that, because it is where both published failures of the most widely deployed option in this set were found.
Anthropic srt — the one you are probably already running
What it actually is
Apache-2.0, around 5.5k stars, and labelled a Beta Research Preview with Windows support explicitly alpha. It is a CLI and a library — srt "curl example.com" comes back with Connection blocked by network allowlist — and it restricts arbitrary processes, not just agents: MCP servers and bash commands go through the same wrapper. Configuration is one file, ~/.srt-settings.json. The interesting engineering is the per-platform backend: generated Seatbelt profiles under sandbox-exec on macOS, bubblewrap with the network namespace removed on Linux, and on Windows a dedicated srt-sandbox local user with a WFP egress filter keyed on that account's SID — so a process that unsets the proxy environment variables is still blocked, because the environment variable was never the boundary.
It shares your kernel, which the project does not hide and which matters less than it sounds for this threat model: the code the agent runs is code you asked it to write, not malware. What it buys you for that trade is the lowest overhead and the only option here that needs no virtualisation at all.
The read default, and the two bypasses
The filesystem rules have deliberately opposite precedence, and this is the line to read twice. Writes are denied everywhere by default and you open them with allowWrite. Reads are allowed everywhere by default and you close them with denyRead. The README's own example denies ~/.ssh — which tells you that until you write that list, ~/.aws, ~/.kube/config, your gh token and your browser cookie jar are all readable by the sandboxed agent. There is a floor: a set of mandatory deny paths is always write-blocked even inside an allowed directory, including .bashrc, .gitconfig, .mcp.json, .vscode/ and .git/hooks/. Note what that floor protects — it stops the agent editing its own next startup, not reading your secrets.
Then the failure history, which is the most useful public data in this whole comparison. Two bypasses of the network sandbox have been reported, and both were in the hostname matcher. CVE-2025-66479: before v0.0.16, an unconfigured allowlist was not enforced at all — the empty list read as allow-everything rather than allow-nothing, fixed in a release on 26 November 2025. Then a null-byte injection reported by Aonan Guan: a hostname of the form attacker-host.com\x00.google.com passed the suffix check and was then truncated by the OS, so the connection went to the attacker's host. Public reporting puts the affected range from the sandbox's general availability in Claude Code 2.0.24 through the 2.1.8x series in early 2026, disagrees on the exact fixed version, and records that no CVE was published for it; the patch added an isValidHost() wrapper rejecting null bytes, percent signs and CRLF before the matcher runs.
Neither bypass was an escape from Seatbelt or bubblewrap. Both were string handling in front of the proxy — and in both cases what the attacker got was decided entirely by what the sandbox could read, which is the default this project leaves open.
NVIDIA OpenShell — the only one that treats the credential as the product
A policy layer, not a runtime
Apache-2.0, around 15.8k stars, on a 0.1.x line, with Windows support through WSL 2 marked experimental. It does not implement isolation; it requires Docker, Podman or host virtualisation underneath and governs what runs inside. Policy covers filesystem paths, outbound network and process execution, declared per agent. The split worth knowing: filesystem and process policy is locked when the sandbox is created, while network policy can change while the agent is running — which is the right way round for a long session, and the opposite of what you would guess.
Two features have no analogue in the other three. An advisor and a prover sit in front of policy changes, with the prover using formal verification to flag a change that grants risky new access — reaching a new host with credentials attached, calling a new API method — and holding it for human review. And the enforcement granularity is per request rather than per host: the documented example is allowing reads against the GitHub API while blocking POSTs, which a domain allowlist cannot express.
Providers, and the weight
The providers feature is the architectural answer to this article's question. Agents never hold real credentials; OpenShell attaches them to requests bound for approved endpoints and nothing else. A prompt injection inside that sandbox cannot exfiltrate a token because there is no token to read, and the blast radius of a confused agent is the set of endpoints the policy approves, which is a thing you wrote down. That is a categorically different posture from "the token is on disk and I denied reads to one directory".
The cost is weight and novelty. It is more moving parts than a wrapper, Kubernetes deployment requires a CNI that enforces NetworkPolicy, and the broader platform it was announced with — Open Agent Safety Platform, 28 September 2026 — pairs it with Sentry, a watchdog that runs on BlueField-4 DPUs. Sentry is a datacentre component and is not available on a laptop, so read the hardware half of the announcement as orthogonal to the thing you can install today.
Docker Sandboxes — the strongest boundary and the shortest config
A microVM per agent
Each sandbox is a microVM with its own kernel and its own Docker daemon, which means an agent that decides to docker run something is not touching your daemon. sbx is a separate binary and does not need Docker Desktop running. Claude Code, Codex, Gemini CLI, Copilot CLI, OpenCode, Kiro and Docker's own agent are supported out of the box. Egress is deny-by-default through a host-side gateway, sbx policy log shows you what was blocked — a detail the others under-serve and the single most useful affordance for tuning an allowlist — and rules scope per sandbox by default, with a global flag when you want the fleet.
The credential story is the best of the four for the least effort, and it is not a feature so much as a consequence: only the workspace you mount crosses into the VM, at the same absolute path. Your home directory is simply absent. You get that by doing nothing, which is the opposite of srt, where you get exposure by doing nothing.
The sign-in and the licence
Two things to price in. The CLI and local sandbox compute are free, including for commercial use, with organisation governance on a paid subscription — but this is a product, not an open-source project, and it is the only option here without an Apache-2.0 repository you can read. And it requires sbx login with a Docker account before it will run a purely local sandbox, with the first login also setting a default network policy. If you are evaluating these because you need an auditable boundary for regulated work, the one you cannot read the source of is a different kind of bet from the other three, however good the isolation is.
microsandbox — the library-shaped one
microVMs without a server
Apache-2.0, around 8.6k stars, explicitly beta and saying so in the README. Isolation is a microVM via libkrun on macOS with Apple Silicon, Linux with KVM and Windows with WHP. The distinguishing design choice is that there is no long-running daemon: the SDK's create() boots a microVM as a child process, and sandboxes can be detached when a session needs to outlive the caller. There is a CLI (msb), SDKs for TypeScript, Rust, Python, Go and Ruby, and an MCP server plus Agent Skills so an agent can drive it.
That shape makes it the natural pick when the sandbox is something your own code creates per task rather than something a developer wraps a shell in — CI jobs, self-hosted runners, a product feature that executes model-written code. It is the one of the four you would build a platform on.
Host-scoped secrets
Network policy is allowed hosts and allowed ports per sandbox, expressed in the SDK or in YAML. The feature worth stealing regardless of what you adopt is the secret model: keys are bound to a specific host and described as never entering the VM. That is OpenShell's providers idea in a smaller package, and it is the single design decision that makes a leaked prompt or a poisoned dependency unable to walk off with anything, because the thing it would steal was never in the address space.
The caveats are the honest beta ones — expect breaking changes — and that its egress posture is documented as allow-lists rather than as an explicit deny-by-default guarantee, so verify the default in the version you install rather than assuming it matches sbx.
The axis that actually separates them
Put the four designs side by side on one question — can a process inside the sandbox read a usable credential — and they split three to one, with the three arriving by different routes. Docker Sandboxes gets there by topology: the home directory is not mounted, so there is nothing to deny. OpenShell gets there by construction: the credential is held by a provider outside the box and attached at the proxy to requests the policy already approved. microsandbox gets there per destination: the secret is bound to a host and never crosses into the VM. srt gets there only if you wrote the list.
This is the axis to pick on because it is the one that bounds the damage when everything else works as designed. An agent on a laptop was handed your credentials on purpose; it did not need to escape anything to use them, and the published incidents in this space are consistently about authorised actions taken for the wrong reason rather than about escapes. A microVM with your token inside it is a strong boundary around an action you already authorised.
The allowlist is the weak layer, not the kernel
Every one of these four enforces network policy by matching a name. That is unavoidable — TLS means the destination is a hostname, not an IP you can reason about — and it means the control's correctness lives in a parser rather than in the kernel. The two srt bypasses are the available evidence, and they are both parser bugs of the most ordinary kind: a boundary case read the wrong way, and a character the matcher and the resolver disagreed about. There is no reason to think the other three are structurally better here; there is only less public scrutiny, and srt got its scrutiny by being the one bundled with the most-used coding agent.
Two practical consequences. First, prefer the option that can express a narrower rule than a hostname, because the narrower the rule the less the matcher has to carry — OpenShell's method-and-path granularity and microsandbox's host-plus-port are both doing real work here. Second, log the denials, whichever you pick. sbx policy log is the model: a record of what was blocked is how you find out that the matcher and the agent disagree, and it is the only one of these telemetry surfaces you can read without instrumenting anything.
When to pick which
| Situation | Pick | Because |
|---|---|---|
| You run Claude Code and want a boundary today | srt, with a denyRead list written first | It is already installed; the list is the whole value and it is not on by default |
| A fleet of laptops, policy decided centrally | NVIDIA OpenShell | Providers keep credentials off the machine, and the prover makes a policy change reviewable rather than ambient |
| One developer, several agents in parallel, minimum config | Docker Sandboxes | Own kernel per agent, workspace-only mount, and a policy log you can read |
| Your product executes model-written code | microsandbox | A library with no daemon, SDKs in five languages, and host-scoped secrets |
| Regulated work needing an auditable boundary | OpenShell or microsandbox | Apache-2.0 source you can read; sbx's isolation is strong but closed, and it requires a vendor sign-in |
| Hostile code, not just unreviewed code | A microVM, and reconsider the task | Shared-kernel sandboxes are not a boundary against an adversary who wants out |
FAQ
Is a microVM actually better than Seatbelt or bubblewrap?
Against hostile code, yes, clearly — a separate kernel is a separate kernel. For a coding agent running code you asked it to write, the difference is mostly theoretical, and it costs you boot time and the ability to run with no virtualisation. Buy it for the topology side effect (the home directory is not mounted) rather than for the kernel.
We already set a domain allowlist. Are we done?
You have handled the cost and abuse case and part of the unsanctioned-action case. You have not handled exfiltration, because the allowlist contains hosts that accept data, and you have not handled a matcher bug. Pair the allowlist with a credential the agent cannot read and the remaining exposure is small.
What is the single highest-value change for an existing deployment?
Write the denyRead list. Cloud and cluster config, SSH keys, registry tokens, the git credential helper, browser profiles. It is ten lines of JSON, it is the one line of configuration that bounds the damage, and in the default configuration it is absent.
Does OpenShell need NVIDIA hardware?
OpenShell itself does not — Linux, macOS on Apple Silicon or Windows with WSL 2, plus Docker, Podman or host virtualisation. Sentry, the hardware watchdog announced alongside it, runs on BlueField-4 DPUs and is a datacentre component. Treat them as two products.
Can I use these for untrusted third-party MCP servers?
srt is explicitly built for that case and will wrap an MCP server like any other process. But an MCP server is given tools and credentials on purpose, so the same conclusion applies: the sandbox bounds what it can reach, and only a brokered credential bounds what it can do with what it was given.
Why is there no benchmark in this comparison?
Because the numbers that exist measure boot time and memory, and no boot-time figure distinguishes these for the decision being made. The axis that matters is a configuration default, which is a thing you read rather than a thing you measure.
Further reading
On this wiki:
- Agents on developer workstations — the deployment these four exist for, and why the user being root changes the control set.
- Credential delivery to the sandbox — the four channels that put a secret inside the box in the first place.
- Sandbox and isolation patterns — the layers underneath all four of these.
- Egress control for agents — why one allowlist cannot serve exfiltration, unsanctioned action and cost at once.
- Agent artifacts on the endpoint — what is in the home directory you are deciding whether to expose.
- Credential lifetime — why the token in that directory is worth weeks, not an hour.
Project sources:
- anthropics/sandbox-runtime — README, platform backends, settings schema and mandatory deny paths
- NVIDIA/OpenShell — policy model, providers, advisor and prover
- Docker Sandboxes documentation — microVM model, policy commands and pricing
- microsandbox/microsandbox — libkrun isolation, SDKs, host-scoped secrets
- CVE-2025-66479 — network sandbox not enforced when no allowed domains were configured