Claude Code’s worktree bug is a useful reminder that AI coding agents are not just “chat with a shell attached.” They are software systems with their own tools, trust boundaries, filesystem assumptions, and security-critical glue code. When those pieces compose badly, a prompt injection can stop being a cute demo and become a real sandbox escape.
The reported bug affected Anthropic Claude Code CLI v2.1.139 and was fixed in v2.1.163. The core issue was surprisingly small: Claude Code allowed a git worktree to be named .git. In an ordinary project, that might sound like a weird edge case. In a malicious repository shaped to confuse Git’s idea of “where the repository metadata lives,” it became the first domino in a chain that ended with code execution outside the macOS seatbelt sandbox.
As Metnew describes, the attacker’s goal was to get code execution even in Claude Code’s most restricted mode: sandbox enabled, Bash not automatically allowed, and the agent mostly limited to approved read-only actions. The trick was not to ask Claude to run a suspicious command directly. Instead, the malicious repository’s CLAUDE.md instructed the agent to use its own worktree tools in a very specific sequence.
The repository was built so its root also looked like a valid Git directory: it contained files such as HEAD, config, objects/, and refs/. That matters because once Claude created a worktree named .git, later Git commands could be steered into treating attacker-controlled files as repository metadata.
From there, Git’s core.fsmonitor feature became the execution sink. git status is normally harmless-looking, and agents run it constantly. But if the repository config says to use a custom fsmonitor command, Git may execute attacker-controlled code during routine status checks. In this exploit, every worktree enter, exit, or status operation advanced a small staged payload.
The payload’s job was to bend Claude’s worktree paths outward. It swapped .claude/worktrees into a symlink pointing at the user’s home directory, caused Claude to create another .git worktree through that symlink, and then reconstructed worktree metadata so Claude could “enter” a worktree that was actually $HOME.
That still was not the final escape. The key final move was writing to ~/.zshenv. On macOS, zsh reads that file before the sandbox profile is applied to the command Claude is about to run. So once the exploit planted code there, the next Claude Bash invocation triggered unsandboxed execution. The proof of concept opened Calculator.
The merit of the bug is not that one component was obviously broken. It is that several individually plausible behaviors lined up badly:
Git trusts repository configuration.
Claude Code trusts repository instructions enough to operate its own tools.
Worktree paths interacted with symlinks and .git in dangerous ways.
Shell startup files execute before the intended sandbox boundary.
That is exactly why agent security is hard. A coding agent does not need one giant “run malware” button to be exploitable. It needs enough small, legitimate abilities that an attacker can arrange them into a new capability.
Anthropic’s fix rejected .git as a valid worktree name. That closes the reported chain, but the broader lesson is bigger: AI agent tools need threat models closer to browsers and package managers than to plain chatbots. Any feature that reads project-local instructions, runs Git, follows symlinks, manages worktrees, or launches shells is part of the attack surface.
The interesting part is also the uncomfortable part: the exploit did not require the user to approve an obviously malicious command. The agent was guided through “normal” development operations. That makes prompt injection against coding agents qualitatively different from prompt injection against a summarizer. The model is not merely saying the wrong thing. It is operating machinery.
For users, the practical takeaway is simple: do not open untrusted repositories in powerful coding agents casually, especially if the agent can run project tooling. For vendors, the takeaway is sharper: sandboxing has to wrap the real execution boundary, including shell startup, Git helpers, hooks, config-driven commands, and filesystem pivots. Otherwise, the sandbox may protect the command while missing the code that runs just before it.
