---
title: "Claude Code v2.1.309 Is a Sandbox and Permissions Hardening Release. Read It Like One."
date: 2026-10-23
tags: ["claude-code","security","sandbox","permissions","mcp","worktrees","changelog"]
categories: ["AI Tools","Agentic Workflows"]
summary: "Claude Code v2.1.309 ships roughly 60 changelog bullets, and the heart of it is closing gaps in the sandbox, Bash permission checks and worktree isolation guard. It also makes `claude ultrareview` require workspace trust and denies dangerous `rm` calls outright in bypass mode on Desktop and VS Code. Changelog-only analysis; not run."
---


![Claude Code v2.1.309 Is a Sandbox and Permissions Hardening Release. Read It Like One.](/images/claude-code-v2-1-309-sandbox-permission-hardening.png)

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](https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md). 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

- [Claude Code CHANGELOG, v2.1.309](https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md)

