You turned on Claude Code's Bash sandbox so the agent could run commands without asking you each time. The sandbox was supposed to keep their writes inside the project folder and their network traffic behind a proxy. Claude Code 2.1.309, published on GitHub on October 22 at 22:18 UTC, lists more than a dozen places where that boundary, or the permission checks around it, did less than it should have.
The first item on the list is the one to read twice:
Fixed sandboxed Bash commands on macOS and Linux running the shell's startup files outside the sandbox before each command
This post goes through the sandbox and permission fixes in that release, what each one means in practice, and what to check on your machine. It is based on the release notes and Anthropic's docs as of October 23, 2026. When we wrote it, the repository's security advisories page had no entry for these fixes, so the release notes are all there is. We make Sessionboxer, which runs the whole agent in a container instead, and that part is near the end.
The startup files
Claude Code's tools reference explains how the Bash tool gets your aliases: "At session start, Claude Code sources ~/.zshrc, ~/.bashrc, or ~/.profile depending on your shell, captures the resulting aliases, functions, and shell options, and applies them to every Bash command."
Until 2.1.309, on macOS and Linux, the startup files ran outside the sandbox before each sandboxed command. So the command itself was confined, but whatever your startup files did ran with your normal access, every time the agent ran something.
For many people it is a prompt theme, a few aliases and a version manager. Others load a project's environment, call tools that read the current directory, or run scripts from other places. The release note does not describe an attack, and we will not invent one. What the note does say is that this code ran unsandboxed on every command, so it is worth knowing what that code was.
The other sandbox fixes
The other sandbox and permission items from the release, quoted or close to it:
| Fix in 2.1.309 | Who it affects |
|---|---|
macOS denyWrite glob patterns did not apply at a path's real location when the pattern's folder was reached through a symlink |
macOS users with denyWrite rules on symlinked folders |
Sandboxed commands and auto-accepted edits could modify the MCP config file passed with --mcp-config |
Anyone who starts Claude Code with --mcp-config |
| A disabled MCP server could be reconnected by a later permission prompt in print and SDK sessions | Scripts using claude -p or the Agent SDK |
| On Linux, sandbox write denies lifted when a background command outlived the session | Linux users whose agent starts long-running servers or watchers |
| Profile store write protection did not apply when the config directory was reached through a symlink | People with a symlinked Claude config directory |
An Edit(path) deny rule did not block a Bash redirect to that path in some commands that also held a subshell |
Anyone who relies on Edit deny rules for Bash too |
Some compound commands that cd before running git, with the cd wrapped or prefixed, did not prompt |
Anyone who approves git commands case by case |
PowerShell hooks did not block on exit code 2, and on Windows PreToolUse and PermissionRequest hooks with "shell": "powershell" failed open without Git for Windows |
Windows users with policy hooks |
The --mcp-config fix needs some context. The sandboxing docs say that local MCP servers run outside the sandbox "with your full access". An MCP config names the command that starts each server. If a sandboxed command can rewrite that file, it can choose a program that later runs outside the sandbox. By default the sandbox can write to the working directory, so a config file kept inside the project was within its reach.
There is also one behaviour change about fallbacks. Commands listed in excludedCommands now "ask before writing to its write-list paths while the sandbox is enabled but cannot run; the unsandboxed fallback is refused there."
What to do today
Update first, then check the parts the update does not fix for you.
- Run
claude --version. You want 2.1.309 or later. The setup docs say native installations "automatically update in the background", and Homebrew and WinGet installations do not. If you use Homebrew'sclaude-codecask, note that it tracks the stable channel, which the same page says is "typically about a week behind". Useclaude-code@latestor the native installer if you want this release now. - Update every copy, including the ones in dev containers, CI images and servers. A pinned version in a Dockerfile stays pinned.
- Read your startup files:
~/.zshrc,~/.bashrc,~/.profileand anything they source. Until today they ran unsandboxed on every command. Move anything you would not want the agent to trigger out of them. - Keep the file you pass to
--mcp-configoutside the project directory and outside any path inallowWrite. Check that it still says what you wrote. - If you rely on the sandbox as a hard boundary, set
sandbox.failIfUnavailabletotrue. The sandboxing docs say that without it, if the sandbox cannot start, "Claude Code runs commands without sandboxing." - On Windows, test your PowerShell hooks again with a command they should refuse. Our post on Claude Code hooks that fail open has a way to do that.
What the sandbox was never meant to cover
None of these fixes change the shape of the Bash sandbox. The sandboxing docs say it wraps shell commands only. The Read, Edit and Write tools follow permission rules instead, and "command hooks, local MCP servers, plugin monitors, LSP servers, and helper commands such as your status line command and apiKeyHelper run with your full access." Reads are also wide by default: the same page lists "most of the machine, including credential files such as ~/.ssh and ~/.aws/credentials" as readable.
The sandbox is still useful on your own machine: it lets Claude Code run commands without asking, and its network proxy starts with no allowed hosts. It is also not the first time it has had gaps. The advisory for an earlier sandbox escape, GHSA-vp62-r36r-9xqp, says that exploiting it "required the ability to add untrusted content into a Claude Code context window", which is what prompt injection does.
For unattended work, Anthropic's sandbox environments page recommends something else: "Always run --dangerously-skip-permissions sessions inside a container, a VM, or the sandbox runtime, so that file tools, MCP servers, and hooks are also inside the boundary." Our guide to running Claude Code with --dangerously-skip-permissions safely goes through those options, and the post on Chromium and podman in Claude Code's sandbox covers another trade-off from this week.
Where Sessionboxer fits
Sessionboxer runs each session in its own Docker container, and Claude Code runs there with all permissions granted. The image's Claude Code settings set bypassPermissions and do not turn on the Bash sandbox. The container is the boundary for everything the agent starts: its shell, its startup files, its file tools and its hooks.
Command-based MCP servers run inside the box too, and the MCP servers chapter of the guide explains how you register them once in Global settings and switch them per session. A rewritten MCP config in a box would start a program in that box, not on your machine.
What it does not do:
- The image pins Claude Code 2.1.272. The fixes in 2.1.309 reach the box only when we ship a new image. Most of them concern the Bash sandbox, which is off in the box.
- Network egress from the box is not restricted. There is no host allowlist like the Bash sandbox's proxy, so an agent that reads a token in the box can send it anywhere.
- A container shares the host kernel, so it is a weaker wall than a VM. A box with Docker inside runs privileged unless Sysbox is installed on the host; the Docker inside sessions chapter explains the difference.
The short version
- Claude Code 2.1.309, out October 22, stops shell startup files from running outside the Bash sandbox before each command on macOS and Linux.
- It also protects the
--mcp-configfile from sandboxed commands, keeps Linux write denies in place after the session, and fixes several permission checks and Windows hooks. - Update every copy, read your startup files, and keep your MCP config outside the project.
- The Bash sandbox still covers shell commands only. For unattended runs, put the whole agent in a container or VM.