One git call let a repo escape the Claude Code sandbox

Counterintuitively, switching the sandbox on is what removed the permission prompt. Accomplish turned Claude Code's sandbox on, set permission mode to the strictest "don't ask", opened a repository and sent one short message, and a command from that repo ran on their Mac, outside the sandbox, with nothing asking first.
At a glance
- Anthropic fixed the escape in Claude Code 2.1.247 on Aug 26, 2026, after a first round of hardening in 2.1.223 missed several of the git calls the chain could use.
- Claude Code's harness runs git outside the Seatbelt wrapper to index a repository, and git's core.fsmonitor setting, read from the repo's own .git/config, is a shell command git executes.
- The chain also works through an indirect prompt injection, and it needs no click: reading one file in the poisoned folder auto-loads a skill, and that triggers the unhardened index refresh.
If you have not been following: the same group earlier published an escape from the Claude Cowork sandbox, where one short message got the agent out to the host Mac with no prompt; by Accomplish's account that report was closed as Informative. The class has a name too. According to The Hacker News, Manifold Security disclosed eight flaws across seven command-line coding agents in which a repository's own git config names a command the agent then runs.
Seatbelt wraps the Bash tool, and the harness runs git outside it
Claude Code's sandbox uses Seatbelt, the macOS sandbox, to confine what the agent's shell commands can touch. According to HackTricks, that mechanism hooks almost any operation a process attempts and allows only what the profile permits. Because those commands are confined, Claude stops asking before it runs them, which is the trade the strictest mode makes.
According to Claude Code's docs, permission modes decide what runs without asking: manual stops before most shell commands and file edits, while bypassPermissions allows everything and is intended only for isolated containers and VMs.
The harness has git work of its own. To index a repository it runs git commands in the background, and those run outside the Seatbelt wrapper. Git reads core.fsmonitor from the repository's own .git/config and executes its value as a shell command whenever it refreshes its view of the working tree.
Four defenses stood in the way, and the escape went through the gap in each
First, hardening. The git commands the harness runs outside the sandbox pass flags that blank out core.fsmonitor and other dangerous options, so the harness never executes them. Accomplish found one call left unhardened: the file index refresh, git ls-files.
Second, the .git folder is protected. Claude's file tools refuse to write inside one, Seatbelt blocks bash from writing there, a fresh clone never brings the remote's config along, and renaming another folder into .git is blocked. That last rule covers the project's root only; the Seatbelt profile has no equivalent for a nested .git.
So a setup script can build a git folder under a harmless name, write core.fsmonitor into its config, and rename it to .git inside a subfolder, where nothing stops the rename.
Reading one file in the subfolder runs the rest of the chain
The third defense was location. The harness's git commands were expected to run in the project root, where .git is clean. In practice they run in whatever directory the Bash tool used last, so the script changes into the subfolder holding the poisoned .git.
The fourth was timing. The harness does not re-run that index refresh by itself, so the script's last line tells Claude to read a build report in the same subfolder. When Claude reads a file, it checks that folder for skills and loads what it finds, and loading a skill triggers a file index refresh.
Think of core.fsmonitor as a sticky note inside the folder that reads "run this before you look at me", which git obeys every time it refreshes the index.
Anthropic triaged the report the same day and shipped the full fix in 2.1.247
Accomplish reported the escape on Jul 13, 2026, and Anthropic triaged it that day. The first hardening shipped on Aug 6 in 2.1.223, but it missed some of the git calls and the escape moved to another one. Accomplish sent over the calls that were left, and the full fix landed on Aug 26 in 2.1.247.
Every git command the harness runs now blanks core.fsmonitor, so a repository's config cannot run anything. Accomplish also says the chain can be driven by an indirect prompt injection, not only by a setup script.
For its own agent, Accomplish puts the whole thing in a VM: bash, git, every process it starts. Real credentials never enter the guest, the agent holds placeholders, and its traffic leaves through a proxy on the host it cannot reconfigure.
That the first hardening missed calls, and the escape simply moved to the next one, reads as the measure of this class: the defense here is an inventory of git invocations, and an inventory can be one entry short. In our view the odd part is the asymmetry in the Seatbelt profile, where a rule blocks renaming a folder into the project's root .git and nothing blocks the same rename one directory down. Accomplish's own design concedes the limit as well, since inside its VM a poisoned core.fsmonitor still runs, it just runs in the guest.
The path Beltdown does not cover
Accomplish's chain is closed in 2.1.247. A neighbouring one may not be. According to The Hacker News, Manifold Security retested command-line coding agents on September 1 and found a second Claude Code path, which it calls the "claude ultrareview" path, still executing repository-supplied commands on 2.1.252. The material we have carries no fix date for that path, so the checkpoint to watch is whichever Claude Code release closes it.
Related stories
Comments
No comments yet. Be the first.
Join the conversation
Sign in with Google to leave a comment. Your name and avatar come from your Google profile, and the comment appears after moderation.
