diff --git a/backport-CVE-2025-48384-config-quote-values-containing-CR-character.patch b/backport-CVE-2025-48384-config-quote-values-containing-CR-character.patch deleted file mode 100644 index d7e94700296f5110989ee7fc9631157d76b69d1f..0000000000000000000000000000000000000000 --- a/backport-CVE-2025-48384-config-quote-values-containing-CR-character.patch +++ /dev/null @@ -1,123 +0,0 @@ -From 05e9cd64ee23bbadcea6bcffd6660ed02b8eab89 Mon Sep 17 00:00:00 2001 -From: Justin Tobler -Date: Mon, 19 May 2025 21:26:04 -0500 -Subject: [PATCH] config: quote values containing CR character - -When reading the config, values that contain a trailing CRLF are -stripped. If the value itself has a trailing CR, the normal LF that -follows results in the CR being unintentionally stripped. This may lead -to unintended behavior due to the config value written being different -when it gets read. - -One such issue involves a repository with a submodule path containing a -trailing CR. When the submodule gets initialized, the submodule is -cloned without being checked out and has "core.worktree" set to the -submodule path. The git-checkout(1) that gets spawned later reads the -"core.worktree" config value, but without the trailing CR, and -consequently attempts to checkout to a different path than intended. - -If the repository contains a matching path that is a symlink, it is -possible for the submodule repository to be checked out in arbitrary -locations. This is extra bad when the symlink points to the submodule -hooks directory and the submodule repository contains an executable -"post-checkout" hook. Once the submodule repository checkout completes, -the "post-checkout" hook immediately executes. - -To prevent mismatched config state due to misinterpreting a trailing CR, -wrap config values containing CR in double quotes when writing the -entry. This ensures a trailing CR is always separated for an LF and thus -prevented from getting stripped. - -Note that this problem cannot be addressed by just quoting each CR with -"\r". The reading side of the config interprets only a few backslash -escapes, and "\r" is not among them. This fix is sufficient though -because it only affects the CR at the end of a line and any literal CR -in the interior is already preserved. - -Co-authored-by: David Leadbeater -Signed-off-by: Justin Tobler -Signed-off-by: Taylor Blau ---- - config.c | 2 +- - t/t1300-config.sh | 11 +++++++++++ - t/t7450-bad-git-dotfiles.sh | 33 +++++++++++++++++++++++++++++++++ - 3 files changed, 45 insertions(+), 1 deletion(-) - -diff --git a/config.c b/config.c -index 9ff6ae1cb9..629981451d 100644 ---- a/config.c -+++ b/config.c -@@ -2999,7 +2999,7 @@ static ssize_t write_pair(int fd, const char *key, const char *value, - if (value[0] == ' ') - quote = "\""; - for (i = 0; value[i]; i++) -- if (value[i] == ';' || value[i] == '#') -+ if (value[i] == ';' || value[i] == '#' || value[i] == '\r') - quote = "\""; - if (i && value[i - 1] == ' ') - quote = "\""; -diff --git a/t/t1300-config.sh b/t/t1300-config.sh -index f4e2752134..1010410b7e 100755 ---- a/t/t1300-config.sh -+++ b/t/t1300-config.sh -@@ -2590,4 +2590,15 @@ test_expect_success 'writing to stdin is rejected' ' - - done - -+test_expect_success 'writing value with trailing CR not stripped on read' ' -+ test_when_finished "rm -rf cr-test" && -+ -+ printf "bar\r\n" >expect && -+ git init cr-test && -+ git -C cr-test config set core.foo $(printf "bar\r") && -+ git -C cr-test config get core.foo >actual && -+ -+ test_cmp expect actual -+' -+ - test_done -diff --git a/t/t7450-bad-git-dotfiles.sh b/t/t7450-bad-git-dotfiles.sh -index 5b845e899b..2026285566 100755 ---- a/t/t7450-bad-git-dotfiles.sh -+++ b/t/t7450-bad-git-dotfiles.sh -@@ -347,4 +347,37 @@ test_expect_success 'checkout -f --recurse-submodules must not use a nested gitd - test_path_is_missing nested_checkout/thing2/.git - ' - -+test_expect_success SYMLINKS,!WINDOWS,!MINGW 'submodule must not checkout into different directory' ' -+ test_when_finished "rm -rf sub repo bad-clone" && -+ -+ git init sub && -+ write_script sub/post-checkout <<-\EOF && -+ touch "$PWD/foo" -+ EOF -+ git -C sub add post-checkout && -+ git -C sub commit -m hook && -+ -+ git init repo && -+ git -C repo -c protocol.file.allow=always submodule add "$PWD/sub" sub && -+ git -C repo mv sub $(printf "sub\r") && -+ -+ # Ensure config values containing CR are wrapped in quotes. -+ git config unset -f repo/.gitmodules submodule.sub.path && -+ printf "\tpath = \"sub\r\"\n" >>repo/.gitmodules && -+ -+ git config unset -f repo/.git/modules/sub/config core.worktree && -+ { -+ printf "[core]\n" && -+ printf "\tworktree = \"../../../sub\r\"\n" -+ } >>repo/.git/modules/sub/config && -+ -+ ln -s .git/modules/sub/hooks repo/sub && -+ git -C repo add -A && -+ git -C repo commit -m submodule && -+ -+ git -c protocol.file.allow=always clone --recurse-submodules repo bad-clone && -+ ! test -f "$PWD/foo" && -+ test -f $(printf "bad-clone/sub\r/post-checkout") -+' -+ - test_done --- -2.33.0 - diff --git a/backport-CVE-2025-48385-bundle-uri-fix-arbitrary-file-writes-via-parameter-i.patch b/backport-CVE-2025-48385-bundle-uri-fix-arbitrary-file-writes-via-parameter-i.patch deleted file mode 100644 index 60afc4422a2ce8538833dd7ea05ab63dc91a15f6..0000000000000000000000000000000000000000 --- a/backport-CVE-2025-48385-bundle-uri-fix-arbitrary-file-writes-via-parameter-i.patch +++ /dev/null @@ -1,160 +0,0 @@ -From 35cb1bb0b92c132249d932c05bbd860d410e12d4 Mon Sep 17 00:00:00 2001 -From: Patrick Steinhardt' via Git Security -Date: Wed, 14 May 2025 08:32:02 +0200 -Subject: [PATCH] bundle-uri: fix arbitrary file writes via parameter injection - -We fetch bundle URIs via `download_https_uri_to_file()`. The logic to -fetch those bundles is not handled in-process, but we instead use a -separate git-remote-https(1) process that performs the fetch for us. The -information about which file should be downloaded and where that file -should be put gets communicated via stdin of that process via a "get" -request. This "get" request has the form "get $uri $file\n\n". As may be -obvious to the reader, this will cause git-remote-https(1) to download -the URI "$uri" and put it into "$file". - -The fact that we are using plain spaces and newlines as separators for -the request arguments means that we have to be extra careful with the -respective vaules of these arguments: - - - If "$uri" contained a space we would interpret this as both URI and - target location. - - - If either "$uri" or "$file" contained a newline we would interpret - this as a new command. - -But we neither quote the arguments such that any characters with special -meaning would be escaped, nor do we verify that none of these special -characters are contained. - -If either the URI or file contains a newline character, we are open to -protocol injection attacks. Likewise, if the URI itself contains a -space, then an attacker-controlled URI can lead to partially-controlled -file writes. - -Note that the attacker-controlled URIs do not permit completely -arbitrary file writes, but instead allows an attacker to control the -path in which we will write a temporary (e.g., "tmp_uri_XXXXXX") -file. - -The result is twofold: - - - By adding a space in "$uri" we can control where exactly a file will - be written to, including out-of-repository writes. The final - location is not completely arbitrary, as the injected string will be - concatenated with the original "$file" path. Furthermore, the name - of the bundle will be "tmp_uri_XXXXXX", further restricting what an - adversary would be able to write. - - Also note that is not possible for the URI to contain a newline - because we end up in `credential_from_url_1()` before we try to - issue any requests using that URI. As such, it is not possible to - inject arbitrary commands via the URI. - - - By adding a newline to "$file" we can inject arbitrary commands. - This gives us full control over where a specific file will be - written to. Potential attack vectors would be to overwrite hooks, - but if an adversary were to guess where the user's home directory is - located they might also easily write e.g. a "~/.profile" file and - thus cause arbitrary code execution. - - This injection can only become possible when the adversary has full - control over the target path where a bundle will be downloaded to. - While this feels unlikely, it is possible to control this path when - users perform a recursive clone with a ".gitmodules" file that is - controlled by the adversary. - -Luckily though, the use of bundle URIs is not enabled by default in Git -clients (yet): they have to be enabled by setting the `bundle.heuristic` -config key explicitly. As such, the blast radius of this parameter -injection should overall be quite contained. - -Fix the issue by rejecting spaces in the URI and newlines in both the -URI and the file. As explained, it shouldn't be required to also -restrict the use of newlines in the URI, as we would eventually die -anyway in `credential_from_url_1()`. But given that we're only one small -step away from arbitrary code execution, let's rather be safe and -restrict newlines in URIs, as well. - -Eventually we should probably refactor the way that Git talks with the -git-remote-https(1) subprocess so that it is less fragile. Until then, -these two restrictions should plug the issue. - -Reported-by: David Leadbeater -Based-on-patch-by: David Leadbeater -Signed-off-by: Patrick Steinhardt -Signed-off-by: Taylor Blau ---- - bundle-uri.c | 22 ++++++++++++++++++++++ - t/t5558-clone-bundle-uri.sh | 23 +++++++++++++++++++++++ - 2 files changed, 45 insertions(+) - -diff --git a/bundle-uri.c b/bundle-uri.c -index ca32050a78..a6a3c1c4b3 100644 ---- a/bundle-uri.c -+++ b/bundle-uri.c -@@ -292,6 +292,28 @@ static int download_https_uri_to_file(const char *file, const char *uri) - struct strbuf line = STRBUF_INIT; - int found_get = 0; - -+ /* -+ * The protocol we speak with git-remote-https(1) uses a space to -+ * separate between URI and file, so the URI itself must not contain a -+ * space. If it did, an adversary could change the location where the -+ * downloaded file is being written to. -+ * -+ * Similarly, we use newlines to separate commands from one another. -+ * Consequently, neither the URI nor the file must contain a newline or -+ * otherwise an adversary could inject arbitrary commands. -+ * -+ * TODO: Restricting newlines in the target paths may break valid -+ * usecases, even if those are a bit more on the esoteric side. -+ * If this ever becomes a problem we should probably think about -+ * alternatives. One alternative could be to use NUL-delimited -+ * requests in git-remote-http(1). Another alternative could be -+ * to use URL quoting. -+ */ -+ if (strpbrk(uri, " \n")) -+ return error("bundle-uri: URI is malformed: '%s'", file); -+ if (strchr(file, '\n')) -+ return error("bundle-uri: filename is malformed: '%s'", file); -+ - strvec_pushl(&cp.args, "git-remote-https", uri, NULL); - cp.err = -1; - cp.in = -1; -diff --git a/t/t5558-clone-bundle-uri.sh b/t/t5558-clone-bundle-uri.sh -index 996a08e90c..2af523aaa4 100755 ---- a/t/t5558-clone-bundle-uri.sh -+++ b/t/t5558-clone-bundle-uri.sh -@@ -1052,6 +1052,29 @@ test_expect_success 'bundles are downloaded once during fetch --all' ' - trace-mult.txt >bundle-fetches && - test_line_count = 1 bundle-fetches - ' -+ -+test_expect_success 'bundles with space in URI are rejected' ' -+ test_when_finished "rm -rf busted repo" && -+ mkdir -p "$HOME/busted/ /$HOME/repo/.git/objects/bundles" && -+ git clone --bundle-uri="$HTTPD_URL/bogus $HOME/busted/" "$HTTPD_URL/smart/fetch.git" repo 2>err && -+ test_grep "error: bundle-uri: URI is malformed: " err && -+ find busted -type f >files && -+ test_must_be_empty files -+' -+ -+test_expect_success 'bundles with newline in URI are rejected' ' -+ test_when_finished "rm -rf busted repo" && -+ git clone --bundle-uri="$HTTPD_URL/bogus\nget $HTTPD_URL/bogus $HOME/busted" "$HTTPD_URL/smart/fetch.git" repo 2>err && -+ test_grep "error: bundle-uri: URI is malformed: " err && -+ test_path_is_missing "$HOME/busted" -+' -+ -+test_expect_success 'bundles with newline in target path are rejected' ' -+ git clone --bundle-uri="$HTTPD_URL/bogus" "$HTTPD_URL/smart/fetch.git" "$(printf "escape\nget $HTTPD_URL/bogus .")" 2>err && -+ test_grep "error: bundle-uri: filename is malformed: " err && -+ test_path_is_missing escape -+' -+ - # Do not add tests here unless they use the HTTP server, as they will - # not run unless the HTTP dependencies exist. - --- -2.33.0 - diff --git a/backport-CVE-2025-48386-wincred-avoid-buffer-overflow-in-wcsncat.patch b/backport-CVE-2025-48386-wincred-avoid-buffer-overflow-in-wcsncat.patch deleted file mode 100644 index bdd51a18035a6ea568f8926faae462544f6d5f0b..0000000000000000000000000000000000000000 --- a/backport-CVE-2025-48386-wincred-avoid-buffer-overflow-in-wcsncat.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 9de345cb273cc7faaeda279c7e07149d8a15a319 Mon Sep 17 00:00:00 2001 -From: Taylor Blau -Date: Mon, 19 May 2025 18:30:29 -0400 -Subject: [PATCH] wincred: avoid buffer overflow in wcsncat() - -The wincred credential helper uses a static buffer ("target") as a -unique key for storing and comparing against internal storage. It does -this by building up a string is supposed to look like: - - git:$PROTOCOL://$USERNAME@$HOST/@PATH - -However, the static "target" buffer is declared as a wide string with no -more than 1,024 wide characters. The first call to wcsncat() is almost -correct (it copies no more than ARRAY_SIZE(target) wchar_t's), but does -not account for the trailing NUL, introducing an off-by-one error. - -But subsequent calls to wcsncat() have an additional problem on top of -the off-by-one. They do not account for the length of the existing -wide string being built up in 'target'. So the following: - - $ perl -e ' - my $x = "x" x 1_000; - print "protocol=$x\nhost=$x\nusername=$x\npath=$x\n" - ' | - C\:/Program\ Files/Git/mingw64/libexec/git-core/git-credential-wincred.exe get - -will result in a segmentation fault from over-filling buffer. - -This bug is as old as the wincred helper itself, dating back to -a6253da0f3 (contrib: add win32 credential-helper, 2012-07-27). Commit -8b2d219a3d (wincred: improve compatibility with windows versions, -2013-01-10) replaced the use of strncat() with wcsncat(), but retained -the buggy behavior. - -Fix this by using a "target_append()" helper which accounts for both the -length of the existing string within the buffer, as well as the trailing -NUL character. - -Reported-by: David Leadbeater -Helped-by: David Leadbeater -Helped-by: Jeff King -Signed-off-by: Taylor Blau ---- - .../wincred/git-credential-wincred.c | 22 +++++++++++++------ - 1 file changed, 15 insertions(+), 7 deletions(-) - -diff --git a/contrib/credential/wincred/git-credential-wincred.c b/contrib/credential/wincred/git-credential-wincred.c -index 4cd56c42e2..ceff44207a 100644 ---- a/contrib/credential/wincred/git-credential-wincred.c -+++ b/contrib/credential/wincred/git-credential-wincred.c -@@ -37,6 +37,14 @@ static void *xmalloc(size_t size) - static WCHAR *wusername, *password, *protocol, *host, *path, target[1024], - *password_expiry_utc, *oauth_refresh_token; - -+static void target_append(const WCHAR *src) -+{ -+ size_t avail = ARRAY_SIZE(target) - wcslen(target) - 1; /* -1 for NUL */ -+ if (avail < wcslen(src)) -+ die("target buffer overflow"); -+ wcsncat(target, src, avail); -+} -+ - static void write_item(const char *what, LPCWSTR wbuf, int wlen) - { - char *buf; -@@ -294,17 +302,17 @@ int main(int argc, char *argv[]) - - /* prepare 'target', the unique key for the credential */ - wcscpy(target, L"git:"); -- wcsncat(target, protocol, ARRAY_SIZE(target)); -- wcsncat(target, L"://", ARRAY_SIZE(target)); -+ target_append(protocol); -+ target_append(L"://"); - if (wusername) { -- wcsncat(target, wusername, ARRAY_SIZE(target)); -- wcsncat(target, L"@", ARRAY_SIZE(target)); -+ target_append(wusername); -+ target_append(L"@"); - } - if (host) -- wcsncat(target, host, ARRAY_SIZE(target)); -+ target_append(host); - if (path) { -- wcsncat(target, L"/", ARRAY_SIZE(target)); -- wcsncat(target, path, ARRAY_SIZE(target)); -+ target_append(L"/"); -+ target_append(path); - } - - if (!strcmp(argv[1], "get")) --- -2.33.0 - diff --git a/git-2.50.0.tar.xz b/git-2.50.1.tar.xz similarity index 32% rename from git-2.50.0.tar.xz rename to git-2.50.1.tar.xz index 2590a91ab166068dc4ca9af1722b312b9b7c0bac..607b6268e1877c48b1d89c5170a21fed9a6e00b3 100644 --- a/git-2.50.0.tar.xz +++ b/git-2.50.1.tar.xz @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dff3c000e400ace3a63b8a6f8b3b76b88ecfdffd4504a04aba4248372cdec045 -size 7878256 +oid sha256:7e3e6c36decbd8f1eedd14d42db6674be03671c2204864befa2a41756c5c8fc4 +size 7880972 diff --git a/git.spec b/git.spec index 38bae4422c3b8e46b8ab038baa9d0390bbd1958f..f5b7b82be82dc5e0918461478201aacbe5ad55ec 100644 --- a/git.spec +++ b/git.spec @@ -1,7 +1,7 @@ %global gitexecdir %{_libexecdir}/git-core Name: git -Version: 2.50.0 -Release: 2 +Version: 2.50.1 +Release: 1 Summary: A popular and widely used Version Control System License: BSD-3-Clause AND GPL-2.0-only AND GPL-2.0-or-later AND LGPL-2.1-or-later AND MIT URL: https://git-scm.com/ @@ -12,9 +12,6 @@ Source101: git@.service.in Source102: git.socket Patch0: backport-CVE-2024-52005.patch -Patch1: backport-CVE-2025-48384-config-quote-values-containing-CR-character.patch -Patch2: backport-CVE-2025-48385-bundle-uri-fix-arbitrary-file-writes-via-parameter-i.patch -Patch3: backport-CVE-2025-48386-wincred-avoid-buffer-overflow-in-wcsncat.patch BuildRequires: gcc gettext BuildRequires: openssl-devel libcurl-devel expat-devel systemd asciidoc xmlto glib2-devel libsecret-devel pcre2-devel desktop-file-utils @@ -288,6 +285,9 @@ grep -E "$not_core_re" bin-man-doc-files > git-bin-files %{_mandir}/man7/git*.7.* %changelog +* Thu Jul 10 2025 Funda Wang - 2.50.1-1 +- update to 2.50.1 + * Wed Jul 9 2025 fuanan - 2.50.0-2 - Fix CVE-2025-48384 CVE-2025-48385 CVE-2025-48386