Most guides to the AI-agent git config bug tell you to run git inside the repo
On 1 September 2026, Manifold Security disclosed GitSpawn: eight findings across seven AI coding agents, all sharing one mechanism. A repository's own git configuration can name a command. When an agent runs git status or git diff to gather context, which it does constantly and without asking, git runs that command. It runs as you, outside the agent's sandbox, with no approval prompt. On several agents it fires before the workspace-trust prompt appears.
Two months on, most of what has been published about it gets three things wrong. And the mitigation repeated in almost every write-up is one you shouldn't follow.
1. The standard advice is to run git inside the repo you're afraid of
Nearly every guide says to check a suspicious repository by running git config --get core.fsmonitor from its root.
That is an instruction to run git inside the tree you suspect is hostile.
It happens to be survivable. git config --get reads configuration and doesn't refresh the index, so it doesn't trigger core.fsmonitor itself. But that is luck, not design. It checks one key out of dozens that can execute commands. It reads the root's configuration and says nothing about a hostile repository sitting one directory down. And it trains exactly the habit this bug exploits: open the thing, run git, look.
The safe way to inspect a repository you don't trust is to read its configuration as text, without invoking git at all.
2. git clone is not how this arrives, except when it is
Most coverage implies you're exposed when you clone a malicious repository. Ordinarily, you aren't. Cloning builds a fresh local .git/config on your machine; it does not copy the remote's. A hostile core.fsmonitor doesn't survive the trip.
The real delivery path is a directory copied with its .git folder intact: a zip of a project, a shared drive, a USB stick, a "here's the repo" attachment. Anything where the .git directory travels as files.
There is one exception, and it is the dangerous one. Git refuses to commit a directory named .git. It has no such rule for a directory that merely looks like a bare repository: a folder containing HEAD, objects/ and refs/. That folder commits and clones as ordinary files. Run git from inside it, or from any directory beneath it, and git discovers it and honours its config. It has to sit in a subdirectory; at the root it isn't used. Justin Steven documented this in 2022 (OVE-20210718-0001), and GitHub's Copilot CLI advisory describes the same primitive.
So the threat model has two halves. Archive-delivered repositories are common and fairly obvious. Buried bare repositories survive git clone and are the case almost no write-up mentions.
3. Your global setting doesn't protect you
A common reaction is to set core.fsmonitor=false in your global git config and move on. It doesn't work.
Git reads system configuration, then global, then the repository's own, and the last value it finds wins. That is documented in the FILES section of git-config(1) and in Pro Git's chapter on git configuration. A repository that sets core.fsmonitor overrides your global false.
The usual way to outrank repository configuration is per command, with git -c core.fsmonitor=false .... That covers one key, and I have only one source for it, so treat it as a partial measure.
Git's other protections barely apply. safe.directory checks who owns the directory, and you own anything you just unzipped. safe.bareRepository=explicit does stop the buried-bare-repository path, but it is opt-in and off by default.
4. It's September, and most of what you've read is one source
Much of the coverage is dated October. It is almost all derivative of Manifold's single September disclosure: roundups citing roundups, repeating the same version table. A dozen posts that mirror one source are one source.
That matters most for the question everyone actually wants answered, which is whether their agent is fixed. Almost every status after 1 September rests on a single source, usually the vendor's own changelog, with no independent retest.
Where the agents stand
This is the status at Manifold's last published retest on 1 September, plus what has appeared since. Anything not independently confirmed is labeled. Check with your vendor before relying on any row.
| Agent | At 1 Sep | Since |
|---|---|---|
| goose | Patched in 1.44.0 (CVE-2026-72718) | |
| Cursor | Patched | |
| Codex CLI / Desktop | Patched (CVE-2026-19592, CVE-2026-19593) | |
Claude Code, core.fsmonitor |
Patched by 2.1.196 | |
Claude Code, ultrareview |
Unpatched | 2.1.310 changelog says it now requires workspace trust. Unverified: vendor changelog only, no independent retest. |
| Hermes Agent | Unpatched (CVE-2026-71963) | v0.21.6 hardened git filter programs, a related sink. Whether this finding is closed is unverified. |
| Qwen Code | Unpatched | Nothing found indicating a fix. Unknown. |
| Grok Build | Unpatched | Nothing found indicating a fix. Unknown. |
Status as of [DATE — re-check before publishing].
core.fsmonitor is one key out of dozens
The disclosure centres on core.fsmonitor because it fires on the quietest operations an agent performs. It isn't alone. Filter drivers (clean, smudge, process) run on checkout, add and diff of any path whose attributes name them. Hermes and Claude Code have both shipped fixes for exactly that. Diff textconv drivers, core.pager, and a redirected core.hooksPath all reach command execution through ordinary agent behaviour. Further down the list are core.sshCommand, credential.helper, gpg.program, editor settings and ! aliases.
Git's own maintainers have said an exhaustive list of dangerous settings isn't achievable. Any tool or checklist that claims completeness is wrong.
What actually helps
- Don't run git, a git-aware editor, or an agent inside an unpacked archive. If you were sent a repository as files, clone it fresh from its real remote instead. Cloning drops a hostile
.git/config, though not a buried bare repository, which is what the next point is for. - Set
safe.bareRepository=explicitin your global config. It closes the buried-bare-repository path, the one that survives cloning. Expect it to break workflows that genuinely rely on bare repository discovery. - Keep your agents updated, and treat any "fixed" claim as unconfirmed until someone other than the vendor has retested it.
- Inspect untrusted repositories by reading their configuration as data, including every
include.pathandincludeIfthey pull in, and every bare-looking directory beneath them.
A lesson from my own scanner
I built a tool for that last point. Before releasing it, I had a reviewer who hadn't watched it being built read the code cold. It found a way to make the scanner lie.
The scanner capped how many included config files it would follow. A config with a couple of hundred include lines pointing at one decoy file used up that budget. The included file that actually carried core.fsmonitor was never read. The scan ended as "needs review" instead of "critical", and the --fail-on critical flag people use in CI turned that into a pass. A few large junk files could do the same to the scanner's overall work budget.
In other words, an attacker could make a compromised repository pass a security check by padding it.
It is fixed. Hitting any limit now produces its own exit code, which no flag can turn into a pass. But the general lesson is worth more than the fix: a scanner that fails open under load is a scanner an attacker can walk past. If your security checks have budgets, find out what happens when they run out.
The tool
sinkcheck is a read-only pre-flight check for this class of bug. It never runs git or any other process, never opens a network connection, and never writes anything. It parses configuration as data, follows include chains, finds buried bare repositories, and pairs .gitattributes with the drivers they name. In pre-flight mode it also checks the agent versions you have installed against the dated table above.
python -m sinkcheck scan PATH
python -m sinkcheck preflight PATH
python -m sinkcheck audit --root ~/code
Its test suite starts with a gate. Fixtures carry a live payload that writes a file outside the tree, and the build fails if that file ever appears. A control run of real git afterwards proves the payload works.
A clean result means nothing was found in the places it looked. It is not a clean bill of health, and the tool says so next to every verdict. Its known limits, including several untested Windows cases, are listed in the README.
github.com/painsparc/sinkcheck
Sources
- Manifold Security, GitSpawn disclosure, 1 September 2026, and coverage in The Hacker News
- Cloud Security Alliance research note
- Justin Steven, buried bare repositories and fsmonitor abuses (2022)
- GitHub Copilot CLI advisory GHSA-9ccr-r5hg-74gf
- git-config(1), FILES section; Pro Git, "Customizing Git: Git Configuration"
- Claude Code changelog
- Hermes Agent changelog
Not affiliated with any vendor or project named here.
— Pushkar Wagh, The Painsparc Company