All articles
Dev ToolsBy Petru Popa · 6 min read

AI Agent Sandboxing with NVIDIA OpenShell: The Sandbox Holds. The Gateway Can Start Wide Open.

v0.1.5 shipped on October 20. On October 21 two accepted security issues described a control plane that grants every caller admin when no auth is configured. The source agrees.

NVIDIA OpenShell reached the Hacker News front page on October 22, two days after its v0.1.5 release and one day after two accepted security issues described a control plane that can hand every caller admin rights. For anyone evaluating AI agent sandboxing this quarter, the issue tracker, commit history and v0.1.5 source tell a more useful story than the README.

What OpenShell does for AI agent sandboxing

OpenShell is an Apache-2.0 runtime that puts each AI agent in a sandbox and enforces a policy you write on everything the agent touches. Filesystem access goes through Landlock, system calls through seccomp, and every outbound connection through a policy proxy that injects credentials only for approved endpoints, so the agent never holds a real key. A gateway service creates sandboxes and holds policies; Docker, Podman, Kubernetes or a microVM do the isolation.

The part you would otherwise hand-roll badly is the network side. Wrapping Landlock and seccomp is a weekend. A per-connection policy check with credential injection, plus an SMT-backed prover that flags a proposed rule reaching a new host with credentials or a cloud metadata address, is not. The prover docs are candid that its guarantees cover only the policy features its model represents.

Maturity, read from activity rather than prose

SignalWhat the API returned
Commits on main since August 25656, between 41 and 108 a week, from 17 to 30 authors a week
ContributorsAt least 100; the top committer has 359 of 1,852 commits, the top three 711
Releases0.0.75 on July 2 to 0.0.116 on August 28, near-daily; 0.1.0 on September 25; 0.1.5 on October 20
Issues373 open, 1,333 closed; 98 closed since October 16 with a median of 8.1 days open; 131 labelled stale, 178 awaiting triage
Pull requests192 open, 75 merged since October 16

The support matrix promises a weekly stable tag, targeting Tuesdays, and 0.1.4 and 0.1.5 both landed on one.

Adoption outside NVIDIA is real but young. Homebrew counts 127 installs in the past 30 days. Anthropic's quickstarts repository ships a self-hosted Managed Agents sandbox demo on OpenShell, pinned to 0.1.2. OpenClaw, SAP, Cisco AI Defense and Google repositories reference it. A code search for the sandbox-create command outside the main repository returns 2,624 files, an upper bound over indexed public default branches.

The 0.1.0 line is where production starts, and the upgrade guide says so: no mixed 0.0.x and 0.1.0 peers, every sandbox recreated, provider profiles exported first. Patch releases still carry upgrade notes. The v0.1.5 notes rename the OCSF audit log files, reject Kubernetes pod annotations unless an operator allowlists them, and change the Go SDK's sandbox-create signature.

The thing the README does not say

The README calls OpenShell the safe, private runtime for fleets of agents. The sandbox boundary earns that. The gateway in front of it does not yet.

Issue 4814, filed on October 21 with the security label and an accepted state, describes the mechanism, and the v0.1.5 source confirms it. In multiplex.rs the request handler derives a principal from the authenticator chain when one exists. When no OIDC issuer, mTLS user auth, operator auth or gateway JWT is configured, no chain is built, and the final else branch injects a local-dev principal carrying the openshell-user and openshell-admin roles and the openshell:all scope. That branch runs whether or not allow_unauthenticated_users is set. The configuration docs show the flag as false and call setting it true an unsafe escape hatch; in this one case leaving it false changes nothing. The only signal is a startup warning in cli.rs that the gateway has no authentication mechanism.

Who reaches that branch? Not the default installs. Homebrew, Debian, RPM and snap gateways bind to 127.0.0.1:17670 and generate an mTLS bundle, and the Helm chart issues a gateway certificate and a client certificate at install time. The Docker Compose config sets the flag to true on purpose and binds to loopback. The path is a hand-written gateway.toml with a mistyped OIDC table or an unset client CA, bound beyond loopback. A fix, PR 4821, was opened on October 22 and makes the gateway refuse to start instead. It was still open when this was written.

The companion issue, 4813, is about the documented path rather than the accidental one. The Kubernetes access-control page's reverse-proxy recipe for Cloudflare Access or ngrok sets disableTls and allow_unauthenticated_users to true, and the issue states that the gateway never validates the Access JWT the CLI sends, so anyone who reaches the pod without passing the proxy is admin. Across public repositories outside the main one, 122 files set the flag to true and 58 set it to false; NVIDIA's own NemoClaw and NeMo examples are in the true set.

This is the pattern the Copilot sandbox post found two weeks ago from the other side: the isolation primitive is sound and the defaults around it are the exposure. It is also the gap we budget for between a proof of concept and production. The sandbox is the demo; identity on the control plane is the part nobody scoped, and it is where the design time goes on an agent platform.

Who should not use it yet

Teams that need a shared gateway without an identity provider in front of it. Podman users behind a corporate proxy: issue 4831 reports that on 0.1.4 and 0.1.5 the supervisor presents the wrong credential to the upstream proxy and egress fails, while the Docker driver on the same host works. Anyone whose containers restart under them: issue 4828 reports a Ready sandbox dropping to Error after a Docker restart, with nothing short of delete and recreate recovering it. Telemetry is on by default, with an environment variable to disable it.

The claim, and what would break it

On v0.1.5, a gateway with no authentication mechanism configured grants platform admin to every caller that reaches its port, whatever allow_unauthenticated_users says. The claim is wrong if a protected RPC on such a gateway returns Unauthenticated, and it stops applying once PR 4821 ships in a tagged release.

Before a gateway leaves loopback:

openshell-gateway config preflight --path ~/.config/openshell/gateway.toml
grep -nE 'oidc|mtls_auth|gateway_jwt|allow_unauthenticated_users|bind_address' ~/.config/openshell/gateway.toml
journalctl --user -u openshell-gateway | grep -i 'no authentication mechanism'

If the second command shows no OIDC issuer, no mTLS auth and no gateway JWT, the gateway is in the open branch. Add one, or keep bind_address on loopback until a release you have installed contains the fix.

Ready to start?

Turn this into a plan for your team.

One week, fixed fee: a working session with your team, a prioritized use-case backlog, and an ROI model for the opportunities worth chasing.

Book an AI Opportunity Sprint