mcp-server-git --repository <path>is the one setting that keeps the reference Git MCP server inside a single repository. An advisory published on 2026-10-28 showed that a nested directory with a.gitfile pointing elsewhere let tool calls read and change a repository outside that boundary; the fix is version 2026.10.28. The configuration the project's README shows runs the server throughuvxwith no version in it, and a sibling advisory for the filesystem server, a regression, shows what each way of pinning costs.
What the advisory found
The advisory is GHSA-w766-5x43-whvw, mcp-server-git: nested gitdir file bypasses --repository confinement, reported by ShieldPi on 2026-10-27 and rated Moderate (CVSS 5.3). Affected versions are everything before 2026.10.28, which is the patched version. On PyPI, 2026.10.28 was uploaded on 2026-10-28 at 21:06 UTC, and it was still the newest release when we checked again on 2026-11-03 (UTC).
It is not the first advisory about keeping this server inside a repository. The repository's advisory list also has GHSA-j22h-9j4x-23w5, "Missing path validation when using --repository flag in mcp-server-git", published on 2025-12-17 with 2025.12.18 as the patched version, and GHSA-vjqx-cfc4-9h6v, "Path traversal in git_add allows staging files outside repository boundaries in mcp-server-git", published on 2026-02-25 with 2026.1.14 as the patched version. Each fix closed one way out of the boundary. That history is the practical reason to know which version your launch command runs, which is where this article ends up.
The mechanism rests on an ordinary Git feature. Git's repository layout documentation explains that instead of a .git directory "you can have a plain text file .git at the root of your working tree, containing gitdir: to point at the real directory that has the repository." Submodules and worktrees use this every day.
The server checked the path it was given, not the repository Git ended up opening. In the report's words, the path check "canonicalize[s] only the caller-supplied repo_path and check[s] that it is inside allowed_repository", and then the repository is opened, at which point "GitPython resolves that redirection later. There is no check after opening the repository to ensure that the repository actually selected by Git is the allowed one."
The reporter confirmed two effects through the real MCP interface: reading committed content from the outside repository, and creating a branch in it. "This bypasses the server's claimed repository boundary and permits unauthorized read and modification with the MCP process's privileges." The report is also explicit about what it does not claim: it "does not claim arbitrary host-file write or code execution", and it is "not claimed to be an unauthenticated standalone remote exploit".
The precondition is a second server
The interesting part of the report is how the nested .git file gets there. The caller has to be able to "create a nested directory and a .git file inside the allowed repository, or cause such content to be placed there", and to guess the path of another repository the process can reach.
The report names one realistic setup: "a deployment that also gives a filesystem MCP server write access to the same allowed directory." At the tested commit, the filesystem server's write_file "has no special .git exclusion."
That is a plausible configuration. Both servers live in the same reference repository, both are easy to point at the same project in Claude Code or Cursor, and each server's boundary looks fine on its own. The combination is what crossed it. An agent steered by text it read, in an issue or a file, would only need to use both tools in the right order.
What the README says after the fix
The mcp-server-git README is worth rereading, because it states the boundary more precisely than most people configure it.
"Without --repository, the server reads and writes any Git repository the server process can reach." The README adds that this holds "for the tools that change a repository too", and that "--repository is the only confinement the server offers".
It also widens what the flag admits: "At startup the server walks up to the enclosing repository root", so "A path inside the repository therefore allows tool calls anywhere in that repository, not only under the subdirectory given." If you pointed --repository at packages/api hoping to keep the server out of the rest of a monorepo, it does not do that.
And it describes the fix: a tool call's repo_path must be inside the repository, "and so must the directories Git then uses for it: a repository nested inside whose .git file, commondir or core.worktree points outside is refused."
Which version does your launch command run?
Here is the configuration the README gives for Claude Desktop, and the same command is what most people pass to claude mcp add:
{ "command": "uvx", "args": ["mcp-server-git", "--repository", "path/to/git/repo"] } There is no version in it. uv's tools guide gives two ways to say which version you want: "To run a tool at a specific version, use command@", and "To run a tool at the latest version, use command@latest". It also notes that "the @ syntax cannot be used for anything other than an exact version." The bare name is a third choice, and the guide we read does not promise it means the newest release, which is reason enough to write one of the other two.
The filesystem server's launch commands follow the same pattern with npx -y. npm's npm exec documentation says the CLI "utilizes its internal package cache when using the package name specified", and describes --prefer-online as the flag that "Forces staleness checks for packages, making the cli look for updates immediately even if the package is already in the cache."
To see what Claude Code launches, claude mcp list shows each configured server and its status, and claude mcp get <name> shows the details of one, according to the MCP documentation. The command and arguments live in .mcp.json for project scope and in ~/.claude.json for local and user scope.
Pin or float: the filesystem regression shows both costs
Three days before the Git advisory, the same repository published GHSA-4gxg-m5jx-9j57 for server-filesystem. On a case-insensitive file system, such as the macOS and Windows defaults, versions 2026.8.31, 1.0.0 and 2.0.0 could create files outside the allowed directories through a symlink spelled with different letter case. The detail that matters for pinning is one line: "It is a regression: 2026.7.10 refuses these requests." The fix is 2.0.1.
The npm registry's release times make the trade-off concrete:
| How the version is chosen | What it got from July to October 2026 |
|---|---|
| Exact pin to 2026.7.10 | Never had this regression, and never got any later change either (whether it is affected by the other advisories published that day is a separate question) |
| Always the newest release | Picked up the regression on 2026-08-31 and the fix on 2026-10-25 (2.0.1) |
| Exact pin to 2.0.1 | Fixed, and stays there until someone edits the command |
Neither column is free. An exact pin keeps out a bad release, including a malicious one pushed with a stolen token, but it also keeps out the next security fix until a person moves it. Floating gets fixes as soon as they ship and regressions just as fast. What we would avoid is the bare name, where the version is decided by a cache you did not choose.
What to change today
- Check the version. Run
claude mcp get <name>for your Git server and look at its arguments. If it saysmcp-server-gitwith no version, you do not know whether you are on 2026.10.28. - Write the version you mean. For an exact pin,
uvx mcp-server-git@2026.10.28 --repository /path/to/repo. For always-newest,uvx mcp-server-git@latest .... Withclaude mcp add, the command goes after--, as inclaude mcp add git -- uvx mcp-server-git@2026.10.28 --repository /path/to/repo. - Do the same for
server-filesystem. Version 2.0.1 or later fixes the case-variant symlink problem. The npm registry still listed 2.1.0 as the latest release on 2026-11-03 (UTC). - Always pass
--repository. The README's warning about running without it is the clearest sentence in the whole document, and the flag admits the whole enclosing repository, so pick the repository you mean. - Look at the servers together. If a filesystem server can write inside the directory a Git server is confined to, the precondition of this advisory is already met. Before 2026.10.28 that pair could cross the Git boundary; after it, the Git server refuses the redirect, which is the fix you want installed.
We read the boundary flags of MCP servers as promises from one server. This advisory is a reminder that they are promises about one server's own checks, and that the agent holding several tools at once can combine them in ways no single server sees.
Do you pin your MCP server versions in .mcp.json, float on @latest, or leave the bare name? If you have a way to get told when a pinned server has a fix waiting, describe it in the comments below.

