ghsa-86c2-4x57-wc8g
Vulnerability from github
Description
The Git credential protocol is text-based over standard input/output, and consists of a series of lines of key-value pairs in the format key=value
. Git's documentation restricts the use of the NUL (\0
) character and newlines to form part of the keys[^1] or values.
When Git reads from standard input, it considers both LF and CRLF[^2] as newline characters for the credential protocol by virtue of calling strbuf_getline
that calls to strbuf_getdelim_strip_crlf
. Git also validates that a newline is not present in the value by checking for the presence of the line-feed character (LF, \n
), and errors if this is the case. This captures both LF and CRLF-type newlines.
Git Credential Manager uses the .NET standard library StreamReader
class to read the standard input stream line-by-line and parse the key=value
credential protocol format. The implementation of the ReadLineAsync
method considers LF, CRLF, and CR as valid line endings. This is means that .NET considers a single CR as a valid newline character, whereas Git does not.
This mismatch of newline treatment between Git and GCM means that an attacker can craft a malicious remote URL such as:
https://\rhost=targethost@badhost
..which will be interpreted by Git as:
protocol=https
host=badhost
username=\rhost=targethost
This will instead be parsed by GCM as if the following has been passed by Git:
protocol=https
host=badhost
username=
host=targethost
This results in the host
field being resolved to the targethost
value. GCM will then return a credential for targethost
to Git, which will then send this credential to the badhost
host.
Impact
When a user clones or otherwise interacts[^3] with a malicious repository that requires authentication, the attacker can capture credentials for another Git remote. The attack is also heightened when cloning from repositories with submodules when using the --recursive
clone option as the user is not able to inspect the submodule remote URLs beforehand.
Patches
https://github.com/git-ecosystem/git-credential-manager/compare/749e287571c78a2b61f926ccce6a707050871ab8...99e2f7f60e7364fe807e7925f361a81f3c47bd1b
Workarounds
Only interacting with trusted remote repositories, and do not clone with --recursive
to allow inspection of any submodule URLs before cloning those submodules.
Fixed versions
This issue is fixed as of version 2.6.1.
[^1]: The =
character is also forbidden to form part of the key.
[^2]: Carriage-return character (CR, \r
), followed by a line-feed character.
[^3]: Any remote operation such as fetch
, ls-remote
, etc.
{ "affected": [ { "database_specific": { "last_known_affected_version_range": "\u003c= 2.6.0" }, "package": { "ecosystem": "NuGet", "name": "git-credential-manager" }, "ranges": [ { "events": [ { "introduced": "0" }, { "fixed": "2.6.1" } ], "type": "ECOSYSTEM" } ] } ], "aliases": [ "CVE-2024-50338" ], "database_specific": { "cwe_ids": [ "CWE-200", "CWE-436" ], "github_reviewed": true, "github_reviewed_at": "2025-01-14T19:40:54Z", "nvd_published_at": "2025-01-14T19:15:31Z", "severity": "HIGH" }, "details": "### Description\nThe [Git credential protocol](https://git-scm.com/docs/git-credential#IOFMT) is text-based over standard input/output, and consists of a series of lines of key-value pairs in the format `key=value`. Git\u0027s documentation restricts the use of the NUL (`\\0`) character and newlines to form part of the keys[^1] or values.\n\nWhen Git reads from standard input, it considers both LF and CRLF[^2] as newline characters for the credential protocol by virtue of [calling `strbuf_getline`](https://github.com/git/git/blob/6a11438f43469f3815f2f0fc997bd45792ff04c0/credential.c#L311) that calls to `strbuf_getdelim_strip_crlf`. Git also validates that a newline is not present in the value by checking for the presence of the line-feed character (LF, `\\n`), and errors if this is the case. This captures both LF and CRLF-type newlines.\n\nGit Credential Manager uses the .NET standard library [`StreamReader`](https://learn.microsoft.com/en-us/dotnet/api/system.io.streamreader?view=net-8.0) class to [read the standard input stream line-by-line](https://github.com/git-ecosystem/git-credential-manager/blob/ae009e11a0fbef804ad9f78816d84a0bc7e052fe/src/shared/Core/StreamExtensions.cs#L138-L141) and parse the `key=value` credential protocol format. The [implementation of the `ReadLineAsync` method](https://github.com/dotnet/runtime/blob/e476b43b5cb42eb44ce23b1c7b793aa361624cf6/src/libraries/System.Private.CoreLib/src/System/IO/StreamReader.cs#L926) considers LF, CRLF, and CR as valid line endings. This is means that .NET considers a single CR as a valid newline character, whereas Git does not.\n\nThis mismatch of newline treatment between Git and GCM means that an attacker can craft a malicious remote URL such as:\n\n```\nhttps://\\rhost=targethost@badhost\n```\n\n..which will be interpreted by Git as:\n\n```\nprotocol=https\nhost=badhost\nusername=\\rhost=targethost\n```\n\nThis will instead be parsed by GCM as if the following has been passed by Git:\n\n```\nprotocol=https\nhost=badhost\nusername=\nhost=targethost\n```\n\nThis results in the `host` field being resolved to the `targethost` value. GCM will then return a credential for `targethost` to Git, which will then send this credential to the `badhost` host.\n\n### Impact\nWhen a user clones or otherwise interacts[^3] with a malicious repository that requires authentication, the attacker can capture credentials for another Git remote. The attack is also heightened when cloning from repositories with submodules when using the `--recursive` clone option as the user is not able to inspect the submodule remote URLs beforehand.\n\n### Patches\nhttps://github.com/git-ecosystem/git-credential-manager/compare/749e287571c78a2b61f926ccce6a707050871ab8...99e2f7f60e7364fe807e7925f361a81f3c47bd1b\n\n### Workarounds\nOnly interacting with trusted remote repositories, and do not clone with `--recursive` to allow inspection of any submodule URLs before cloning those submodules.\n\n### Fixed versions\nThis issue is fixed as of [version 2.6.1](https://github.com/git-ecosystem/git-credential-manager/releases/tag/v2.6.1).\n\n[^1]: The `=` character is also forbidden to form part of the key.\n[^2]: Carriage-return character (CR, `\\r`), followed by a line-feed character.\n[^3]: Any remote operation such as `fetch`, `ls-remote`, etc.", "id": "GHSA-86c2-4x57-wc8g", "modified": "2025-01-14T21:59:51Z", "published": "2025-01-14T19:40:54Z", "references": [ { "type": "WEB", "url": "https://github.com/git-ecosystem/git-credential-manager/security/advisories/GHSA-86c2-4x57-wc8g" }, { "type": "ADVISORY", "url": "https://nvd.nist.gov/vuln/detail/CVE-2024-50338" }, { "type": "WEB", "url": "https://git-scm.com/docs/git-credential#IOFMT" }, { "type": "WEB", "url": "https://github.com/dotnet/runtime/blob/e476b43b5cb42eb44ce23b1c7b793aa361624cf6/src/libraries/System.Private.CoreLib/src/System/IO/StreamReader.cs#L926" }, { "type": "PACKAGE", "url": "https://github.com/git-ecosystem/git-credential-manager" }, { "type": "WEB", "url": "https://github.com/git-ecosystem/git-credential-manager/blob/ae009e11a0fbef804ad9f78816d84a0bc7e052fe/src/shared/Core/StreamExtensions.cs#L138-L141" }, { "type": "WEB", "url": "https://github.com/git-ecosystem/git-credential-manager/compare/749e287571c78a2b61f926ccce6a707050871ab8...99e2f7f60e7364fe807e7925f361a81f3c47bd1b" }, { "type": "WEB", "url": "https://github.com/git-ecosystem/git-credential-manager/releases/tag/v2.6.1" }, { "type": "WEB", "url": "https://github.com/git/git/blob/6a11438f43469f3815f2f0fc997bd45792ff04c0/credential.c#L311" }, { "type": "WEB", "url": "https://learn.microsoft.com/en-us/dotnet/api/system.io.streamreader?view=net-8.0" } ], "schema_version": "1.4.0", "severity": [ { "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:N/A:N", "type": "CVSS_V3" } ], "summary": "Git Credential Manager carriage-return character in remote URL allows malicious repository to leak credentials" }
Sightings
Author | Source | Type | Date |
---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or seen somewhere by the user.
- Confirmed: The vulnerability is confirmed from an analyst perspective.
- Exploited: This vulnerability was exploited and seen by the user reporting the sighting.
- Patched: This vulnerability was successfully patched by the user reporting the sighting.
- Not exploited: This vulnerability was not exploited or seen by the user reporting the sighting.
- Not confirmed: The user expresses doubt about the veracity of the vulnerability.
- Not patched: This vulnerability was not successfully patched by the user reporting the sighting.