bundle-uri: refuse advertised URIs by protocol
PATCH 1/1 bundle-uri: refuse advertised URIs by protocol
From: Johannes Schindelin <[email protected]>
Servers may advertise bundle URIs that are not HTTP(S); copy_uri_to_file() then opens it as a local path. On Windows that can be a UNC path like //attacker/share/x, i.e. a clone can be manipulated into making an outbound SMB connection that leaks NTLM credentials (CVE-2026-62960).
Subject advertised URIs to the usual protocol allow-list (protocol.*.allow), which drops "file" (and bare/UNC paths) by default but keeps http/https/git/ssh. Do it in fetch_bundle_list(), the clone/fetch consume path, so ls-remote still lists everything; each skipped URI is reported. A user-supplied --bundle-uri is unaffected, and protocol.file.allow=always re-enables an advertised file URI.
---
bundle-uri: refuse advertised URIs by protocol
This is the security fix released with Git for Windows v2.55.0(4). Due to the transparent NTLM authentication ("SSPI"), the vulnerability affects only Windows. The patch has been sent to the git-security list on June 26th, 2026, but only received reviews in the PR in
https://github.com/git-for-windows/git/security/advisories/GHSA-xrpg-8j9v-v282's
private fork (which had to be deleted so that the advisory could be published).
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-2200%2Fdscho%2Frespect-allowed-protocols-in-bundle-uris-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-2200/dscho/respect-allowed-protocols-in-bundle-uris-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/2200
bundle-uri.c | 50 ++++++++++++++++++++++++++++++++ t/lib-bundle-uri-protocol.sh | 56 ++++++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+)
bundle-uri.c +50 -0
@@ -15,6 +15,8 @@#include "remote.h" #include "trace2.h" #include "odb.h" +#include "transport.h" +#include "url.h" static struct { enum bundle_list_heuristic heuristic;
@@ -890,11 +892,59 @@ cleanup:return result; } +/* protocol of 'uri', or "file" if it has none (bare/UNC/relative path) */ +static void bundle_uri_protocol (const char *uri,struct strbuf *out) +{ +const char *p = uri; + +while (is_urlschemechar (p == uri, *p)) + p++; +strbuf_reset (out); +if (p > uri &&starts_with (p,"://" )) +strbuf_add (out, uri, p - uri); +else +strbuf_addstr (out,"file" ); +} + +/* Drop advertised URIs whose protocol is not allowed (see protocol.*.allow). */ +static void sanitize_bundle_list (struct bundle_list *list) +{ +struct remote_bundle_info **skipped; +size_t nr =0 , i; +struct remote_bundle_info *info; +struct hashmap_iter iter; +struct strbuf proto =STRBUF_INIT ; + +ALLOC_ARRAY (skipped,hashmap_get_size (&list->bundles)); +hashmap_for_each_entry (&list->bundles, &iter, info, ent) { +if (!info->uri) +continue ; +bundle_uri_protocol (info->uri, &proto); +/* advertised URIs are not user-provided */ +if (!is_transport_allowed (proto.buf,0 )) { +warning (_ ("skipping bundle URI '%s': protocol '%s' " +"is not allowed" ), info->uri, proto.buf); + skipped[nr++] = info; + } + } +strbuf_release (&proto); + +for (i =0 ; i < nr; i++) { +hashmap_remove (&list->bundles, &skipped[i]->ent,NULL ); +clear_remote_bundle_info (skipped[i],NULL ); +free (skipped[i]); + } + +free (skipped); +} +int fetch_bundle_list (struct repository *r,struct bundle_list *list) {int result;struct bundle_list global_list; +sanitize_bundle_list (list); +/* * If the creationToken heuristic is used, then the URIs * advertised by 'list' are not nested lists and instead
t/lib-bundle-uri-protocol.sh +56 -0
59 lines not on this page · raw message
base-commit: 11c6700f10234578d10523faf35656ca491425c9
Signature · 1 line
gitgitgadget