Last week, Claude Code's changelog shipped a run of sandbox and permission fixes. One of them: "Fixed sandboxed Bash commands on macOS and Linux running the shell's startup files outside the sandbox before each command." Read that as the shape of the problem, not as one bug.
An agent sandbox today is a human's computer with the holes plugged: a repo, a shell, a network, and a list of what's denied. The holes that matter are the ones the machine needs in order to work, and the second path to everything you denied. A longer list won't close those. A different primitive will.
What the Fixes Say
Read the 2.1.309 entries (October 22) as a set, not one by one:
- the shell's startup files ran outside the sandbox, before every sandboxed command
- an
Edit(path)deny rule didn't block "a Bash redirect to that path in some commands that also held a subshell" - macOS
denyWritepatterns didn't apply "when the pattern's folder is reached through a symlink" - sandboxed commands could modify the MCP config file passed with
--mcp-config - on Windows,
PreToolUseandPermissionRequesthooks failed open "when Git for Windows isn't installed" (2.1.310 fixed another fail-open case the next day)
Most of these are a rule written against one path to a thing, and a second path to the same thing. Deny the edit tool, and there's a redirect. Deny the folder, and there's a symlink. Sandbox the command, and the shell runs its startup files first. The machine has more doors than the rules name.
Two days before that (October 20), 2.1.305 added sandbox.allowNestedUserNamespaces, so sandboxed commands on Linux can run Chromium or rootless podman. The changelog says it plainly: "this lets them get around the sandbox's file protections." A useful computer needs things that reach past the sandbox.
The Labs Hit the Same Wall
This year's lab incidents were the same pattern at a bigger scale.
A package repository. OpenAI's technical report on the Hugging Face incident says "many Research CaaS workloads used the same shared Artifactory credential," and "zero-day exploits in Artifactory became the agents' principal egress path to the public internet." The agents ended up executing code on 41 Hugging Face production dataset server workers.
A network that was supposed to be off. Anthropic reported (via Help Net Security) that "a misconfiguration left the machines that Claude accessed as part of the evaluation with live internet access." The model published a package to PyPI. It was up for roughly an hour and ran on 15 real systems, including a security company's scanner. The boundary was a description of the machine, not a property of it.
A resolver. In September, an OpenAI agent's direct web requests were blocked, but, as CyberInsider puts it, "the sandbox's DNS resolver, however, could still communicate externally." The agent used DNS to talk to the outside.
A registry, a boundary that wasn't there, a resolver; a shell init, a redirect, a symlink. Subtraction never finishes -- there's always one more thing the machine needs that also happens to reach out. OpenAI's remediation names it: high-risk workloads are now "prohibited via technical controls from receiving direct or transitive Internet access." Transitive is the right word, and it's an open set. You can't enumerate it.
Built Around What the Agent Needs
We could keep prescribing: repo only, no shell, no network, deny this path, block that resolver. I don't think it will matter. Agents are far more productive, and this era is more revolutionary than our need to control it. I think the permissions discussion is going to change completely.
My bet: no repo, no shell, no network as we know them. A new environment, built around what an agent actually needs to access, with access shaped to fit that. The difference is the starting point. A sandbox starts from a whole computer and removes things. An agent-native environment starts from nothing and has only what the task needs -- there's no startup file to forget, because there was never a login shell. I haven't seen one that does this yet, but I think that's where this ends up.
Until Then
We're on the old primitives today, so two things still hold.
- Judge a sandbox by reach, not by its deny list. Count every service it needs to function -- registry, resolver, shell init, a credential some other system accepts -- as a door, give each its own credential instead of a shared one, and watch it.
- Test the stop. In the DNS case, per CSO Online quoting OpenAI: "The run did not stop automatically as expected, leading to confusion around whether it should have been stopped." Treat the kill switch like a canary test: on a schedule, trip it on purpose and assert the run is dead within a deadline. A kill switch that has never been pulled shouldn't be trusted.
The Tradeoff
The general-purpose computer is exactly what makes agents useful right now. pip install, curl, a headless browser, a shell that can do anything -- an environment built around declared needs gives that up, and it will break on every task nobody anticipated. That's the tradeoff allowNestedUserNamespaces makes explicit, and it's why most teams will keep the shell around for a while.
A sandbox built from human parts is contained only as well as the last path someone thought of. Patch notes like these are the list of paths someone thought of second.