Version in base suite: 3.3.0-1 Base version: git-lfs_3.3.0-1 Target version: git-lfs_3.3.0-1+deb12u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/g/git-lfs/git-lfs_3.3.0-1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/g/git-lfs/git-lfs_3.3.0-1+deb12u1.dsc changelog | 8 patches/0002-CVE-2024-53263-reject-lf-in-creds.patch | 219 +++++++++++++++++++ patches/series | 1 3 files changed, 228 insertions(+) diff -Nru git-lfs-3.3.0/debian/changelog git-lfs-3.3.0/debian/changelog --- git-lfs-3.3.0/debian/changelog 2022-12-01 00:32:31.000000000 +0000 +++ git-lfs-3.3.0/debian/changelog 2025-01-21 09:54:02.000000000 +0000 @@ -1,3 +1,11 @@ +git-lfs (3.3.0-1+deb12u1) bookworm-security; urgency=high + + * Non-maintainer upload by the Security Team. + * Apply upstream patch to fix CVE-2024-53263: + - Reject LF bytes in credential data + + -- Andrej Shadura Tue, 21 Jan 2025 10:54:02 +0100 + git-lfs (3.3.0-1) unstable; urgency=medium * New upstream release diff -Nru git-lfs-3.3.0/debian/patches/0002-CVE-2024-53263-reject-lf-in-creds.patch git-lfs-3.3.0/debian/patches/0002-CVE-2024-53263-reject-lf-in-creds.patch --- git-lfs-3.3.0/debian/patches/0002-CVE-2024-53263-reject-lf-in-creds.patch 1970-01-01 00:00:00.000000000 +0000 +++ git-lfs-3.3.0/debian/patches/0002-CVE-2024-53263-reject-lf-in-creds.patch 2025-01-21 09:50:53.000000000 +0000 @@ -0,0 +1,219 @@ +From: Chris Darroch +Date: Tue, 26 Nov 2024 21:25:21 -0800 +Subject: creds/creds.go: reject LF bytes in credential data + +As reported in CVE-2024-53263, when Git LFS writes credential request +keys and values to a Git credential helper via the git-credential(1) +command, it does not remove any line feed (LF) control characters +included in the values, which may allow a malicious server to insert +spurious keys and values into the credential request. + +Because the "git credential fill" command receives these values as its +input, it is not able to disambiguate the line feed characters we add +at the end of each input line from those which are the result of +decoding URL-encoded characters. + +When Git processes a URL and passes values from that URL to a credential +helper, any line feed characters which have been decoded are detected by +a check in the credential_write_item() function of the credential.c +source file and cause Git to exit with an error. This check was added +in commit git/git@9a6bbee8006c24b46a85d29e7b38cfa79e9ab21b and released +in Git version 2.17.4 (and other patch releases) to address the +vulnerability reported in CVE-2020-5260: + + https://github.com/git/git/blob/v2.47.1/credential.c#L391-L392 + +Given that the Git security issue in CVE-2020-5260 has the same cause +and effect as the one reported for Git LFS in CVE-2024-53263, we adopt +the same approach as Git to resolve the latter issue now. To do this +we revise the buffer() method of the Creds structure in our "creds" +package (which we refactored from a bufferCreds() function in a prior +commit in this PR) so it returns an error if any of the values it +processes have an embedded line feed character. We then alter the sole +caller of this method, the exec() method of our commandCredentialHelper +structure in the same package, to detect and return any error from the +buffer() method. + +To verify these changes we add a TestCredsBufferProtect() test function, +which checks that the buffer() method returns an error when one of the +values it is given contains a line feed character. + +We also create a new t/t-credentials-protect.sh test script with one +initial test named "credentials rejected with line feed". This test +confirms that an error is reported and no Git LFS object is pushed if a +value which would be passed to a "git credential fill" command contains +a bare line feed character decoded from a URL-encoded line feed character +found in a URL. + +We use the "localhost" hostname in this URL rather than the 127.0.0.1 +address on which our lfstest-gitserver utility listens for requests +because otherwise Git LFS will detect that the scheme and the host +subcomponent of the URL for the Git LFS API match those of the URL of +the current Git remote, and will then use the Git remote's URL when +querying for credentials. As that URL does not contain a URL-encoded +line feed character, our test would not achieve its purpose, so we +instead use the "localhost" alias in the test's Git LFS configuration. + +As this test makes use of the "localhost" hostname, we provide a +credential record file associated with that hostname for our +git-credential-lfstest helper to find and use. To establish this file +we copy the record file associated with the 127.0.0.1 address, as +that file has already been created by the setup_creds() function from +our t/testhelpers.sh library. + +This test does not actually depend on the existence of a credential +record file for the "localhost" hostname, as we expect the credential +helper to never be consulted due to the presence of a line feed character +in the values that would be sent to it. However, we expect to add +another test to our new test script in a subsequent commit in this PR, +and that test will depend on the credential helper finding a record file +for the "localhost" hostname. + +The presence of the record file also ensures that if in the future a +regression should be introduced such that values containing a bare +line feed character are passed to the credential helper, our test would +not continue to pass. If we did not establish a record file, and a +regression caused the bare line feed character to be ignored, the +"git lfs push" command would still fail because it would not find +credentials for the "localhost" hostname, and so no object would be +pushed, as the test expects, and thus the test would continue to pass. + +Instead, in the case of a regression we want the "git lfs push" command +to succeed, and then the subsequent call to the refute_server_object() +function to fail and cause the test to fail. We therefore create a +valid credential record file even though it is not used at present. + +Some of the tests in the existing t/t-credentials.sh test script depend +on a credential record file for the "localhost" hostname not existing, +though, which is why we define our new test in a new, separate test +script. We can then set a unique path for the CREDSDIR environment +variable in that script, which guarantees that any modifications the +script makes to the set of credential record files do not affect any +other script's tests. + +Reported-by: RyotaK from Flatt Security Inc. + +Origin: backport, https://github.com/git-lfs/git-lfs/commit/0345b6f816e611d050c0df67b61f0022916a1c90 +--- + creds/creds.go | 14 +++++++++++--- + creds/creds_test.go | 12 ++++++++++++ + t/t-credentials-protect.sh | 46 ++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 69 insertions(+), 3 deletions(-) + create mode 100755 t/t-credentials-protect.sh + +diff --git a/creds/creds.go b/creds/creds.go +index a4dd328..8395d2f 100644 +--- a/creds/creds.go ++++ b/creds/creds.go +@@ -53,17 +53,21 @@ func (credWrapper *CredentialHelperWrapper) FillCreds() error { + // as input. + type Creds map[string]string + +-func bufferCreds(c Creds) *bytes.Buffer { ++func bufferCreds(c Creds) (*bytes.Buffer, error) { + buf := new(bytes.Buffer) + + for k, v := range c { ++ if strings.Contains(v, "\n") { ++ return nil, errors.New(fmt.Sprintf("credential value for %s contains newline: %q", k, v)) ++ } ++ + buf.Write([]byte(k)) + buf.Write([]byte("=")) + buf.Write([]byte(v)) + buf.Write([]byte("\n")) + } + +- return buf ++ return buf, nil + } + + type CredentialHelperContext struct { +@@ -309,7 +313,11 @@ func (h *commandCredentialHelper) exec(subcommand string, input Creds) (Creds, e + 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 = bufferCreds(input) ++ if err != nil { ++ return nil, errors.New(fmt.Sprintf("invalid input to `git credential %s`: %v", subcommand, err)) ++ } + cmd.Stdout = output + /* + There is a reason we don't read from stderr here: +diff --git a/creds/creds_test.go b/creds/creds_test.go +index 92f0805..4696211 100644 +--- a/creds/creds_test.go ++++ b/creds/creds_test.go +@@ -7,6 +7,18 @@ import ( + "github.com/stretchr/testify/assert" + ) + ++func TestCredsBufferProtect(t *testing.T) { ++ creds := make(Creds) ++ ++ // Always disallow LF characters ++ creds["protocol"] = "https" ++ creds["host"] = "one.example.com\nhost=two.example.com" ++ ++ buf, err := bufferCreds(creds) ++ assert.Error(t, err) ++ assert.Nil(t, buf) ++} ++ + type testCredHelper struct { + fillErr error + approveErr error +diff --git a/t/t-credentials-protect.sh b/t/t-credentials-protect.sh +new file mode 100755 +index 0000000..89bbd87 +--- /dev/null ++++ b/t/t-credentials-protect.sh +@@ -0,0 +1,46 @@ ++#!/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" ++) ++end_test diff -Nru git-lfs-3.3.0/debian/patches/series git-lfs-3.3.0/debian/patches/series --- git-lfs-3.3.0/debian/patches/series 2021-10-15 07:18:48.000000000 +0000 +++ git-lfs-3.3.0/debian/patches/series 2025-01-21 09:50:53.000000000 +0000 @@ -0,0 +1 @@ +0002-CVE-2024-53263-reject-lf-in-creds.patch