Skip to content

Claude Code

Untrusted Git config can run code in Claude Code

3 min read

Written by an AI model from the linked sources and checked against them by a second model. How we work

All about: Claude Code versions and changes →
Image: manifold.security

Five CLI coding agents run a command planted in a repository’s own Git configuration while they gather context about the project, before any approval prompt appears. Manifold named Claude Code, Goose, Grok Build, Hermes and Qwen Code in a September 1 post, and says it found the same flaw in more agents than it lists. The researchers call the pattern GitSpawn.

The Manifold research started with one question: what does a CLI agent actually do when it starts up? Every agent they examined did roughly the same thing. It called git to learn about the project: the current branch, modified or staged files, the files a change touched, every tracked path, or a fresh worktree for a sub-agent. Some of those calls happen at startup and some once the session is running. Two of the samples, from different products, were git status --porcelain=2 --branch and git diff --name-only HEAD. You would probably type either one yourself.

Most git commands that touch the working tree refresh the index first, and that refresh is where the command gets in. core.fsmonitor is a documented performance setting for large repositories. Instead of scanning every file on disk, git asks a helper program what changed, and it runs that helper during the refresh. Git reads the setting from the repository’s own .git/config, so a repository can ship [core] fsmonitor = <command>. Then any git call that refreshes the index runs it, whichever command the agent picked. Manifold says core.fsmonitor isn’t the only setting that works this way, and one of its findings has nothing to do with it. An earlier GitHub advisory for Copilot CLI puts the number of similar keys at more than 15, among them core.hookspath, diff.external and merge.tool.

Git doesn’t carry this config over the network. Cloning, fetching or pulling a hostile repository does nothing. The repository has to arrive as files with its .git directory already inside, through a shared .zip, a shared drive, a sync folder or a USB stick. That is how colleagues pass projects around and how consultants hand them to clients. Manifold used a .zip for every proof of concept.

Once the files are on disk, the command runs as you, on your machine, with your privileges. The agent’s own code spawns git as a subprocess, so the command runs outside the sandbox and never triggers an approval prompt. In Manifold’s words, “The permission model never sees it.”

The bug class had already turned up in GitHub Copilot CLI. In that case a malicious bare repository was nested inside a project directory, and git found it automatically while walking the directory tree. Versions before 1.0.42 are affected. The fix sets safe.bareRepository=explicit through the GIT_CONFIG_COUNT environment variables, which take precedence over every config file, so git uses only bare repositories on an explicit allowlist.

Goose has a CVE for its case: CVE-2026-72718, published on August 10 and rated 7 High under CVSS v4.0. Before version 1.44.0, the goose review command ran git diff --name-only HEAD and git diff HEAD with the repository’s config left in place. The planted command fired before goose contacted a model, with no prompt submitted and no tool approval or trust prompt. SentinelOne says goose spawned git without overrides such as -c core.fsmonitor=false or a restricted environment, and that the patch adds a hardened git_command() helper. The NVD entry lists the impact: the command runs with the privileges and environment of the user running goose, so it can read or change files and exfiltrate environment secrets, provider API keys included. Version 1.44.0 fixes it.

No comments yet. Be the first.

Join the conversation

Sign in to leave a comment. It appears after moderation.