DEV Community

Cover image for Git Security Release: 6 Vulnerabilities and CVE-2026-111760
devTalk
devTalk

Posted on Originally published at dev-talk.com

Git Security Release: 6 Vulnerabilities and CVE-2026-111760

Last updated: 15 November 2026. This is a recent security release; see theupdate logand check the Git announcement for changes.

On 10 November 2026 the Git project released fixes for six vulnerabilities. One of them is the kind that makes developers nervous: cloning a malicious repository with git clone --recurse-submodules can lead to attacker-controlled code running on your machine. The other five are a mix of file-write, memory-corruption and denial-of-service bugs that matter most to servers and tools that handle untrusted repositories.

This article walks through all six, says which ones you should worry about, shows how to check your Git version (with a script I tested), and lists what you can do until you have patched. A caution up front: the Git announcement gives no severity scores, and I could not run the exploits, so the severity talk below is based on what the maintainers wrote.

The short version

  • Fixed in: Git 2.56.1 and the maintenance releases 2.55.1, 2.54.1, 2.53.1, 2.52.1, 2.51.3 and 2.50.2.
  • Affected: per the announcement, all versions back to v2.27.0. Versions older than 2.50 are no longer serviced upstream.
  • The serious one: CVE-2026-111760, code execution during a recursive clone of an attacker-controlled repository.
  • Exploited in the wild: none of the coverage I read reports it.
  • Action: update Git, and update every tool that bundles its own copy of Git.

The six vulnerabilities at a glance

CVE What happens Triggered by Impact (per the announcement)
CVE-2026-111760 Integer truncation in path handling lets a crafted path be written as .git git clone --recurse-submodules of an attacker's repository Remote code execution
CVE-2026-113408 Unvalidated HEAD symref from a server (protocol v2) with .. segments Cloning from a malicious server, then a later operation like git commit A ref file written outside the refs directory
CVE-2026-114467 More than two GPG signatures overflow a fixed array in remove_signature() Merging a tag whose message has more than two PGP signatures Stack corruption: denial of service, a risk for forges
CVE-2026-114469 Binary patch size check looks only at the compressed size Applying an attacker's binary patch (for example git apply) Out-of-bounds read and crash
CVE-2026-105437 Size overflow in the three-way merge buffer, with many conflicts and a large conflict-marker-size Any textual three-way merge: merge, rebase, cherry-pick, merge-tree Heap buffer overflow; on forges that read attributes from trees, a risk for anyone who can push and request a merge
CVE-2026-114466 fast-import features rewrite-submodules-from/to and export-pack-edges access arbitrary files Feeding an untrusted fast-import stream Arbitrary file read (content can leak in error messages) and append

CVE-2026-111760: how a clone can run code

The Git maintainers describe the bug like this. Git stores the length of a path name in a 32-bit field, but computes it as a larger type. A path of about 232 bytes makes the stored length wrap around to 4. Path validation looks at the full, long name and finds nothing wrong. Checkout, however, writes only the first 4 bytes, and those 4 bytes can be .git.

If the entry is a symlink, it can replace the .git file of a submodule. Normally a submodule's .git is a small file that points to the real repository directory. Pointing it at a directory the attacker controls, one that holds hooks or configuration, means Git will later run attacker-specified code. Git refuses to replace a .git directory with a symlink, but a freshly cloned submodule's .git is a file, and The Hacker News notes that this check does not block that case.

Requirements, per the announcement:

  • You clone an attacker-controlled repository with --recurse-submodules.
  • Such a repository fails the LARGE_PATHNAME and TREE_NOT_SORTED fsck checks, so major forges would be expected to refuse a push of it. But a malicious .gitmodules in a normal-looking repository that points at one is enough.

That second point is the practical risk. The repository you clone looks innocent. The submodule it pulls in is the weapon. Credit for the report goes to Robert Chen. A secondary source rates it High with a CVSS base score of 8.0; the Git announcement itself gives no score.

Who is at risk

  • Developers who clone unfamiliar repositories (open source, a contractor's repo, a "try this" link) with --recurse-submodules.
  • CI systems that check out pull requests from forks or arbitrary repositories with recursive submodules, especially when the job has secrets or deploy credentials.
  • Code hosting and review tools that merge, apply patches or import repositories for users. The merge, patch and signature bugs mostly matter here, and GitLab is cited as saying that servers running git merge-tree are most exposed to CVE-2026-105437.
  • Anything that bundles its own Git: GUI clients, IDEs, deployment tools, and container images. Updating the Git on your PATH does not update those.

Check your version

git --version
Enter fullscreen mode Exit fullscreen mode

Compare it with the fixed releases. This script does that for you. It knows the seven fixed releases and prints a clear verdict:

#!/usr/bin/env bash
# Usage: ./chk_git.sh                (checks the git on PATH)
#        ./chk_git.sh "git version 2.54.0"   (checks a version string)
# Fixed upstream releases for the November 2026 security release:
#   2.50.2 2.51.3 2.52.1 2.53.1 2.54.1 2.55.1 2.56.1
declare -A FIXED=( [2.50]=2 [2.51]=3 [2.52]=1 [2.53]=1 [2.54]=1 [2.55]=1 [2.56]=1 )
raw="${1:-$(git --version)}"
ver=$(echo "$raw" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)
[ -z "$ver" ] && { echo "could not parse: $raw"; exit 2; }
IFS=. read -r maj min pat <<< "$ver"
series="$maj.$min"
if [ "$maj" -gt 2 ] || { [ "$maj" -eq 2 ] && [ "$min" -gt 56 ]; }; then
  echo "$ver: newer than the 2.56 series, assumed to include the fixes"; exit 0
fi
if [ -z "${FIXED[$series]:-}" ]; then
  echo "$ver: series $series gets no upstream maintenance release for this advisory."
  echo "   Distribution packages may carry backported fixes: check your vendor's security notice."
  exit 1
fi
if [ "$pat" -ge "${FIXED[$series]}" ]; then
  echo "$ver: includes the fix (needs $series.${FIXED[$series]} or newer)"; exit 0
else
  echo "$ver: VULNERABLE. Update to $series.${FIXED[$series]} or newer (2.56.1 is the newest line)"; exit 1
fi
Enter fullscreen mode Exit fullscreen mode

Results from my tests of the script:

2.50.1: VULNERABLE. Update to 2.50.2 or newer (2.56.1 is the newest line)
2.50.2: includes the fix (needs 2.50.2 or newer)
2.54.0: VULNERABLE. Update to 2.54.1 or newer (2.56.1 is the newest line)
2.54.1: includes the fix (needs 2.54.1 or newer)
2.56.0: VULNERABLE. Update to 2.56.1 or newer (2.56.1 is the newest line)
2.56.1: includes the fix (needs 2.56.1 or newer)
2.57.0: newer than the 2.56 series, assumed to include the fixes
2.43.0: series 2.43 gets no upstream maintenance release for this advisory.
   Distribution packages may carry backported fixes: check your vendor's security notice.
Enter fullscreen mode Exit fullscreen mode

It also handled suffixes such as 2.56.0.windows.4 and 2.39.5 (Apple Git-154), and exits with an error for input it cannot parse. The Git on the machine where I tested was 2.43.0, a distribution package. That is the case the script cannot settle: Linux distributions often backport security fixes into older version numbers, so an old number there does not prove you are vulnerable, and a new-looking number from an unofficial source does not prove you are safe. Check your distribution's security notice for these CVEs.

Windows, macOS and bundled copies

  • Git for Windows: my sources disagree. One secondary report says Git for Windows 2.56.1 was released on 11 November, while The Hacker News says that, when it checked, no fixed Git for Windows version was out, and the releases page I fetched listed 2.56.0.windows.4 as the latest. Check the Git for Windows releases page yourself.
  • GitHub: per GitHub's statement quoted in the coverage, github.com and GitHub Enterprise Cloud are patched; GitHub Enterprise Server fixes are in 3.19.15, 3.20.11, 3.21.9 and 3.22.4; patched builds of GitHub Desktop and the Copilot app are being coordinated, with Codespaces and Actions to follow.
  • Bundled Git: any application that ships its own Git needs its own update. Look at the vendor's release notes.

Until you can update

The Git maintainers' advice, as quoted by GitHub's Elijah Newren, is to clone only from trusted servers and avoid recursive clones of untrusted repositories. These precautions do not replace installing the fixes. Some concrete ways to follow it:

Clone first, look, then fetch submodules

git clone https://example.com/someone/project.git
cd project
git config -f .gitmodules --get-regexp '^submodule\..*\.url$'
Enter fullscreen mode Exit fullscreen mode
submodule.vendor/libs.url ../libs
Enter fullscreen mode Exit fullscreen mode

A plain clone leaves submodule directories empty (I confirmed: zero files in vendor/libs after cloning). The second command lists every URL the repository wants to fetch. If a submodule points at a host you don't recognize, stop there. If they look fine:

git submodule update --init --recursive
Enter fullscreen mode Exit fullscreen mode

I tested this workflow with local repositories: the plain clone fetched nothing, the URL listing worked, and the update checked out the submodule. This reduces the chance of fetching a submodule you did not intend to, but it is a manual review step, not a guarantee that a submodule you decide to trust is safe, and it does not remove the underlying flaw.

Be careful with untrusted merges and patches

  • Don't merge tags or branches from sources you don't trust (CVE-2026-114467, CVE-2026-105437).
  • Don't git apply binary patches from unknown senders (CVE-2026-114469).
  • Don't feed git fast-import streams from untrusted sources (CVE-2026-114466).

A workaround for the merge overflow: conflict-marker-size

For CVE-2026-105437, The Hacker News cites GitLab suggesting a workaround: set conflict-marker-size=7 in each repository's info/attributes file. The reason this can work is that the dangerous input is the attacker-controlled attribute value, and info/attributes overrides the attributes committed in the repository. I tested the precedence with a small repository whose committed .gitattributes sets the marker size to 20:

printf '* conflict-marker-size=7\n' > .git/info/attributes
git check-attr conflict-marker-size -- f.txt
Enter fullscreen mode Exit fullscreen mode
f.txt: conflict-marker-size: 7
Enter fullscreen mode Exit fullscreen mode

Before that file existed, a conflicted merge produced 20-character markers (<<<<<<<<<<<<<<<<<<<< HEAD); afterwards it produced the standard 7. So the override works as described. What I could not do is confirm that the override prevents the overflow itself, since I cannot trigger that bug. For a hosting service, this is a stopgap while you roll out a patched Git, not a replacement for it.

The fast-import change can break scripts

The fix for CVE-2026-114466 turns the risky fast-import features off unless --allow-unsafe-features is passed. The Git announcement calls this a backwards-incompatible change with minimal expected impact, since the features mostly serve import/export remote helpers. If you run such a tool after updating and it fails, that flag is why. Add it only when the program generating the stream is trusted.

A hardening baseline worth adopting

These are my recommendations, not part of the announcement:

  • Don't run git clone --recurse-submodules as a reflex. Make recursive fetching a deliberate step for repositories you trust.
  • In CI, don't check out untrusted forks with recursive submodules in jobs that hold secrets. Separate "build the pull request" from "deploy" and keep credentials out of the first job.
  • Inventory the tools on build agents and laptops that bundle Git, and include them in your patching process.
  • Keep Git on servers that handle user repositories on a patch schedule of days, not months.

Common mistakes

  • Updating the system Git but leaving an IDE, GUI client or container image with an old bundled copy.
  • Assuming "2.4x is old, so I'm vulnerable" or "my distro updated, so I'm safe" without reading the vendor notice.
  • Treating a forge's fsck checks as protection when the real payload is a malicious .gitmodules in an ordinary-looking repository.
  • Ignoring the five non-RCE bugs on servers that merge or apply patches for users.
  • Applying --allow-unsafe-features everywhere to make a broken script work again.

Related Dev Talk articles

Frequently asked questions

Which Git versions are fixed?

2.56.1, 2.55.1, 2.54.1, 2.53.1, 2.52.1, 2.51.3 and 2.50.2. Anything older is no longer serviced upstream; your distribution may have its own patched package.

Can a normal git clone run malicious code?

For CVE-2026-111760 the announcement describes a recursive clone (--recurse-submodules) of an attacker-controlled repository. A plain clone did not fetch submodules in my test. Check the other five for the operations they need (merging, applying patches and so on).

Is it being exploited?

None of the sources I read report exploitation. Details are public, so patch anyway.

Do I need to update GitHub Desktop, VS Code or other tools?

If they bundle their own Git, yes, once the vendor releases an update. Whether a given tool bundles Git or uses the one on your system differs by tool, and I did not check individual products, so read each vendor's release notes.

Does disabling submodules fully protect me?

It removes the route for CVE-2026-111760, but the other bugs have other triggers. Update Git.

update log

  • 15 November 2026: first version.
  • To recheck on each update: the Git announcement and release notes, the Git for Windows releases page, your distribution's security notice, and GitHub's client rollout.

Sources


Originally published on DEV Talk.

Top comments (0)