Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package git-lfs for openSUSE:Factory checked in at 2025-01-15 17:45:02 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/git-lfs (Old) and /work/SRC/openSUSE:Factory/.git-lfs.new.1881 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "git-lfs" Wed Jan 15 17:45:02 2025 rev:18 rq:1238007 version:3.6.1 Changes: -------- --- /work/SRC/openSUSE:Factory/git-lfs/git-lfs.changes 2024-11-22 23:54:04.643778418 +0100 +++ /work/SRC/openSUSE:Factory/.git-lfs.new.1881/git-lfs.changes 2025-01-15 17:45:06.069404993 +0100 @@ -1,0 +2,23 @@ +Wed Jan 15 07:00:27 UTC 2025 - Johannes Kastl <[email protected]> + +- update to 3.6.0: (boo#1235876) + This release introduces a security fix for all platforms, which + has been assigned CVE-2024-53263. + When requesting credentials from Git for a remote host, prior + versions of Git LFS passed portions of the host's URL to the + git-credential(1) command without checking for embedded + line-ending control characters, and then sent any credentials + received back from the Git credential helper to the remote host. + By inserting URL-encoded control characters such as line feed + (LF) or carriage return (CR) characters into the URL, an attacker + might have been able to retrieve a user's Git credentials. + Git LFS now prevents bare line feed (LF) characters from being + included in the values sent to the git-credential(1) command, and + also prevents bare carriage return (CR) characters from being + included unless the credential.protectProtocol configuration + option is set to a value equivalent to false. + * Bugs + - Reject bare line-ending control characters in Git credential + requests (@chrisd8088) + +------------------------------------------------------------------- Old: ---- git-lfs-3.6.0.obscpio New: ---- git-lfs-3.6.1.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ git-lfs.spec ++++++ --- /var/tmp/diff_new_pack.veEphz/_old 2025-01-15 17:45:09.249536506 +0100 +++ /var/tmp/diff_new_pack.veEphz/_new 2025-01-15 17:45:09.257536836 +0100 @@ -1,7 +1,7 @@ # # spec file for package git-lfs # -# Copyright (c) 2024 SUSE LLC +# Copyright (c) 2025 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -22,7 +22,7 @@ %bcond_without build_docs Name: git-lfs -Version: 3.6.0 +Version: 3.6.1 Release: 0 Summary: Git extension for versioning large files License: MIT ++++++ _service ++++++ --- /var/tmp/diff_new_pack.veEphz/_old 2025-01-15 17:45:09.477545935 +0100 +++ /var/tmp/diff_new_pack.veEphz/_new 2025-01-15 17:45:09.505547092 +0100 @@ -3,7 +3,7 @@ <param name="url">https://github.com/git-lfs/git-lfs</param> <param name="scm">git</param> <param name="exclude">.git</param> - <param name="revision">v3.6.0</param> + <param name="revision">v3.6.1</param> <param name="versionformat">@PARENT_TAG@</param> <param name="changesgenerate">disable</param> <param name="versionrewrite-pattern">v(.*)</param> ++++++ git-lfs-3.6.0.obscpio -> git-lfs-3.6.1.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/git-lfs-3.6.0/CHANGELOG.md new/git-lfs-3.6.1/CHANGELOG.md --- old/git-lfs-3.6.0/CHANGELOG.md 2024-11-21 00:04:33.000000000 +0100 +++ new/git-lfs-3.6.1/CHANGELOG.md 2024-12-04 01:24:27.000000000 +0100 @@ -1,5 +1,43 @@ # Git LFS Changelog +## 3.6.1 (3 December 2024) + +This release introduces a security fix for Linux, macOS, and Windows +systems, which has been assigned CVE-2024-53263. + +When Git LFS requests credentials from Git for a remote host, it passes +portions of the host's URL to the `git-credential(1)` command without +checking for embedded line-ending control characters, and then sends any +credentials it receives back from the Git credential helper to the +remote host. By inserting URL-encoded control characters such as +line feed (LF) or carriage return (CR) characters into the URL, an +attacker may be able to retrieve a user's Git credentials. + +By default Git LFS will now report an error if a line-ending control +character (LF or CR) or a null byte (NUL) is found in any value Git LFS +would otherwise pass to the `git-credential(1)` command. + +For users who depend on the ability to pass bare carriage return +characters in a Git credential request, Git LFS will now honour the +`credential.protectProtocol` Git configuration option. If this option +is set to `false`, Git LFS will allow carriage return characters in the +values it sends to the `git-credential(1)` command. This option will be +introduced in Git as part of the remedy for the vulnerability in Git +designated as CVE-2024-52006. + +Git LFS v3.6.1 will be released in coordination with releases from +several other projects including Git, Git for Windows, and Git Credential +Manager (GCM). + +We would like to extend a special thanks to the following open-source +contributors: + +* @Ry0taK for reporting this to us responsibly + +### Bugs + +* Reject bare line-ending control characters in Git credential requests (@chrisd8088) + ## 3.6.0 (20 November 2024) This release is a feature release which includes support for multi-stage diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/git-lfs-3.6.0/config/version.go new/git-lfs-3.6.1/config/version.go --- old/git-lfs-3.6.0/config/version.go 2024-11-21 00:04:33.000000000 +0100 +++ new/git-lfs-3.6.1/config/version.go 2024-12-04 01:24:27.000000000 +0100 @@ -13,7 +13,7 @@ ) const ( - Version = "3.6.0" + Version = "3.6.1" ) func init() { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/git-lfs-3.6.0/creds/creds.go new/git-lfs-3.6.1/creds/creds.go --- old/git-lfs-3.6.0/creds/creds.go 2024-11-21 00:04:33.000000000 +0100 +++ new/git-lfs-3.6.1/creds/creds.go 2024-12-04 01:24:27.000000000 +0100 @@ -58,13 +58,23 @@ return slices.Contains([]string{"1", "true"}, FirstEntryForKey(c, "continue")) } -func bufferCreds(c Creds) *bytes.Buffer { +func (c Creds) buffer(protectProtocol bool) (*bytes.Buffer, error) { buf := new(bytes.Buffer) buf.Write([]byte("capability[]=authtype\n")) buf.Write([]byte("capability[]=state\n")) for k, v := range c { for _, item := range v { + if strings.Contains(item, "\n") { + return nil, errors.Errorf(tr.Tr.Get("credential value for %s contains newline: %q", k, item)) + } + if protectProtocol && strings.Contains(item, "\r") { + return nil, errors.Errorf(tr.Tr.Get("credential value for %s contains carriage return: %q\nIf this is intended, set `credential.protectProtocol=false`", k, item)) + } + if strings.Contains(item, string(rune(0))) { + return nil, errors.Errorf(tr.Tr.Get("credential value for %s contains null byte: %q", k, item)) + } + buf.Write([]byte(k)) buf.Write([]byte("=")) buf.Write([]byte(item)) @@ -72,7 +82,7 @@ } } - return buf + return buf, nil } type CredentialHelperContext struct { @@ -168,6 +178,9 @@ helpers = append(helpers, ctxt.askpassCredHelper) } } + + ctxt.commandCredHelper.protectProtocol = ctxt.urlConfig.Bool("credential", rawurl, "protectProtocol", true) + return CredentialHelperWrapper{CredentialHelper: NewCredentialHelpers(append(helpers, ctxt.commandCredHelper)), Input: input, Url: u} } @@ -307,7 +320,8 @@ } type commandCredentialHelper struct { - SkipPrompt bool + SkipPrompt bool + protectProtocol bool } func (h *commandCredentialHelper) Fill(creds Creds) (Creds, error) { @@ -338,7 +352,10 @@ if err != nil { return nil, errors.New(tr.Tr.Get("failed to find `git credential %s`: %v", subcommand, err)) } - cmd.Stdin = bufferCreds(input) + cmd.Stdin, err = input.buffer(h.protectProtocol) + if err != nil { + return nil, errors.New(tr.Tr.Get("invalid input to `git credential %s`: %v", subcommand, err)) + } cmd.Stdout = output /* There is a reason we don't read from stderr here: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/git-lfs-3.6.0/creds/creds_test.go new/git-lfs-3.6.1/creds/creds_test.go --- old/git-lfs-3.6.0/creds/creds_test.go 2024-11-21 00:04:33.000000000 +0100 +++ new/git-lfs-3.6.1/creds/creds_test.go 2024-12-04 01:24:27.000000000 +0100 @@ -1,12 +1,101 @@ package creds import ( + "bytes" "errors" + "slices" + "strings" "testing" "github.com/stretchr/testify/assert" ) +func assertCredsLinesMatch(t *testing.T, expected []string, buf *bytes.Buffer) { + expected = append(expected, "") + actual := strings.SplitAfter(buf.String(), "\n") + + slices.Sort(expected) + slices.Sort(actual) + + assert.Equal(t, expected, actual) +} + +func TestCredsBufferFormat(t *testing.T) { + creds := make(Creds) + + expected := []string{"capability[]=authtype\n", "capability[]=state\n"} + + buf, err := creds.buffer(true) + assert.NoError(t, err) + assertCredsLinesMatch(t, expected, buf) + + creds["protocol"] = []string{"https"} + creds["host"] = []string{"example.com"} + + expectedPrefix := strings.Join(expected, "") + expected = append(expected, "protocol=https\n", "host=example.com\n") + + buf, err = creds.buffer(true) + assert.NoError(t, err) + assert.True(t, strings.HasPrefix(buf.String(), expectedPrefix)) + assertCredsLinesMatch(t, expected, buf) + + creds["wwwauth[]"] = []string{"Basic realm=test", "Negotiate"} + + expected = append(expected, "wwwauth[]=Basic realm=test\n") + expected = append(expected, "wwwauth[]=Negotiate\n") + + buf, err = creds.buffer(true) + assert.NoError(t, err) + assert.True(t, strings.HasPrefix(buf.String(), expectedPrefix)) + assertCredsLinesMatch(t, expected, buf) +} + +func TestCredsBufferProtect(t *testing.T) { + creds := make(Creds) + + // Always disallow LF characters + creds["protocol"] = []string{"https"} + creds["host"] = []string{"one.example.com\nhost=two.example.com"} + + buf, err := creds.buffer(false) + assert.Error(t, err) + assert.Nil(t, buf) + + buf, err = creds.buffer(true) + assert.Error(t, err) + assert.Nil(t, buf) + + // Disallow CR characters unless protocol protection disabled + creds["host"] = []string{"one.example.com\rhost=two.example.com"} + + expected := []string{ + "capability[]=authtype\n", + "capability[]=state\n", + "protocol=https\n", + "host=one.example.com\rhost=two.example.com\n", + } + + buf, err = creds.buffer(false) + assert.NoError(t, err) + assertCredsLinesMatch(t, expected, buf) + + buf, err = creds.buffer(true) + assert.Error(t, err) + assert.Nil(t, buf) + + // Always disallow null bytes + creds["host"] = []string{"one.example.com\x00host=two.example.com"} + + buf, err = creds.buffer(false) + assert.Error(t, err) + assert.Nil(t, buf) + + buf, err = creds.buffer(true) + assert.Error(t, err) + assert.Nil(t, buf) +} + type testCredHelper struct { fillErr error approveErr error diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/git-lfs-3.6.0/debian/changelog new/git-lfs-3.6.1/debian/changelog --- old/git-lfs-3.6.0/debian/changelog 2024-11-21 00:04:33.000000000 +0100 +++ new/git-lfs-3.6.1/debian/changelog 2024-12-04 01:24:27.000000000 +0100 @@ -1,3 +1,9 @@ +git-lfs (3.6.1) stable; urgency=low + + * New upstream version + + -- Chris Darroch <[email protected]> Tue, 03 Dec 2024 14:29:00 -0000 + git-lfs (3.6.0) stable; urgency=low * New upstream version diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/git-lfs-3.6.0/rpm/SPECS/git-lfs.spec new/git-lfs-3.6.1/rpm/SPECS/git-lfs.spec --- old/git-lfs-3.6.0/rpm/SPECS/git-lfs.spec 2024-11-21 00:04:33.000000000 +0100 +++ new/git-lfs-3.6.1/rpm/SPECS/git-lfs.spec 2024-12-04 01:24:27.000000000 +0100 @@ -1,5 +1,5 @@ Name: git-lfs -Version: 3.6.0 +Version: 3.6.1 Release: 1%{?dist} Summary: Git extension for versioning large files diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/git-lfs-3.6.0/t/cmd/lfstest-gitserver.go new/git-lfs-3.6.1/t/cmd/lfstest-gitserver.go --- old/git-lfs-3.6.0/t/cmd/lfstest-gitserver.go 2024-11-21 00:04:33.000000000 +0100 +++ new/git-lfs-3.6.1/t/cmd/lfstest-gitserver.go 2024-12-04 01:24:27.000000000 +0100 @@ -26,6 +26,7 @@ "net/http" "net/http/httptest" "net/textproto" + "net/url" "os" "os/exec" "regexp" @@ -257,6 +258,7 @@ } func lfsUrl(repo, oid string, redirect bool) string { + repo = url.QueryEscape(repo) if redirect { return server.URL + "/redirect307/objects/" + oid + "?r=" + repo } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/git-lfs-3.6.0/t/t-credentials-protect.sh new/git-lfs-3.6.1/t/t-credentials-protect.sh --- old/git-lfs-3.6.0/t/t-credentials-protect.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/git-lfs-3.6.1/t/t-credentials-protect.sh 2024-12-04 01:24:27.000000000 +0100 @@ -0,0 +1,146 @@ +#!/usr/bin/env bash + +. "$(dirname "$0")/testlib.sh" + +ensure_git_version_isnt $VERSION_LOWER "2.3.0" + +export CREDSDIR="$REMOTEDIR/creds-credentials-protect" +setup_creds + +# Copy the default record file for the test credential helper to match the +# hostname used in the Git LFS configurations of the tests. +cp "$CREDSDIR/127.0.0.1" "$CREDSDIR/localhost" + +begin_test "credentials rejected with line feed" +( + set -e + + reponame="protect-linefeed" + setup_remote_repo "$reponame" + clone_repo "$reponame" "$reponame" + + contents="a" + contents_oid=$(calc_oid "$contents") + + git lfs track "*.dat" + printf "%s" "$contents" >a.dat + git add .gitattributes a.dat + git commit -m "add a.dat" + + # Using localhost instead of 127.0.0.1 in the LFS API URL ensures this URL + # is used when filling credentials rather than the Git remote URL, which + # would otherwise be used since it would have the same scheme and hostname. + gitserver="$(echo "$GITSERVER" | sed 's/127\.0\.0\.1/localhost/')" + testreponame="test%0a$reponame" + git config lfs.url "$gitserver/$testreponame.git/info/lfs" + + GIT_TRACE=1 git lfs push origin main 2>&1 | tee push.log + if [ "0" -eq "${PIPESTATUS[0]}" ]; then + echo >&2 "fatal: expected 'git lfs push' to fail ..." + exit 1 + fi + grep "batch response: Git credentials for $gitserver.* not found" push.log + grep "credential value for path contains newline" push.log + refute_server_object "$testreponame" "$contents_oid" + + git config credential.protectProtocol false + + GIT_TRACE=1 git lfs push origin main 2>&1 | tee push.log + if [ "0" -eq "${PIPESTATUS[0]}" ]; then + echo >&2 "fatal: expected 'git lfs push' to fail ..." + exit 1 + fi + grep "batch response: Git credentials for $gitserver.* not found" push.log + grep "credential value for path contains newline" push.log + refute_server_object "$testreponame" "$contents_oid" +) +end_test + +begin_test "credentials rejected with carriage return" +( + set -e + + reponame="protect-return" + setup_remote_repo "$reponame" + clone_repo "$reponame" "$reponame" + + contents="a" + contents_oid=$(calc_oid "$contents") + + git lfs track "*.dat" + printf "%s" "$contents" >a.dat + git add .gitattributes a.dat + git commit -m "add a.dat" + + # Using localhost instead of 127.0.0.1 in the LFS API URL ensures this URL + # is used when filling credentials rather than the Git remote URL, which + # would otherwise be used since it would have the same scheme and hostname. + gitserver="$(echo "$GITSERVER" | sed 's/127\.0\.0\.1/localhost/')" + testreponame="test%0d$reponame" + git config lfs.url "$gitserver/$testreponame.git/info/lfs" + + GIT_TRACE=1 git lfs push origin main 2>&1 | tee push.log + if [ "0" -eq "${PIPESTATUS[0]}" ]; then + echo >&2 "fatal: expected 'git lfs push' to fail ..." + exit 1 + fi + grep "batch response: Git credentials for $gitserver.* not found" push.log + grep "credential value for path contains carriage return" push.log + refute_server_object "$testreponame" "$contents_oid" + + git config credential.protectProtocol false + + git lfs push origin main 2>&1 | tee push.log + if [ "0" -ne "${PIPESTATUS[0]}" ]; then + echo >&2 "fatal: expected 'git lfs push' to succeed ..." + exit 1 + fi + [ $(grep -c "Uploading LFS objects: 100% (1/1)" push.log) -eq 1 ] + assert_server_object "$testreponame" "$contents_oid" +) +end_test + +begin_test "credentials rejected with null byte" +( + set -e + + reponame="protect-null" + setup_remote_repo "$reponame" + clone_repo "$reponame" "$reponame" + + contents="a" + contents_oid=$(calc_oid "$contents") + + git lfs track "*.dat" + printf "%s" "$contents" >a.dat + git add .gitattributes a.dat + git commit -m "add a.dat" + + # Using localhost instead of 127.0.0.1 in the LFS API URL ensures this URL + # is used when filling credentials rather than the Git remote URL, which + # would otherwise be used since it would have the same scheme and hostname. + gitserver="$(echo "$GITSERVER" | sed 's/127\.0\.0\.1/localhost/')" + testreponame="test%00$reponame" + git config lfs.url "$gitserver/$testreponame.git/info/lfs" + + GIT_TRACE=1 git lfs push origin main 2>&1 | tee push.log + if [ "0" -eq "${PIPESTATUS[0]}" ]; then + echo >&2 "fatal: expected 'git lfs push' to fail ..." + exit 1 + fi + grep "batch response: Git credentials for $gitserver.* not found" push.log + grep "credential value for path contains null byte" push.log + refute_server_object "$testreponame" "$contents_oid" + + git config credential.protectProtocol false + + GIT_TRACE=1 git lfs push origin main 2>&1 | tee push.log + if [ "0" -eq "${PIPESTATUS[0]}" ]; then + echo >&2 "fatal: expected 'git lfs push' to fail ..." + exit 1 + fi + grep "batch response: Git credentials for $gitserver.* not found" push.log + grep "credential value for path contains null byte" push.log + refute_server_object "$testreponame" "$contents_oid" +) +end_test diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/git-lfs-3.6.0/versioninfo.json new/git-lfs-3.6.1/versioninfo.json --- old/git-lfs-3.6.0/versioninfo.json 2024-11-21 00:04:33.000000000 +0100 +++ new/git-lfs-3.6.1/versioninfo.json 2024-12-04 01:24:27.000000000 +0100 @@ -4,7 +4,7 @@ "FileVersion": { "Major": 3, "Minor": 6, - "Patch": 0, + "Patch": 1, "Build": 0 } }, @@ -13,7 +13,7 @@ "FileDescription": "Git LFS", "LegalCopyright": "GitHub, Inc. and Git LFS contributors", "ProductName": "Git Large File Storage (LFS)", - "ProductVersion": "3.6.0" + "ProductVersion": "3.6.1" }, "IconPath": "script/windows-installer/git-lfs-logo.ico" } ++++++ git-lfs.obsinfo ++++++ --- /var/tmp/diff_new_pack.veEphz/_old 2025-01-15 17:45:10.569591095 +0100 +++ /var/tmp/diff_new_pack.veEphz/_new 2025-01-15 17:45:10.601592419 +0100 @@ -1,5 +1,5 @@ name: git-lfs -version: 3.6.0 -mtime: 1732143873 -commit: 6340befc60876f4f039f215479d9d5a945f817e1 +version: 3.6.1 +mtime: 1733271867 +commit: ea47a34bde1ba1ecf9eb8dc6d44fcf7aef42f5e3 ++++++ vendor.tar.xz ++++++
