How one line in .git/config makes your AI coding agent run a stranger's code
Seven agents ran the same trick. The reason is not a bug in any of them. It is a Git feature from 2017 meeting a habit every agent has.
Read the original first: https://www.manifold.security/blog/ai-coding-agents-git-hijack
In one minute
- A Git repo can name a program in its own .git/config, and Git will run that program for you.
- Every AI coding agent runs git status in the background to see what changed. That is the trigger.
- The program runs as you, outside the agent's sandbox, sometimes before you type anything.
- git clone, fetch and pull do NOT copy that setting, so normal cloning is safe.
- A zip, a shared drive, a sync folder or a USB stick DOES carry it. That is the whole risk.
- Seven agents were tested and all seven ran it. Four of eight reported holes are still open.
The Git feature nobody thinks about
Git has a setting called core.fsmonitor. Its job is speed. On a big repo, git status has to check thousands of files to see what you changed, and that is slow. So Git lets you name a helper program that watches the filesystem and answers the question instantly.
The setting looks like this, and it lives in the repo's own .git/config file:
[core] fsmonitor = /path/to/some/program
That is the whole trick. The value is a command. Git runs it. This is documented, intended behavior that has been in Git since 2017, and it is not a vulnerability in Git.
The problem is who gets to write that line. Normally it is you, on your own machine, for your own repo. But .git/config is a file inside the folder. If the folder came from somewhere else, that line came from somewhere else too.
Why every agent fell for it at once
Seven different agents, built by seven different teams, all hit the same trap. That is usually a sign the cause is not a coding mistake in any of them. It is a shared assumption.
The assumption is this: to be useful, a coding agent has to know what is in your working tree. Which files changed, what branch you are on, what is staged. The cheapest way to learn that is to shell out to git status, and every agent does it, usually the moment a folder is opened and then repeatedly as you work.
So the sequence is:
- You open a folder with your agent.
- The agent runs git status in the background to orient itself.
- Git reads .git/config, finds core.fsmonitor, and runs the named program.
- That program runs as your user, with your permissions.
Notice what is missing from that list: you. No prompt was typed, no tool was approved, no command was confirmed. The execution happens during orientation, which every agent treats as the safe part.
Why the sandbox and the trust prompt do not help
Most agents have two protections here, and this defeats both by timing rather than by force.
The first is a sandbox. Agents run risky commands inside a restricted environment. But the background git status is not treated as a risky command, it is treated as reading the state of the folder, so it runs outside the sandbox. The helper program inherits that.
The second is a trust prompt, the dialog that asks whether you trust the code in this directory. The trouble is what has already happened by the time you see it. The agent has to look at the folder to tell you anything about it, and looking at the folder means running git. A prompt that appears after the first git call is asking permission for something that already happened.
This is why the fix in the patched agents is not a better sandbox. It is refusing to honor an untrusted fsmonitor value at all.
What Git copies, and what it does not
This is the part that decides whether you are actually exposed, and it is worth being precise about.
Git treats .git/config as local machine configuration, not as repo content. It is not tracked, not committed, and not transferred by the network protocol. So:
- git clone builds a fresh .git directory and writes its own config. Nothing carries over.
- git fetch and git pull move objects and refs. They do not touch your config.
- Cloning from a malicious repo does NOT hand you a malicious fsmonitor.
But copying a directory copies everything inside it, including the hidden .git folder and the config file in it. So:
- A zip or tarball of a working directory carries it.
- A shared network drive or a synced folder like Dropbox carries it.
- A USB stick carries it.
- A container image or a VM snapshot with a checked-out repo carries it.
The rule of thumb: if the code arrived as FILES, the config came with it. If it arrived over the Git protocol, it did not.
How to check a folder before you open it
The check is fast and needs no tooling. Read the config, look for any value that is a command:
cat .git/config git config --local --list | grep -Ei 'fsmonitor|hooksPath|sshCommand|pager|editor|askpass'
Those keys are the ones that take a program rather than a value. fsmonitor is the one being used here, but hooksPath is worth the same suspicion: it points Git at a directory of hook scripts, and hooks run on ordinary operations.
Also look at the hooks themselves, since they travel in the same copied directory:
ls -la .git/hooks/
A stock .git/hooks contains only files ending in .sample, which Git ignores. Anything without that suffix will run.
Who is affected
| Case | Status |
|---|---|
| git clone, then open with an agent | Safe. Clone writes its own config. |
| git fetch or git pull on a repo you cloned | Safe. Neither touches local config. |
| A zip or tarball a coworker sent you | EXPOSED if it includes the .git folder. |
| A repo on a shared or synced drive | EXPOSED. File copy carries .git/config. |
| A repo from a USB stick | EXPOSED. Same reason. |
| A container image or VM with a checked-out repo | EXPOSED if the tree was copied in. |
| Claude Code, Codex, Cursor, Goose | Patched per Manifold. Update and confirm your version. |
| Hermes, Qwen Code, Grok Build | Reported still open as of Manifold's Sept 1 retest. |
What to do
- Update every AI coding agent you use today, and check the version rather than assuming the update applied.
- Before pointing an agent at any folder that did not come from a clone, run cat .git/config and read it.
- Prefer git clone over accepting a zip. It is the single habit that removes most of this risk.
- If you must take a zip, delete its .git directory and clone the repo fresh, or re-init and re-add the remote.
- Tell your team the rule in one line: code that arrives as files carries settings, code that arrives over git does not.
- On the three agents still reported open, do not open untrusted folders with them at all until they ship a fix.
What is still unknown
- Manifold reports which versions are patched. The Claude Code changelog for 2.1.196 does not name fsmonitor, so that specific claim rests on Manifold's testing rather than on a vendor note.
- Whether any of this has been used against a real target. Nobody has published evidence either way.
- Whether the same timing gap reaches other config keys that take a command, beyond fsmonitor and hooksPath.
- Whether agents that added a fix cover every code path in their own product. Manifold found one Claude Code path still open at 2.1.252 after an earlier one was closed, which suggests these fixes are per-path rather than global.
Sources
- Manifold Security — the original report
- Git documentation: core.fsmonitor
- Git documentation: githooks