The Incident
On September 1, 2026, Manifold Security published “GitSpawn,” a coordinated disclosure of eight silent, pre-authentication code-execution flaws across seven CLI-based AI coding agents: Claude Code, Codex, Cursor, Grok Build, GitHub Copilot CLI, Hermes Agent, Goose, and Qwen Code. Four of the eight findings remained unpatched at publication.
The mechanism is one Git primitive. Each affected agent auto-invokes git status or git diff at session startup to build repository context. Git’s automatic bare-repository discovery walks the working tree looking for anything that resembles a bare repo — a directory containing HEAD and config — and reads that config. An attacker embeds vendor/malicious.git/ (or any other innocuous-looking path) in an otherwise legitimate project, sets core.fsmonitor (a Git performance setting whose value is a shell command Git invokes to enumerate changed files), and Git executes that command outside the agent’s sandbox, as the developer’s shell user. No prompt injection. No model interaction. On Claude Code and Hermes Agent, the payload fires before the workspace-trust prompt is accepted. On Qwen Code (v0.22.3), before the user has authenticated. On Grok Build (v1.0.13), on the first keystroke.
GitHub Security Lab shipped the pattern’s first CVE: CVE-2026-45033 for @github/copilot versions ≤ 1.0.42 (CVSS 8.5 High, GHSA published 2026-05-06, credited to syvb), fixed in Copilot CLI 1.0.43. The fix injects safe.bareRepository=explicit into every Git subprocess via GIT_CONFIG_COUNT / GIT_CONFIG_KEY_* / GIT_CONFIG_VALUE_* environment variables, so Git refuses to auto-discover nested bare repos. Anthropic silently patched the core.fsmonitor path in Claude Code 2.1.196 (reported 2026-06-26, fixed 2026-06-29) with no public advisory; a second Claude Code path reachable through the claude ultrareview command uses a different Git configuration key and remained live on 2.1.252 against the then-current 2.1.258 as of the September 1 disclosure. Goose shipped a fix in 1.44.0. Hermes Agent, Qwen Code, and Grok Build were unpatched at publication.
MITRE ATT&CK coverage: T1195.002 Compromise Software Supply Chain, T1546 Event Triggered Execution, T1059 Command and Scripting Interpreter, T1204.002 User Execution: Malicious File.
The Authority Path That Failed
The identity carrying execution authority at the moment of failure is the AI coding agent’s process, running as the developer’s shell user — home directory, SSH keys, cloud-CLI tokens, browser profile, Git credential helper, everything that account can reach. The developer intended to grant that identity a narrow scope: “read this repository and let me approve before you touch anything,” gated by the workspace-trust prompt (or, on Qwen Code, by sign-in; on Grok Build, by the first keystroke). The exercised scope is arbitrary command execution as the developer, before any of those gates fire.
The trust anchor that failed first is Git’s own automatic bare-repository discovery. When Git walks the tree for git status, any directory containing HEAD and config is honored as a repo, and the config’s core.fsmonitor value runs as a shell command. No agent stripped, sandboxed, or overrode that config before spawning git. The held-vs-exercised gap — the developer’s full shell identity vs “compute a summary of changed files” — was never inspected because the mental model that presents the workspace-trust prompt as a code-execution gate was never true. The prompt gates the agent’s own reasoning-loop tool calls, not the subprocesses the agent already spawned to figure out where it is. This is the third public rediscovery of the same class in nine months: Sonar’s December 2025 Claude Code CLI pre-trust arbitrary code execution (patched 2.0.71); Novee’s February 2026 Cursor Git Hooks flaw CVE-2026-26268 (CVSS 9.9, patched in Cursor 2.5); and now Manifold’s ecosystem-wide sweep.
SecurityV0 Perspective
This is unproven_execution / ASI05. Every affected agent silently attached a code-execution capability — git, with core.fsmonitor as the shell-command lever — that the deploying operator never authorized. The developer installed an AI coding assistant on the promise “look at my code, ask before acting.” What each agent shipped instead is “look at my code by spawning Git against whatever config the working tree contains, before the trust prompt renders.” That is the same pattern SecurityV0 mapped in the Langflow CSV Agent’s silent Python REPL and the Cursor Git Hooks CVE-2026-26268 disclosure: a capability the operator did not knowingly attach becomes the agent’s most powerful tool, executed on first ingestion of attacker-controlled input.
The evidence pack SecurityV0 would produce inventories every AI coding agent installed on developer hosts, resolves each installation to a specific version against the vendor’s fixed release (Copilot CLI ≥ 1.0.43; Claude Code ≥ 2.1.196 for the core.fsmonitor path but still exposed through 2.1.258 for the second claude ultrareview path; Goose ≥ 1.44.0; Cursor 2.5 for the earlier CVE-2026-26268 hook-file variant), maps the file paths each agent would read from .git/, and captures whether the agent spawns Git before the workspace-trust prompt or sign-in gate. Pre-clone, the pack answers the operator question: which agent installations on which developer hosts would honor a nested vendor/malicious.git/config before any gate fires? Post-exploitation, it answers the forensic question: which agent runs in the past 90 days spawned a process whose parent chain includes git inside a directory the developer never git inited, and what command did that spawn?
What To Do
- Pin developer hosts to the fixed versions and treat unpatched agents as untrusted.
@github/copilot≥ 1.0.43 closes CVE-2026-45033; Claude Code ≥ 2.1.196 closes thecore.fsmonitorpath but theclaude ultrareviewcode path remained live on 2.1.258 as of publication; Goose ≥ 1.44.0. Enforce agent versions via MDM and gate repository access on a pre-clone version check — the IDE version is a fleet inventory question, not a developer preference. Hermes Agent, Qwen Code v0.22.3, and Grok Build v1.0.13 were unpatched at Manifold’s publication; treat those installations as blocking findings until the vendor ships a fix. - Export
safe.bareRepository=explicitfrom every agent runtime, not just Copilot CLI. Copilot CLI’s fix works — Git refuses to auto-discover nested bare repos when this is set — but the fix is per-process env-var injection, and any agent that spawns Git without also setting it inherits the same class of flaw. Roll the setting into the Git configuration used by every AI coding agent runtime you run — developer workstations, CI runners, and any container image an agent runs inside. Verify each installed agent’s subprocess environment includes it before the agent runs on untrusted content. - Do not treat the workspace-trust prompt as a code-execution boundary. On four of the seven agents Manifold examined, code from a nested
.git/configexecutes before that prompt is presented. Any downstream policy that reasons “the developer had to click through, so agent code has consent” is unsound for the entire class. Explicit policy: no AI coding agent runs against a freshly cloned repository until the repository has been scanned for nested.gitdirectories, and the workspace-trust prompt is an additional gate, not the first one. - Instrument subprocess spawn from AI coding agent processes. For every developer host running an agent (Claude Code, Codex, Cursor, Grok Build, Copilot CLI, Hermes, Goose, Qwen Code, and their successors), log
execvecalls whose parent chain includes the agent’s binary, especially those spawninggit. GitSpawn is not the last shape this class will take —core.hookspath,core.pager,core.editor,credential.helper,diff.external, and any config key whose value Git treats as a program name are all leverage. The signal to keep is “agent spawned Git inside a directory the developer did not create.” - Refuse the
safe.bareRepository=explicitcollateral breakage as an excuse. The fix pattern has caused legitimate-workflow breakage in SwiftPM caches, Flutter iOS builds, VS Code Git integration, and Copilot CLI itself because the setting is exported into the shared process environment and other tools rely on bare-repo operations. Scope the environment variable to the agent’s subprocess tree only, not the developer’s ambient shell. Do not follow the workaround of unsettingsafe.bareRepository=explicitto unbreak SwiftPM — that path re-exposes the class.
Sources
- GitHub Security Advisory — GHSA-9ccr-r5hg-74gf (CVE-2026-45033, GitHub Copilot CLI)
- Sonar Research — Claude Code CLI arbitrary code execution before trust prompt
- Novee Security — CVE-2026-26268: How an AI Coding Agent Can Run Exploits in Cursor IDE
- Cursor Security Advisory — GHSA-8pcm-8jpx-hv8r
- Manifold Security — GitSpawn disclosure
- The Hacker News — Malicious .git Configs Can Make Claude, Codex, Cursor Run Attacker Code
- CybersecurityNews — GitSpawn Flaws Let Malicious Repositories Execute Code
- heise online — AI agents automatically execute Git malware when starting
- github/copilot-cli issue #3602 — safe.bareRepository=explicit collateral breakage
- microsoft/vscode issue #320880 — Copilot CLI breaks bare-repo Git operations
- flutter/flutter issue #187828 — safe.bareRepository breaks iOS builds
- swiftlang/swift-package-manager issue #8068 — SwiftPM cache regression
- MITRE ATT&CK: T1195.002, T1546, T1059, T1204.002