← Back to Feed CACHED · 2026-06-29 21:48:54 · CACHE_KEY CVE-2026-55607
CVE-2026-55607 · CWE-22 · Disclosed 2026-06-29

Claude Code Sandbox Escape via Git Worktree Path Confusion

ASSESSED — NOISGATE
Vendor
—
—
—
Reassessed
—
—
—
Verdict: —
Do you agree?
01 · The Real Story

A hostile git repo convinces Claude Code's sandbox that `.git` is a directory it's allowed to walk into, and walks straight out of the box

CVE-2026-55607 lives in how @anthropic-ai/claude-code versions >= 2.1.38, < 2.1.163 handled git worktrees. A repo can ship a worktree literally named .git, plus symlinks and a poisoned fsmonitor config. When a developer points Claude Code at the repo and the agent (under prompt injection from README/issue content) performs worktree operations, path confusion + symlink resolution lets git execute core.fsmonitor *outside* the macOS sandbox-exec (seatbelt) profile. The documented payload overwrites ~/.zshenv, so the next shell the user opens runs attacker code as the user. Chained CWEs: CWE-22 (path traversal), CWE-59 (link following), CWE-78 (command injection via git config).

Anthropic rated this High (CVSS 4.0 7.7) and the rating is roughly fair. The novel-CVSS-4.0 vector AV:N/AC:L/AT:P/PR:N/UI:P/VC:H/VI:H/VA:H properly captures that exploitation needs a user to *passively* run Claude Code against attacker-controlled content (User Interaction: Passive, Attack Requirements: Present). It does not need credentials, doesn't need network position beyond a public repo URL, and the chain ends in code execution as the developer — which on a dev workstation typically means SSH keys, npm/PyPI tokens, AWS creds, and active git push rights to internal repos. We hold the verdict at HIGH rather than CRITICAL because (a) it does not reach hypervisor/IdP/DC blast radius directly and (b) auto-update has already shipped 2.1.163 to the bulk of the installed base.

"Sandbox escape in Claude Code worktree handling — a hostile repo + one user prompt-injection beats the seatbelt and writes ~/.zshenv. Patch the CLI fleet."
02 · The Attack Path

5 steps from start to impact.

STEP 01

Publish a poisoned repository

Attacker stages a public git repo (GitHub, an internal mirror, a 'sample project' shared in Slack) containing a crafted worktree directory named .git, a symlink pointing to $HOME, and a core.fsmonitor configuration that points at an attacker-controlled script bundled in the tree. README/issues/CONTRIBUTING contain prompt-injection text aimed at coercing Claude Code into running git worktree commands.
Conditions required:
  • Ability to host or push to a repo a target developer will clone
  • Knowledge that the victim uses Claude Code 2.1.38–2.1.162 on macOS
Where this breaks in practice:
  • Targets must clone an untrusted repo — corp policy may restrict this
  • Some shops mirror through an internal scanner before clone
Detection/coverage: GitHub Advanced Security and gitleaks-style scanners do NOT flag worktree-named directories or fsmonitor abuse. Custom YARA on core.fsmonitor + .git/ directory names is required.
STEP 02

Developer invokes Claude Code against the repo

Victim runs claude in the cloned directory, or attaches the repo path via an /init//add-dir style flow. Claude Code spawns git inside the seatbelt sandbox profile to enumerate the worktree.
Conditions required:
  • Claude Code 2.1.38 ≤ version < 2.1.163 installed
  • Developer trusts the repo enough to point the agent at it
Where this breaks in practice:
  • Teams running claude --dangerously-skip-permissions=false get prompted before some operations
  • macOS-only seatbelt escape — Linux/WSL builds use bubblewrap with different surface
Detection/coverage: EDR sees git worktree invocations but no telemetry calls them malicious. Sandbox profile violations are not logged by default.
STEP 03

Worktree path confusion + symlink follow

The crafted worktree named .git collides with git's own metadata directory semantics; combined with a symlink whose target is outside the project root, git resolves operations to attacker-chosen filesystem locations. The seatbelt profile permits writes inside the worktree, which now points at $HOME via the symlink.
Conditions required:
  • Path-traversal primitive triggered by worktree enumeration
  • Symlink resolved before sandbox policy check
Where this breaks in practice:
  • Hardened seatbelt profiles with explicit deny-write on $HOME would catch this — Anthropic's default did not
Detection/coverage: Filesystem-write telemetry to ~/.zshenv, ~/.bashrc, ~/.config/fish/conf.d/* from a git child process is a high-fidelity IoC.
STEP 04

git fsmonitor executes attacker binary outside sandbox

Git invokes the configured core.fsmonitor hook. Because the hook fires through a path that the seatbelt profile allows but the resolved target sits outside the project, the process runs unsandboxed with the developer's full UID. The PoC overwrites ~/.zshenv.
Conditions required:
  • core.fsmonitor honored (default on modern git)
  • fsmonitor binary path is writable / controllable
Where this breaks in practice:
  • git config --global core.fsmonitor false neutralizes this primitive
  • Repos cloned with GIT_CONFIG_NOSYSTEM=1 git -c core.fsmonitor=false clone are immune
Detection/coverage: Process tree claude → git → <repo-relative binary> writing to dotfiles is detectable in Jamf Protect, CrowdStrike, SentinelOne with a custom rule.
STEP 05

Shell respawn → code execution as the developer

Next time the user opens iTerm/Terminal/VS Code integrated shell, ~/.zshenv runs the attacker payload as the developer's UID. Payload typically harvests ~/.ssh/, ~/.aws/credentials, ~/.netrc, ~/.npmrc, browser cookies via Keychain prompts, and establishes persistence.
Conditions required:
  • Developer's default shell is zsh (macOS default since Catalina)
  • No EDR rule on dotfile writes
Where this breaks in practice:
  • FileVault + Keychain still gate some secret stores behind a prompt
  • SSO + short-lived AWS STS tokens limit cred lifetime
Detection/coverage: Login-shell parent of unexpected child processes; outbound connections from zsh at terminal-open are reasonable EDR signals.
03 · Compensating Control

1
Force-upgrade @anthropic-ai/claude-code fleet-wide to ≥ 2.1.163 — Auto-update covers most users but lab/CI/air-gapped installs lag. Push via Jamf/Intune/MDM software policy and verify with claude --version. Per noisgate HIGH SLA, mitigation deployed within 30 days, vendor patch (the same upgrade) within 180 days — for this CVE the mitigation and remediation collapse into the same action.
2
Disable git fsmonitor globally on developer endpoints — Run git config --global core.fsmonitor false and git config --global core.untrackedCache false via configuration management. fsmonitor is the execution primitive used in step 4; killing it neutralizes the chain even on unpatched Claude Code. Deploy within 30 days as a defense-in-depth measure even after patching.
3
Add EDR rule: dotfile writes by git child processes — Alert on writes to ~/.zshenv, ~/.zshrc, ~/.bashrc, ~/.bash_profile, ~/.config/fish/conf.d/*, ~/.profile where the parent chain includes git or claude. CrowdStrike CQL, Jamf Protect, SentinelOne STAR rules all support this. High signal, low noise on dev fleets.
4
Restrict Claude Code to vetted directories via MDM — Use macOS configuration profiles to apply a project-allowlist (work repos only) and block invocation from ~/Downloads, /tmp, and ad-hoc clones. Reduces the social-engineering surface for the 'try this repo' attack.
5
Audit and rotate developer-held long-lived credentials — Assume any developer who ran Claude Code on a sketchy repo between 2026-05 and 2026-06-25 is potentially affected. Rotate SSH keys, npm tokens, classic-PAT GitHub tokens, and long-lived AWS keys for high-privilege devs as a precaution; for the rest, prioritize moving to short-lived OIDC/STS issuance.
What doesn't work
  • Network egress filtering — the chain runs entirely on the developer's machine until the post-exploit phase; no network hop is required to land execution.
  • SAST/SCA on the Claude Code package — the bug is in worktree handling logic, not a vulnerable dependency. SCA will not flag versions in the affected range unless GHSA-7835-87q9-rgvv is wired into your scanner's feed.
  • macOS Gatekeeper / notarization — Claude Code is properly notarized; Gatekeeper is satisfied. Gatekeeper does not inspect runtime sandbox-escape behavior.
  • Defender / XProtect signatures — no signature exists for this PoC class; behavioral EDR rules are required.
  • Disabling prompt injection via --no-mcp — the injection vector is the repo content (README, issues, file names) that Claude Code reads as context, not MCP. Disabling MCP does not close it.
04 · Intelligence Metadata

The supporting signals.

In-the-wild statusNo public exploitation reports as of 2026-06-30. Disclosure window opened 2026-06-25.
Proof-of-conceptReporter metnew (HackerOne) submitted a working PoC privately; no public repo at time of writing. Expect a Check Point / Phoenix Security writeup within weeks given prior interest in Claude Code CVE chains.
KEV statusNot listed by CISA KEV as of 2026-06-30.
EPSSNot yet scored by FIRST — too new (disclosed 2026-06-25).
CVSSVendor (Anthropic) CVSS 4.0 7.7 / High. Vector CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N. SC/SI/SA all :N — no documented cross-system escalation beyond the developer's account.
Affected versions@anthropic-ai/claude-code >= 2.1.38, < 2.1.163 on macOS (seatbelt sandbox escape). Linux/WSL exposure unconfirmed by the advisory.
Fixed version2.1.163. Distributed via npm; auto-update is on by default.
ExposureNo Shodan/Censys signal — this is a client-side CLI, not a listener. Exposure is measured by *installed developer base* on vulnerable versions, not internet-facing assets.
DisclosureGitHub Security Advisory GHSA-7835-87q9-rgvv published 2026-06-25; CVE assigned CVE-2026-55607.
Reporterhackerone.com/metnew via Anthropic's HackerOne program.
Related CWEsCWE-22 (path traversal), CWE-59 (link following), CWE-78 (OS command injection via git config).

Sources.

  1. Anthropic GHSA-7835-87q9-rgvv advisory
  2. CWE-22: Path Traversal
  3. CWE-59: Link Following
  4. CWE-78: OS Command Injection
  5. Check Point research on Claude Code flaws
  6. Phoenix Security: Claude Code CVE chain analysis
  7. Git fsmonitor documentation (core.fsmonitor)
  8. npm @anthropic-ai/claude-code
05 · The Call

Final Verdict
= UNCHANGED to HIGH (7.4/10)

Why this verdict

  • User-interaction gated, but the gate is low: CVSS 4.0 marks UI as *Passive*. A developer only has to run claude against a repo they cloned — they do not have to approve a permission dialog. The friction is a single social-engineering hop (a 'try this cool MCP server' link in Slack), not a multi-stage compromise.
  • Endpoint blast radius is high: Code execution as the developer UID on an engineering workstation routinely yields ~/.ssh/, ~/.aws/credentials, ~/.npmrc auth tokens, git push credentials, and Keychain-mediated browser cookies. That is the same footprint that drove the SolarWinds and CircleCI dev-endpoint attack classes.
  • Role multiplier: On a standard developer workstation the chain ends in workstation compromise + credential theft — HIGH. On a developer who also holds prod-deploy keys, code-signing keys, or admin rights to internal package registries the chain ends in *supply-chain pivot* — CRITICAL outcome for that role. Because Claude Code's installed base is by definition developers (not random office staff), the supply-chain-adjacent role share is non-trivial; we anchor the floor at HIGH rather than letting friction drag it to MEDIUM.
  • Friction adjustments downward: macOS-only confirmed scope (Linux/WSL not enumerated in advisory) narrows reachable population. Default auto-update on npm has likely already retired most vulnerable installs. No KEV listing, no public PoC yet, no observed campaigns.
  • Floor check: Verdict floor under the noisgate role-multiplier rule is HIGH (developer-workstation → credential theft / source-tree compromise). Friction is not strong enough to break the floor; we sit *at* HIGH rather than above it because the chain stops at one user and does not auto-propagate.

Why not higher?

Not CRITICAL because exploitation requires user-initiated invocation of Claude Code against attacker-controlled content; it is not wormable, not zero-click, and does not directly compromise identity providers, hypervisors, or CI control planes. SC/SI/SA are :N in the CVSS 4.0 vector — no documented subsequent-system impact in the base chain.

Why not lower?

Not MEDIUM because the affected component runs as the developer on engineering workstations holding production credentials, source code, and push rights. A single successful compromise gives an attacker the same standing as an insider engineer — a category we never park in MEDIUM.

06 · Verification

Crowdsourced verification payload.

Run on each developer macOS/Linux workstation. Invoke as the target user (no sudo needed) — e.g. bash check-cve-2026-55607.sh. Exits 0 if patched, 1 if vulnerable, 2 if Claude Code is not installed (UNKNOWN).

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check-cve-2026-55607.sh — detect vulnerable @anthropic-ai/claude-code
# Vulnerable range: >= 2.1.38, < 2.1.163. Fixed: 2.1.163.
set -u

MIN_FIXED="2.1.163"
MIN_VULN="2.1.38"

version_ge() {
  # returns 0 if $1 >= $2 in dotted-semver
  [ "$(printf '%s\n%s\n' "$2" "$1" | sort -V | head -n1)" = "$2" ]
}

find_claude_version() {
  if command -v claude >/dev/null 2>&1; then
    claude --version 2>/dev/null | grep -Eo '[0-9]+\.[0-9]+\.[0-9]+' | head -n1
    return
  fi
  # npm global fallback
  if command -v npm >/dev/null 2>&1; then
    npm ls -g --depth=0 --json 2>/dev/null \
      | grep -A1 '"@anthropic-ai/claude-code"' \
      | grep -Eo '[0-9]+\.[0-9]+\.[0-9]+' | head -n1
  fi
}

VER="$(find_claude_version)"

if [ -z "${VER:-}" ]; then
  echo "UNKNOWN: claude-code not detected on PATH or via npm -g"
  exit 2
fi

if version_ge "$VER" "$MIN_FIXED"; then
  echo "PATCHED: claude-code $VER (>= $MIN_FIXED)"
  exit 0
fi

if version_ge "$VER" "$MIN_VULN"; then
  echo "VULNERABLE: claude-code $VER is in range [$MIN_VULN, $MIN_FIXED) — upgrade to $MIN_FIXED+"
  exit 1
fi

echo "PATCHED: claude-code $VER (pre-affected range)"
exit 0