↓ Skip to main content
  1. Articles/

Claude Code v2.1.309 Is a Sandbox and Permissions Hardening Release. Read It Like One.

·1165 words·6 mins·
Florent Clairambault
Author
Florent Clairambault
CTO & software engineer — writing daily about spec-driven development and agentic coding

Claude Code v2.1.309 Is a Sandbox and Permissions Hardening Release. Read It Like One.

Release notes usually get skimmed for the feature headline. v2.1.309 has none. What it has is a long list of fixes where the agent’s guardrails did not do what their documentation said. If you run Claude Code unattended, in CI, or with auto mode, this is the release to read line by line. Everything below comes from the official changelog. I have not run this version, so the behavior claims are the changelog’s, not mine.

Sandbox escapes, closed
#

Several bullets describe cases where a sandboxed command could do more than the sandbox policy intended:

  • Sandboxed Bash commands on macOS and Linux were running the shell’s startup files outside the sandbox before each command. Startup files are user-writable code that runs on every command, so this is the kind of gap you want closed.
  • macOS denyWrite glob patterns did not apply at a path’s real location when the pattern’s folder was reached through a symlink.
  • Sandboxed commands and auto-accepted edits could modify the MCP config file passed with --mcp-config. An agent that can rewrite its own tool list can grant itself new servers.
  • On Linux, sandbox write denies lifted when a background command outlived the session.
  • Profile store write protection did not apply when the config directory was reached through a symlink.

The pattern is symlinks and ordering. Both are classic sandbox bugs, and both are what a prompt-injected agent would probe first. Anthropic fixing them is good. The lesson for you is to treat the sandbox as one layer, not the layer.

Permission checks that trusted too much
#

A second cluster is in the Bash permission logic:

  • The permission check trusted a variable set by a command whose redirect can fail to open.
  • Some compound commands that cd before running git, when the cd was wrapped or prefixed, skipped the prompt that a plain cd triggers.
  • An Edit(path) deny rule did not block a Bash redirect to that path in some commands that also held a subshell.
  • On Windows, PowerShell checks auto-approved some Set-Location or cd commands that carried extra arguments. They now prompt.
  • PowerShell hooks did not block when the program exited with code 2, and on Windows PreToolUse and PermissionRequest hooks with "shell": "powershell" failed open if Git for Windows wasn’t installed.

That last one deserves a pause. A hook that fails open is a control that quietly turns itself off. If you rely on hooks as policy enforcement on Windows machines, upgrade, then test that a deliberately failing hook actually blocks.

Permission rules written as string patterns against shell commands will always have edge cases, because shell syntax is enormous. Deny rules are a speed bump for a confused agent, not a barrier against an adversarial one. For real isolation use the sandbox, a container or a disposable worktree.

Worktree isolation guard
#

Worktree-isolated sessions are how many of us run parallel agents, and the guard that keeps each agent inside its tree got attention:

  • Some locale-prefixed commands and some zsh arithmetic commands were accepted when the guard should have refused them.
  • Worktrees and branch checkouts that Claude Code creates now ignore git replace refs, as its other git operations already did.
  • Worktree creation and reuse no longer lets git fetch objects on demand. In a partial clone with a Bash sandbox configured, objects are fetched first.

If you run several agents against one repo, this is your isolation story, and it just got tighter. It is also another reminder that “isolated” is a property of a specific guard implementation, not of the word.

Behavior changes that may surprise you
#

The “Changed” bullets are the ones that can break a pipeline:

  • claude ultrareview now requires workspace trust. It asks on a terminal and otherwise refuses. Scripts must pass --trust-workspace, which takes no value, so put a PR number or base branch before it. Or set CLAUDE_CODE_DISABLE_ULTRAREVIEW_TRUST_CHECK=1. If you have a CI job calling claude ultrareview, expect it to fail until you update it. Prefer the flag over the env var: the flag is visible in the command, the env var is a global off switch.
  • Dangerous rm and rmdir in bypass permissions mode on the Desktop app and VS Code are now denied immediately with a rewrite hint, instead of raising a prompt. That helps unattended sessions: the agent gets feedback and tries another route instead of hanging on a prompt nobody sees.
  • sed -i now gets the standard Bash prompt and runs as written, no longer as a simulated file-edit preview. Like other Bash edits, it is not restored by /rewind. If you used sed -i and relied on rewind as a safety net, commit before you let the agent do bulk rewrites.
  • Commands excluded from the sandbox now ask before writing to sandbox write-list paths when the sandbox is enabled but cannot run, and the unsandboxed fallback is refused there.

Context and reliability fixes
#

Not everything is security:

  • A nested CLAUDE.md over the size limit now loads only its start. Previously, sessions could compact repeatedly after reading files under a very large nested one. This is a reminder to keep CLAUDE.md files lean. A spec-driven setup lives or dies on instructions the model can actually hold, and a 200 KB instruction file is not one.
  • Split-pane agent teammates now inherit the tool deny and --tools rules from the leader’s command line. Before, a teammate could have more tools than the leader you restricted.
  • A disabled MCP server could be reconnected by a later permission prompt in print and SDK sessions. Fixed.
  • Long tool output previews could be cut through an emoji, leaving transcripts that jq could not parse. If you post-process session logs, this one is for you.
  • Improved disk-full handling: a Bash command cut off by a full disk now says so and names the folder to free up.
  • Fixed Claude notifying unrelated GitHub users by writing role names and placeholders as mentions in PRs, issues and comments.

What to do with this
#

  1. Upgrade, then diff your assumptions. If your threat model said “the sandbox blocks X”, re-read it against the bullets above.
  2. Update CI. Search your pipelines for claude ultrareview and add --trust-workspace deliberately.
  3. Test your hooks. Make one fail on purpose on each OS you support and confirm the tool call is blocked.
  4. Keep the human-grade backstops. Git history, branch protection and disposable worktrees are what remain when a guard has a bug.

The bigger picture
#

A long list of hardening fixes can read as bad news. I read it the other way. Every serious agent runtime has gaps between the policy it advertises and the policy it enforces. What matters is that someone finds them and ships the fix in the open changelog, in plain language, within days. That’s the difference between a tool built for autonomous use and one that treats autonomy as an afterthought. It’s also why running agents unattended means reading release notes the way you read a security advisory feed.

Sources
#

Guides

Claude Code v2.1.305 and v2.1.306: A Sandbox Escape Hatch, a Smarter Retry Watchdog, and a Managed-MCP Behavior Change

Claude Code v2.1.305 adds an opt-in sandbox.allowNestedUserNamespaces setting, a usage-limit recheck for unattended retry mode, and a change to how allowedMcpServers treats managed stdio servers. v2.1.306 is two fixes. Changelog-only analysis: I did not run either release.

Oct 21, 2026 · 6 min read

Guides

Claude Code v2.1.299: Stricter MCP Allow Rules, Fail-Closed Plugin Hooks, and Idle Compaction

Claude Code v2.1.299 (Oct 14) narrows MCP allow rules to the exact named server, makes plugin hooks that can’t answer refuse the action, stops following redirects on connector proxies, and compacts idle 200K+ token sessions before the one-hour cache expires.

Oct 14, 2026 · 5 min read

AI Tools

Claude Code's Third Security Patch in Three Days

v2.1.223 (Aug 6) closes four more permission and sandbox gaps on top of v2.1.221-222’s worktree isolation fix — a hidden-command Bash bypass, a workflow sandbox escape via dynamic import(), a bypassPermissions policy gap, and invisible-Unicode command padding. Three releases, three straight days, all fixing the same category of problem: agent actions escaping the boundaries meant to contain them.

Aug 6, 2026 · 4 min read

AI Tools

Claude Code v2.1.307: A Safety Event for Every Blocked Tool Call, and a One-Command API Migration

Claude Code v2.1.307 adds a claude_code.safety_event OpenTelemetry event for tool calls stopped, prompted or sent back by permission rules, auto mode, hooks or the sandbox, plus /claude-api api-version to move code to API version 2026-10-21. It also fixes HTTP MCP tool calls being sent twice. Changelog-only analysis; not run.

Oct 22, 2026 · 5 min read

AI Tools

Claude Code Hooks Can Now Fail Closed: onFailure: block and What v2.1.293–296 Changed

Claude Code v2.1.295 (Oct 8) added onFailure: “block” for command and HTTP hooks, so a hook that crashes, times out or exits unexpectedly now blocks the action instead of silently allowing it. v2.1.294 also fixed instruction-style prompt hooks that allowed what they were meant to block, while the MCP description limits changed twice in 48 hours.

Oct 10, 2026 · 6 min read