↓ Skip to main content
  1. Articles/

Claude Code v2.1.321's Quiet Security Fixes: Six Holes in the Permission Boundary

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

Everyone covered the model in v2.1.321. Fewer people read the bug-fix list, which is where the more useful information is. Buried among roughly 70 fixes are several that touch the exact boundary an autonomous agent depends on: what it may read, write, and send, and to whom. This post is based only on the official Claude Code changelog. Anthropic published no advisory I could find for these, and I haven’t reproduced any of them, so treat my analysis as interpretation of one-line release notes.

If you want the model side of this release, see the Fable 5.2 launch coverage.

The fixes that matter
#

Here are the entries, close to verbatim:

  1. MCP OAuth secret leak on redirect. “Fixed MCP OAuth requests sending secrets such as refresh tokens to another host when a server redirected them.”
  2. Sandbox escape for read-only Bash. “Fixed a case where a read-only Bash command ran outside the sandbox without a permission prompt.”
  3. Wrong-folder write checks. “Fixed a case where Bash permission checks judged a file write from the wrong folder and didn’t prompt.”
  4. Deny rules skipped by cp/mv. “Fixed deny rules and protected-file prompts not applying to the file that a cp or mv into a directory writes.”
  5. Commands in the wrong directory. “Fixed Bash commands sometimes running in the wrong folder when Claude sent several at once and an earlier one changed folders.”
  6. Hook decisions lost. “Fixed a PreToolUse hook’s ask being lost when another hook’s defer finished first and could not be honored.”

Taken one by one these are edge cases. Taken together they show where the hard problems in agent permission systems sit.

Why these are the hard bugs
#

Path resolution is the whole game
#

Fixes 3, 4 and 5 share one root: the system’s idea of which path a command touches differed from the shell’s idea. cp a.txt secrets/ never names the destination file. The write lands at secrets/a.txt, so a deny rule on secrets/a.txt has to be matched against a path the command line never spelled out. Likewise, if Claude batches cd subdir && ... with other commands, a permission check that assumes the original working directory evaluates the wrong file.

This is the classic gap between a static check on command text and the dynamic behaviour of the shell. Any allow/deny list over shell commands has it. The practical lesson: permission rules are a convenience layer, not a security boundary. The sandbox is the boundary.

The sandbox bypass is the one to care about
#

Fix 2 is the most serious by design. A command classified as read-only skips the prompt, which is a reasonable UX decision, since nobody wants to approve every ls. But “read-only” combined with “ran outside the sandbox” means a misclassification gives the command the host’s full filesystem and network view with no human or sandbox in the loop. The changelog doesn’t say what triggered it, and I won’t guess.

OAuth redirects: an old web bug in a new place
#

Fix 1 is a textbook problem. When a server answers an authenticated request with a redirect to a different host, a careless client forwards the credentials. Browsers and HTTP libraries stripped Authorization headers on cross-origin redirects years ago. MCP clients are rebuilding this plumbing, and refresh tokens are long-lived, so a leak is worse than a leaked access token. For earlier coverage of MCP OAuth token theft, see MCP OAuth Tokens Are Being Stolen; that is a different issue from this redirect bug.

What to do about it
#

  • Update. Run v2.1.321 or later, and v2.1.322 if you use Vertex. If you pin versions in CI or devcontainers, bump the pin.
  • Rotate if you’re cautious. If you connect to third-party or self-hosted OAuth MCP servers that you don’t fully control, re-authenticate to rotate refresh tokens. Nothing in the changelog says any token was actually stolen. This is hygiene, not a response to a known incident.
  • Keep deny rules, but add a real boundary. Deny rules on .env or secrets/ are good defence in depth. Back them with filesystem-level isolation: a container or devcontainer that simply doesn’t mount the secrets, scoped credentials, and an egress allowlist.
  • Audit your hooks. Fix 6 concerns PreToolUse hooks returning ask while another returns defer. If you rely on hooks to gate dangerous commands, write a test that exercises two hooks at once.
  • Be careful with batching in sensitive repos. Fix 5 concerns concurrent commands where one changes directory. Until you have confidence, prefer absolute paths in custom commands and skills.

The opinionated take
#

I’m pro-Claude Code, and I’d still rather read this list than not have it. A terminal-native agent with real shell access has a large attack surface, and the honest signal is a changelog that states plainly what was wrong. Compare that with tools where the permission model is a black box.

But the list also exposes the limit of the approach. Every one of these is a case where a parser tried to predict what a shell would do. That is a game you keep playing and occasionally lose. The durable answer is the one spec-driven teams already lean toward: run agents in disposable, least-privilege environments, and treat the permission prompt as a second line of defence. The same release’s launch notes put Anthropic’s own sandbox-escape evaluation for the new model at 3.1% of adversarial scenarios, a vendor figure that I covered in the launch post, which is a good reason not to relax.

Caveats
#

  • The changelog is terse. I don’t know severity, exploitability, or how long these bugs existed.
  • No CVE or advisory accompanied them that I could find.
  • “At least six” is my count of entries that touch the permission boundary; others in the ~70 may too.

Sources
#

AI Tools

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

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.

Oct 23, 2026 · 6 min read

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.314: Writes Outside Your Project Can Now Be Blocked in Every Mode

Claude Code v2.1.314 (Oct 30) adds permissions.blockWritesOutsideWorkingDirectories, which makes Write, Edit and NotebookEdit refuse paths outside the working directories in every permission mode, plus idle compaction in VS Code and Desktop for 200K+ token conversations. Changelog-only analysis; not run.

Oct 30, 2026 · 6 min read