AI Blog

Anthropic srt vs NVIDIA OpenShell vs Docker Sandboxes vs microsandbox: pick on where the token lives

All four now deny egress by default, so that column decides nothing. Three of the four keep your credentials outside the sandbox, by three different mechanisms; the fourth is the one bundled with Claude Code, and it allows filesystem reads everywhere until you write a denyRead list. Both published bypasses were in the hostname matcher, not the kernel.

By Agentic AI Wiki 18 min read

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.

ProjectIsolationEgress defaultWhere 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
Four local agent sandboxes across four axes A matrix with Anthropic srt, NVIDIA OpenShell, Docker Sandboxes and microsandbox as rows, and own kernel, default-deny egress, credential kept outside the sandbox, and open-source licence as columns. Every row is strong on egress; the rows differ most on whether the credential is reachable from inside. Where the four actually differ Own kernel Egress default Credential outside Licence Anthropic srt No (shared) Default-deny On disk, read-open Apache-2.0 NVIDIA OpenShell Container or VM Per-connection Providers inject Apache-2.0 Docker Sandboxes microVM Gateway allowlist Workspace only Product, sign-in microsandbox microVM (libkrun) Host and port lists Never enters VM Apache-2.0 Strong Partial Weak or not offered The egress column is solid across every row, which is why it no longer decides anything.
Where they lean hardest. One column is uniform, which is exactly why it has stopped being the decision.

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

Where the credential sits, in each of the four designs Four panels. Under Anthropic srt the credential stays on the real filesystem and the sandbox relies on a deny-read list. Under Docker Sandboxes only the mounted workspace crosses into the microVM, so the home directory is absent. Under NVIDIA OpenShell the credential is held by a provider outside the sandbox and attached to approved requests at the proxy. Under microsandbox the secret is scoped to a host and never enters the virtual machine. Four answers to one question: can the agent read the token? Anthropic srt Sandboxed agent shared kernel ~/.aws, ~/.ssh on the real disk Reads are allowed everywhere by default. The boundary is a denyRead list you have to write. Verdict: inside the box unless you say otherwise. Docker Sandboxes Agent in microVM its own kernel Home directory not mounted Only the workspace you mount crosses in, at the same absolute path. Everything else is absent. Verdict: outside the box, by topology. NVIDIA OpenShell Agent holds no secret Policy proxy Provider holds it Credentials are attached only to requests bound for approved endpoints, outside the sandbox. Verdict: outside the box, by construction. microsandbox Agent in microVM libkrun Secret scoped to one host The project’s own words: keys that never enter the VM, usable only against the named host. Verdict: outside the box, per destination. Three of the four keep the secret out. The fourth is the one most people are already running.
Three mechanisms, one outcome: the secret is not in the address space the agent runs in.

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

Which layer the published failures were in Three columns for the isolation layer, the hostname matcher and the credential reachability. Both publicly reported bypasses of the Anthropic sandbox runtime were in the hostname matcher, not in Seatbelt or bubblewrap, and the damage in each case was bounded by what the sandbox could read. Published bypasses, by the layer they were in Isolation layer Seatbelt, bubblewrap, network-namespace removal, WFP filters Reported bypasses: 0 Hostname matcher Empty allowlist read as allow-all; a null byte that passed the suffix check Reported bypasses: 2 What was reachable Credentials and source on the real filesystem, which set the loss either time Decides the damage: both The strong layer was never the one that failed, and the weak one is a string comparison.
Where the record says the failures were. The comparison everyone runs is about the left column.

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

SituationPickBecause
You run Claude Code and want a boundary todaysrt, with a denyRead list written firstIt is already installed; the list is the whole value and it is not on by default
A fleet of laptops, policy decided centrallyNVIDIA OpenShellProviders keep credentials off the machine, and the prover makes a policy change reviewable rather than ambient
One developer, several agents in parallel, minimum configDocker SandboxesOwn kernel per agent, workspace-only mount, and a policy log you can read
Your product executes model-written codemicrosandboxA library with no daemon, SDKs in five languages, and host-scoped secrets
Regulated work needing an auditable boundaryOpenShell or microsandboxApache-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 codeA microVM, and reconsider the taskShared-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:

Project sources: