Yesterday the Git project shipped six security fixes, and the headline one is the kind that makes you sit up: a malicious repository can run code on your machine when you recursively clone it. Not through a plugin, not through a hook you installed, not through a compromised credential. Just because you ran git clone --recurse-submodules on the wrong URL.
I recursive-clone without thinking. Most of us do. You find a project, you skim the README, you clone it with submodules so the build works, and you trust that the worst thing in there is a messy package.json. That reflex is exactly what CVE-2026-111760 turns against you.
The good news: the fix is a version bump, and the check takes ten seconds. Let me walk you through what the bug actually does, which versions are patched, and how to audit the repositories you already have on disk.

What CVE-2026-111760 actually does
Git checks paths before it writes files into your working tree. That check is the reason a repository can’t normally overwrite its own metadata. The problem is an integer truncation in how Git handles its index: an extremely long path can pass validation under one name, then get written to disk under a shorter name.
An attacker uses that gap to replace a submodule’s .git file with a symbolic link pointing at a directory full of malicious configuration or hooks. When Git later uses that directory, the attacker’s code runs. During a recursive clone, that means code execution on the machine that ran the clone.
Two details make this worth your attention. First, it is rated High with a CVSS score of 8.0. Second, it only fires when --recurse-submodules is in play, which is why the Git team’s workaround is blunt: don’t recursively clone repositories you don’t trust.
Submodules are the key. In a normal clone, .git is a directory and Git refuses to replace it with a symlink. In a freshly cloned submodule, .git is a file, a pointer that says where the real metadata lives. That file is the thing an attacker swaps. I confirmed the mechanism on my own machine: after adding a submodule, mysub/.git is a 30-byte text file containing gitdir: ../.git/modules/mysub. Small file, big consequences.
The other five fixes in the same release
The recursive-clone RCE is the one to patch first, but the same coordinated release closes five more. If you run Git in automation, read this part twice.
- CVE-2026-113408 — path traversal through a server’s advertised
HEAD. A malicious server can point a symref at an unborn branch and write outside the refs directory. - CVE-2026-114467 — stack corruption when stripping GPG signatures. A tag with more than two signatures can crash Git, and hosting services that merge on your behalf are exposed too.
- CVE-2026-114469 — out-of-bounds reads when applying binary patches. A small patch that expands past the size limit can crash Git.
- CVE-2026-105437 — heap corruption during large merges. Many conflicts combined with a large
conflict-marker-sizecan overflow the merge buffer. - CVE-2026-114466 — filesystem access through
fast-importstreams. Three features can read or write arbitrary files unless you pass--allow-unsafe-features.
All six are fixed in the same set of releases, so one upgrade covers the whole batch.
Step 1 — Check which Git you’re running
Run this:
git --version
The patched releases are 2.56.1, 2.55.1, 2.54.1, 2.53.1, 2.52.1, 2.51.3, and 2.50.2. If your version is at or above the patched release for your maintenance series, you are covered. If it is older, you are vulnerable.
On my WSL box the answer was git version 2.34.1, which ships with Ubuntu 22.04. That is well below 2.50.2, so it is firmly in the vulnerable camp. This is the part that trips people up: the upstream fix landed, but your distribution may not have caught up yet.
Step 2 — Patch it, and know what to do when your distro lags
Start with your package manager:
sudo apt update && sudo apt upgrade git
Then check the version again. If apt reports 2.34.1 as the candidate, like it does on my Ubuntu 22.04 machine, the distribution has not backported the fix yet. Check your distro’s security tracker for an advisory before assuming you are stuck. At the time of writing, Ubuntu’s CVE page for this issue had not been published, which is a normal lag for a vulnerability that is barely a day old.
If you cannot wait, build from source. I did exactly that to test this guide, and it is straightforward:
curl -L -o git-2.56.1.tar.gz \
https://codeload.github.com/git/git/tar.gz/refs/tags/v2.56.1
tar -xzf git-2.56.1.tar.gz
cd git-2.56.1
make -j$(nproc) NO_RUST=1 NO_CURL=1 NO_GETTEXT=1
sudo make install
One thing worth knowing: Git 2.56 has optional Rust components, and the build expects cargo unless you opt out. If you do not have Rust installed, pass NO_RUST=1 as I did. My build finished in a couple of minutes on a 16-core box and reported git version 2.56.1. I then ran a recursive clone with the new binary and it completed cleanly, with the submodule’s .git file pointing at the right place.
On Windows, Git for Windows v2.56.1.windows.1 carries the same six fixes. If you are a Homebrew or Scoop user, check that the formula has moved past 2.56.1 before you assume you are patched.
Step 3 — Audit the repositories you already have
Patching protects you going forward. It does not tell you whether you already cloned something dangerous. Three commands give you a fast read on that.
First, find any .git entry that is a symlink rather than a file or directory. That is the exact shape the attack leaves behind:
find . -name .git -type l
Second, list every .git entry and say what it actually is. On a healthy clone you should see one directory for the superproject and a small text file for each submodule:
find . -name .git -maxdepth 3 | while read f; do
printf "%s -> " "$f"
if [ -L "$f" ]; then echo "SYMLINK (suspicious)"
elif [ -f "$f" ]; then echo "gitfile: $(cat "$f")"
else echo "directory"; fi
done
Third, review your submodule URLs. A submodule that points at an absolute path or a host you do not recognize is a smell:
git config -f .gitmodules --get-regexp '^submodule\..*\.(path|url)$'
I ran all three against a test repository with a submodule and got a clean result: one directory, one gitfile pointing at ../.git/modules/mysub, and a relative submodule URL. If any of those come back odd on your machine, that is the moment to stop and look closer.
While you are in there, spend another minute on the other thing that hides in repositories: secrets. I walked through a practical scan for leaked API tokens in git history a while back, and the same habit applies here. An audit that only looks at file types and misses the credentials in commit history is half an audit.
Step 4 — Harden until you can patch
The Git team’s own guidance is plain: clone only from servers you trust, and do not recursively clone repositories you do not trust. Until your version is patched, treat --recurse-submodules on an unfamiliar repository as the risky operation it is.
There are three more precautions from the same advisory. Do not merge untrusted content or tags. Do not process binary patches from untrusted sources. And do not feed fast-import streams from sources you do not trust. None of these replace the patch, but they shrink the window while you wait for your distribution to catch up.
This is the same pattern I keep running into, and it is why I wrote about detecting compromised packages in the first place. The supply chain is not a place, it is a habit. Every tool that pulls code on your behalf is a place where someone else’s decision becomes your execution.
Step 5 — Do not forget the apps that bundle Git
Your terminal is not the only Git on the machine. GitHub Desktop, the GitHub Copilot app, Visual Studio, JetBrains IDEs, CI runners, and a dozen other tools ship their own copy. The Git project’s announcement specifically calls this out: updating your terminal client is necessary but not sufficient.
Check your IDE’s Git version, not just the one on your PATH. In VS Code, git --version in the integrated terminal usually tells you which binary it will use. In CI, pin your runner image and rebuild it. If you run GitHub Enterprise Server, the patched releases are 3.19.15, 3.20.11, 3.21.9, and 3.22.4.
And if you are the person who approves tooling for a team, this is a good week to send the memo. The fix is easy. The awkward part is the sentence “please check your Git version and update it.” I have written enough of those to know they get ignored right up until the week a CVE lands.
The habit matters more than the patch
Git is the one tool every developer trusts without thinking. We run it a hundred times a day, usually on code someone else wrote, usually without reading a line of it. That trust is not irrational, it is just overdue for a small correction.
So run git --version. If you are below the patched line, update. Then run the three audit commands above on the repositories you care about, and take thirty seconds to look at your submodule URLs. It is ten minutes of work that closes a real hole.
If you want the broader picture, I covered how malicious repositories became a delivery mechanism earlier this year, how the Keyv npm worm showed how fast a poisoned dependency moves, and yesterday I walked through checking and patching SSHole on Linux. The thread connecting them is the same one running through this Git fix: the tools we trust are only as trustworthy as the last thing we let them pull in.
Patch the version. Check the submodules. Then get back to work.