MCP-SERVER-GIT · GHSA-6hqx-gqrx-c5r2 · Package
FIX → 2026.11.11
A Git repository's own .git/config can name a program (core.fsmonitor or diff.external) that Git runs when the server inspects that repository, so a read-only git_status call executes attacker-chosen code. The attacker gets code execution as the user running the MCP server, with its environment and credentials.
first public Nov 11, 2026 · 1 source
Could this affect your app?
Free first check from your website. Connect your repo for the full answer.
Teams running mcp-server-git, the reference Git MCP server, against repositories they did not create, such as vendored trees, shared archives or copied workspaces. A plain git clone does not carry the malicious config, so teams that only use freshly cloned repositories are less exposed. Until upgrading, the advisory says to limit the server to repositories whose .git directory you trust.
Not affected if fresh-clones-only, upgraded
Who cares claude-code, cursor, git, mcp, python
pip show mcp-server-git and confirm the version is below 2026.11.11..git directory came from an untrusted source, such as an archive, shared folder or vendored dependency..git/config in those repositories for fsmonitor, diff.external or hooksPath entries.Fixed in mcp-server-git 2026.11.11 (#5514). Upgrade to 2026.11.11 or later. The report below was written against 2026.11.4, before the fix; its "Fixed versions: none" line predates it.
The fix covers every sink the report lists, not only core.fsmonitor:
GIT_CONFIG_COUNT (which outranks every configuration file and is inherited by the Git processes Git itself starts), the settings that would make Git run a program: core.fsmonitor is false; core.hooksPath points at the null device, so no hook runs; commit.gpgSign and merge.verifySignatures are false; submodule.recurse, status.submoduleSummary and are ; and is .Check it with your coding agent
It reads this page and tells you if your code is affected.
Are you affected?
Ask from here. InfraStack checks the affected versions against your stack and answers in your inbox.
InfraStack checks the affected versions against your stack and answers in Slack, with the evidence and the fix.
Upgrade to 2026.11.11
mcp-server-git upgraded to 2026.11.11.merge.autoStashfalsecore.pagercatfilter.<name>.clean, smudge, process), merge driver (merge.<name>.driver) and branch.<name>.mergeOptions that the repository's own configuration defines is emptied. Drivers from the user's global or system configuration, such as Git LFS, keep working.git_merge also passes --no-gpg-sign and --no-verify-signatures, and every diff shown as a patch passes --no-ext-diff and --no-textconv, so diff.external, diff.<driver>.command and textconv filters are ignored.git_status and the diff tools pass --ignore-submodules=dirty, so Git never looks inside a submodule under the submodule's own configuration.GIT_CONFIG_COUNT, is refused rather than run unprotected.git_log and git_show do not run git log or git show, so log.showSignature is never consulted.
None for affected versions other than upgrading. Until then, point the server only at repositories whose .git directory you trust.
core.fsmonitor) during read-only toolsAsset: https://github.com/modelcontextprotocol (scoped asset of the HackerOne anthropic program)
Component: mcp-server-git (PyPI), the reference Git MCP server in modelcontextprotocol/servers (src/git)
Package version tested: mcp-server-git==2026.11.4 (PyPI wheel sha256 0cdaa8f446554d020f8ffa0e44ef45b89df4ed4deaeb961b4305d8a2852b4e0e, published 2026-11-04T21:34:52Z)
Default-branch revision tested: 36380287ed3b15d115b55f546617d723072b1296 (2026-11-04, src/git version 2026.11.4); the installed wheel's mcp_server_git/server.py is byte-identical to src/git/src/mcp_server_git/server.py at that revision (sha256 2304871e38ddd95ed807f628cc68b0e0cdd8ec2e82401110211ea8ea647715a5)
CWE: CWE-94 — Improper Control of Generation of Code ("Code Injection"); supporting: CWE-829 — Inclusion of Functionality from Untrusted Control Sphere
CVSS 4.0: 7.0 (HIGH) — CVSS:4.0/AV:L/AC:L/AT:N/PR:L/UI:A/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
Affected versions: mcp-server-git up to and including 2026.11.4 (verified on 2026.11.4 and 2026.10.28; earlier versions run the same Git commands and are presumed affected)
Fixed versions: none as of 2026-11-07
Also reproduced on: mcp-server-git==2026.10.28 (previous release; evidence/11-older-version.txt), with and without --repository confinement (evidence/12-unconfined-mode.txt)
mcp-server-git runs Git commands inside repositories chosen by the client without neutralising the repository's own configuration. Git honours command-bearing configuration keys from .git/config; core.fsmonitor names a program that Git executes whenever it refreshes the index. A call to the read-only git_status tool on an untrusted repository therefore executes an attacker-chosen program with the MCP server's privileges — its environment (including credentials from the client's env block), its filesystem access and its user — without any approval prompt and outside any sandbox that governs the model's own tool calls.
A second command-bearing key, diff.external, gives the same result through the read-only git_diff_unstaged and git_diff_staged tools. The command need not ship as a separate file: it can be inlined in the configuration line itself (core.fsmonitor = sh -c '…'), so a single edited .git/config is enough. The repository's configuration is never overridden: the server's only -c override is core.quotepath=false (src/git/src/mcp_server_git/server.py:104).
This is the vulnerability class publicly tracked as GitSpawn (CSA research note, 2026-09-03) and assigned CVEs for other agent tooling that shells out to Git: CVE-2026-45033 (GitHub Copilot CLI, core.fsmonitor, 8.5), CVE-2026-72718 (Goose, CWE-94, 7.0) and CVE-2026-71963 (Hermes Agent, 8.6). The mcp-server-git reference server has not applied the mitigation those vendors shipped, and no advisory or issue in the repository covers it.
The malicious configuration lives in .git/config, so the repository must reach the user with its .git directory intact. That is the normal case for the delivery channels this class was reported against (Copilot CLI, Goose, Hermes Agent): a project archive or CI artifact, a backup, a shared network folder, a vendored dependency tree checked into or unpacked beside the user's project, or an agent workspace whose files were copied rather than cloned. A plain git clone of a repository does not copy server-side .git/config, and GitHub's source ZIP excludes .git; those two channels alone do not carry the payload. Everything else that preserves the folder structure does, and the user does not have to run anything inside the repository — one git_status call from the MCP server is enough.
open_repo() (server.py:981-990) builds git.Repo(path), and GitPython executes git in that repository. The only configuration override anywhere in the server is core.quotepath=false:
# server.py:104
output = getattr(repo.git(c="core.quotepath=false"), command)(
*args, stdout_as_string=False
)
Git reads all other configuration from the repository's .git/config. Keys that name a program Git then runs include:
| key | runs when | server tool that triggers it |
|---|---|---|
core.fsmonitor | any index refresh | git_status, git_diff_unstaged, git_add, git_merge |
diff.external / diff.<driver>.command | diff output | git_diff_unstaged, git_diff_staged, git_diff |
core.hooksPath + hooks | merge | git_merge |
log.showSignature + gpg.program | log | git_log |
filter.<driver>.clean | staging | git_add |
commit.gpgSign + gpg.program | merge commit | git_merge |
The demonstrated sink is core.fsmonitor, because it fires on the most innocuous, typically auto-approved tool (git_status) and the payload need not print anything, so the tool result looks completely normal.
Full runnable PoC: poc/ in this packet. The repository is self-contained: the payload script ships inside the repository and is named by its own .git/config, so it travels intact through any channel that preserves a .git directory (an archive, a shared folder, a vendored dependency tree, a CI workspace).
Install the exact published package (Python 3.10+; 3.12/3.15 used here):
python3 -m venv .venv
./.venv/bin/pip install "mcp-server-git==2026.11.4"
Create a project workspace that is itself a Git repository, and a nested "untrusted" repository inside it:
mkdir -p /tmp/poc/workspace/vendor/untrusted-repo
git -C /tmp/poc/workspace init -q
git -C /tmp/poc/workspace/vendor/untrusted-repo init -q
cd /tmp/poc/workspace/vendor/untrusted-repo
echo hello > README.md
git add README.md && git -c user.email=a@b -c user.name=a commit -qm init
printf '#!/bin/sh\nid > /tmp/poc/payload-ran.txt\n' > payload.sh
chmod +x payload.sh
git config core.fsmonitor .