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.
5 steps from start to impact.
Publish a poisoned repository
.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.- 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
- Targets must clone an untrusted repo — corp policy may restrict this
- Some shops mirror through an internal scanner before clone
core.fsmonitor + .git/ directory names is required.Developer invokes Claude Code against the repo
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.- Claude Code 2.1.38 ≤ version < 2.1.163 installed
- Developer trusts the repo enough to point the agent at it
- Teams running
claude --dangerously-skip-permissions=falseget prompted before some operations - macOS-only seatbelt escape — Linux/WSL builds use bubblewrap with different surface
git worktree invocations but no telemetry calls them malicious. Sandbox profile violations are not logged by default.Worktree path confusion + symlink follow
.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.- Path-traversal primitive triggered by worktree enumeration
- Symlink resolved before sandbox policy check
- Hardened seatbelt profiles with explicit deny-write on
$HOMEwould catch this — Anthropic's default did not
~/.zshenv, ~/.bashrc, ~/.config/fish/conf.d/* from a git child process is a high-fidelity IoC.git fsmonitor executes attacker binary outside sandbox
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.core.fsmonitorhonored (default on modern git)- fsmonitor binary path is writable / controllable
git config --global core.fsmonitor falseneutralizes this primitive- Repos cloned with
GIT_CONFIG_NOSYSTEM=1 git -c core.fsmonitor=false cloneare immune
claude → git → <repo-relative binary> writing to dotfiles is detectable in Jamf Protect, CrowdStrike, SentinelOne with a custom rule.Shell respawn → code execution as the developer
~/.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.- Developer's default shell is zsh (macOS default since Catalina)
- No EDR rule on dotfile writes
- FileVault + Keychain still gate some secret stores behind a prompt
- SSO + short-lived AWS STS tokens limit cred lifetime
zsh at terminal-open are reasonable EDR signals.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.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.~/.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.~/Downloads, /tmp, and ad-hoc clones. Reduces the social-engineering surface for the 'try this repo' attack.- 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.
The supporting signals.
| In-the-wild status | No public exploitation reports as of 2026-06-30. Disclosure window opened 2026-06-25. |
|---|---|
| Proof-of-concept | Reporter 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 status | Not listed by CISA KEV as of 2026-06-30. |
| EPSS | Not yet scored by FIRST — too new (disclosed 2026-06-25). |
| CVSS | Vendor (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 version | 2.1.163. Distributed via npm; auto-update is on by default. |
| Exposure | No 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. |
| Disclosure | GitHub Security Advisory GHSA-7835-87q9-rgvv published 2026-06-25; CVE assigned CVE-2026-55607. |
| Reporter | hackerone.com/metnew via Anthropic's HackerOne program. |
| Related CWEs | CWE-22 (path traversal), CWE-59 (link following), CWE-78 (OS command injection via git config). |
Sources.
Why this verdict
- User-interaction gated, but the gate is low: CVSS 4.0 marks UI as *Passive*. A developer only has to run
claudeagainst 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,~/.npmrcauth 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.
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).
#!/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