From 7725b8100ffbbff2750ee4d61a0fcc1f53a086e8 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 30 Oct 2024 13:26:10 +0100 Subject: credential: sanitize the user prompt When asking the user interactively for credentials, we want to avoid misleading them e.g. via control sequences that pretend that the URL targets a trusted host when it does not. While Git learned, over the course of the preceding commits, to disallow URLs containing URL-encoded control characters by default, credential helpers are still allowed to specify values very freely (apart from Line Feed and NUL characters, anything is allowed), and this would allow, say, a username containing control characters to be specified that would then be displayed in the interactive terminal prompt asking the user for the password, potentially sending those control characters directly to the terminal. This is undesirable because control characters can be used to mislead users to divulge secret information to untrusted sites. To prevent such an attack vector, let's add a `git_prompt()` that forces the displayed text to be sanitized, i.e. displaying question marks instead of control characters. Note: While this commit's diff changes a lot of `user@host` strings to `user%40host`, which may look suspicious on the surface, there is a good reason for that: this string specifies a user name, not a @ combination! In the context of t5541, the actual combination looks like this: `user%40@127.0.0.1:5541`. Therefore, these string replacements document a net improvement introduced by this commit, as `user@host@127.0.0.1` could have left readers wondering where the user name ends and where the host name begins. Hinted-at-by: Jeff King Signed-off-by: Johannes Schindelin --- Documentation/config/credential.txt | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'Documentation') diff --git a/Documentation/config/credential.txt b/Documentation/config/credential.txt index 512f31876e..fd8113d6d4 100644 --- a/Documentation/config/credential.txt +++ b/Documentation/config/credential.txt @@ -14,6 +14,12 @@ credential.useHttpPath:: or https URL to be important. Defaults to false. See linkgit:gitcredentials[7] for more information. +credential.sanitizePrompt:: + By default, user names and hosts that are shown as part of the + password prompt are not allowed to contain control characters (they + will be URL-encoded by default). Configure this setting to `false` to + override that behavior. + credential.username:: If no username is set for a network authentication, use this username by default. See credential..* below, and -- cgit v1.2.3 From b01b9b81d36759cdcd07305e78765199e1bc2060 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Mon, 4 Nov 2024 14:48:22 +0100 Subject: credential: disallow Carriage Returns in the protocol by default While Git has documented that the credential protocol is line-based, with newlines as terminators, the exact shape of a newline has not been documented. From Git's perspective, which is firmly rooted in the Linux ecosystem, it is clear that "a newline" means a Line Feed character. However, even Git's credential protocol respects Windows line endings (a Carriage Return character followed by a Line Feed character, "CR/LF") by virtue of using `strbuf_getline()`. There is a third category of line endings that has been used originally by MacOS, and that is respected by the default line readers of .NET and node.js: bare Carriage Returns. Git cannot handle those, and what is worse: Git's remedy against CVE-2020-5260 does not catch when credential helpers are used that interpret bare Carriage Returns as newlines. Git Credential Manager addressed this as CVE-2024-50338, but other credential helpers may still be vulnerable. So let's not only disallow Line Feed characters as part of the values in the credential protocol, but also disallow Carriage Return characters. In the unlikely event that a credential helper relies on Carriage Returns in the protocol, introduce an escape hatch via the `credential.protectProtocol` config setting. This addresses CVE-2024-52006. Signed-off-by: Johannes Schindelin --- Documentation/config/credential.txt | 5 +++++ credential.c | 21 ++++++++++++++------- credential.h | 4 +++- t/t0300-credentials.sh | 16 ++++++++++++++++ 4 files changed, 38 insertions(+), 8 deletions(-) (limited to 'Documentation') diff --git a/Documentation/config/credential.txt b/Documentation/config/credential.txt index fd8113d6d4..9cadca7f73 100644 --- a/Documentation/config/credential.txt +++ b/Documentation/config/credential.txt @@ -20,6 +20,11 @@ credential.sanitizePrompt:: will be URL-encoded by default). Configure this setting to `false` to override that behavior. +credential.protectProtocol:: + By default, Carriage Return characters are not allowed in the protocol + that is used when Git talks to a credential helper. This setting allows + users to override this default. + credential.username:: If no username is set for a network authentication, use this username by default. See credential..* below, and diff --git a/credential.c b/credential.c index 1392a54d5c..b76a730901 100644 --- a/credential.c +++ b/credential.c @@ -69,6 +69,8 @@ static int credential_config_callback(const char *var, const char *value, c->use_http_path = git_config_bool(var, value); else if (!strcmp(key, "sanitizeprompt")) c->sanitize_prompt = git_config_bool(var, value); + else if (!strcmp(key, "protectprotocol")) + c->protect_protocol = git_config_bool(var, value); return 0; } @@ -262,7 +264,8 @@ int credential_read(struct credential *c, FILE *fp) return 0; } -static void credential_write_item(FILE *fp, const char *key, const char *value, +static void credential_write_item(const struct credential *c, + FILE *fp, const char *key, const char *value, int required) { if (!value && required) @@ -271,19 +274,23 @@ static void credential_write_item(FILE *fp, const char *key, const char *value, return; if (strchr(value, '\n')) die("credential value for %s contains newline", key); + if (c->protect_protocol && strchr(value, '\r')) + die("credential value for %s contains carriage return\n" + "If this is intended, set `credential.protectProtocol=false`", + key); fprintf(fp, "%s=%s\n", key, value); } void credential_write(const struct credential *c, FILE *fp) { - credential_write_item(fp, "protocol", c->protocol, 1); - credential_write_item(fp, "host", c->host, 1); - credential_write_item(fp, "path", c->path, 0); - credential_write_item(fp, "username", c->username, 0); - credential_write_item(fp, "password", c->password, 0); + credential_write_item(c, fp, "protocol", c->protocol, 1); + credential_write_item(c, fp, "host", c->host, 1); + credential_write_item(c, fp, "path", c->path, 0); + credential_write_item(c, fp, "username", c->username, 0); + credential_write_item(c, fp, "password", c->password, 0); if (c->password_expiry_utc != TIME_MAX) { char *s = xstrfmt("%"PRItime, c->password_expiry_utc); - credential_write_item(fp, "password_expiry_utc", s, 0); + credential_write_item(c, fp, "password_expiry_utc", s, 0); free(s); } } diff --git a/credential.h b/credential.h index 0364d436d2..2c0b39a925 100644 --- a/credential.h +++ b/credential.h @@ -120,7 +120,8 @@ struct credential { quit:1, use_http_path:1, username_from_proto:1, - sanitize_prompt:1; + sanitize_prompt:1, + protect_protocol:1; char *username; char *password; @@ -134,6 +135,7 @@ struct credential { .helpers = STRING_LIST_INIT_DUP, \ .password_expiry_utc = TIME_MAX, \ .sanitize_prompt = 1, \ + .protect_protocol = 1, \ } /* Initialize a credential structure, setting all fields to empty. */ diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh index b62c70c193..168ae76550 100755 --- a/t/t0300-credentials.sh +++ b/t/t0300-credentials.sh @@ -720,6 +720,22 @@ test_expect_success 'url parser rejects embedded newlines' ' test_cmp expect stderr ' +test_expect_success 'url parser rejects embedded carriage returns' ' + test_config credential.helper "!true" && + test_must_fail git credential fill 2>stderr <<-\EOF && + url=https://example%0d.com/ + EOF + cat >expect <<-\EOF && + fatal: credential value for host contains carriage return + If this is intended, set `credential.protectProtocol=false` + EOF + test_cmp expect stderr && + GIT_ASKPASS=true \ + git -c credential.protectProtocol=false credential fill <<-\EOF + url=https://example%0d.com/ + EOF +' + test_expect_success 'host-less URLs are parsed as empty host' ' check fill "verbatim foo bar" <<-\EOF url=cert:///path/to/cert.pem -- cgit v1.2.3 From 54a3711a9dd968a04249beef157393d64b579d64 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 30 Oct 2024 00:17:53 +0100 Subject: Git 2.40.4 Signed-off-by: Johannes Schindelin --- Documentation/RelNotes/2.40.4.txt | 5 +++++ GIT-VERSION-GEN | 2 +- RelNotes | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 Documentation/RelNotes/2.40.4.txt (limited to 'Documentation') diff --git a/Documentation/RelNotes/2.40.4.txt b/Documentation/RelNotes/2.40.4.txt new file mode 100644 index 0000000000..0ff29f3cfc --- /dev/null +++ b/Documentation/RelNotes/2.40.4.txt @@ -0,0 +1,5 @@ +Git v2.40.4 Release Notes +========================= + +This release lets Git refuse to accept URLs that contain control +sequences. This addresses CVE-2024-50349 and CVE-2024-52006. diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index b345e89cbe..4f4d294651 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v2.40.3 +DEF_VER=v2.40.4 LF=' ' diff --git a/RelNotes b/RelNotes index afb47e28e0..b401038a56 120000 --- a/RelNotes +++ b/RelNotes @@ -1 +1 @@ -Documentation/RelNotes/2.40.3.txt \ No newline at end of file +Documentation/RelNotes/2.40.4.txt \ No newline at end of file -- cgit v1.2.3 From 6fd641a521a722e438b291ec7b852b7bb508b18b Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 30 Oct 2024 00:27:54 +0100 Subject: Git 2.41.3 Signed-off-by: Johannes Schindelin --- Documentation/RelNotes/2.41.3.txt | 6 ++++++ GIT-VERSION-GEN | 2 +- RelNotes | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 Documentation/RelNotes/2.41.3.txt (limited to 'Documentation') diff --git a/Documentation/RelNotes/2.41.3.txt b/Documentation/RelNotes/2.41.3.txt new file mode 100644 index 0000000000..b5aba88790 --- /dev/null +++ b/Documentation/RelNotes/2.41.3.txt @@ -0,0 +1,6 @@ +Git v2.41.3 Release Notes +========================= + +This release merges up the fix that appears in v2.40.4 to address +the security issues CVE-2024-50349 and CVE-2024-52006; see the +release notes for that version for details. diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 990ca9c643..664b521986 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v2.41.2 +DEF_VER=v2.41.3 LF=' ' diff --git a/RelNotes b/RelNotes index 04f6c71310..5bd6fdad36 120000 --- a/RelNotes +++ b/RelNotes @@ -1 +1 @@ -Documentation/RelNotes/2.41.2.txt \ No newline at end of file +Documentation/RelNotes/2.41.3.txt \ No newline at end of file -- cgit v1.2.3 From 54ddf17f827969c989576f2411d9ff519fa8091f Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 30 Oct 2024 00:39:06 +0100 Subject: Git 2.42.4 Signed-off-by: Johannes Schindelin --- Documentation/RelNotes/2.42.4.txt | 6 ++++++ GIT-VERSION-GEN | 2 +- RelNotes | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 Documentation/RelNotes/2.42.4.txt (limited to 'Documentation') diff --git a/Documentation/RelNotes/2.42.4.txt b/Documentation/RelNotes/2.42.4.txt new file mode 100644 index 0000000000..3129d76e75 --- /dev/null +++ b/Documentation/RelNotes/2.42.4.txt @@ -0,0 +1,6 @@ +Git v2.42.4 Release Notes +========================= + +This release merges up the fix that appears in v2.40.4 and v2.41.3 +to address the security issues CVE-2024-50349 and CVE-2024-52006; +see the release notes for these versions for details. diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 070d22c6d1..69948fce1b 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v2.42.3 +DEF_VER=v2.42.4 LF=' ' diff --git a/RelNotes b/RelNotes index 7af3372ac2..e0d3afd77a 120000 --- a/RelNotes +++ b/RelNotes @@ -1 +1 @@ -Documentation/RelNotes/2.42.3.txt \ No newline at end of file +Documentation/RelNotes/2.42.4.txt \ No newline at end of file -- cgit v1.2.3 From 664d4fa692cb8637a7c9297c94abf0de8593e585 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 30 Oct 2024 00:52:18 +0100 Subject: Git 2.43.6 Signed-off-by: Johannes Schindelin --- Documentation/RelNotes/2.43.6.txt | 7 +++++++ GIT-VERSION-GEN | 2 +- RelNotes | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 Documentation/RelNotes/2.43.6.txt (limited to 'Documentation') diff --git a/Documentation/RelNotes/2.43.6.txt b/Documentation/RelNotes/2.43.6.txt new file mode 100644 index 0000000000..2114b9f78d --- /dev/null +++ b/Documentation/RelNotes/2.43.6.txt @@ -0,0 +1,7 @@ +Git v2.43.6 Release Notes +========================= + +This release merges up the fix that appears in v2.40.4, v2.41.3 +and v2.42.4 to address the security issues CVE-2024-50349 and +CVE-2024-52006; see the release notes for these versions for +details. diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index fcaa390a61..81630dde84 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v2.43.5 +DEF_VER=v2.43.6 LF=' ' diff --git a/RelNotes b/RelNotes index 1abe69c298..0a9d8a03d7 120000 --- a/RelNotes +++ b/RelNotes @@ -1 +1 @@ -Documentation/RelNotes/2.43.5.txt \ No newline at end of file +Documentation/RelNotes/2.43.6.txt \ No newline at end of file -- cgit v1.2.3 From 2f323bb16219c105e0c576ea4c2ece9863f5d926 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 30 Oct 2024 00:55:00 +0100 Subject: Git 2.44.3 Signed-off-by: Johannes Schindelin --- Documentation/RelNotes/2.44.3.txt | 7 +++++++ GIT-VERSION-GEN | 2 +- RelNotes | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 Documentation/RelNotes/2.44.3.txt (limited to 'Documentation') diff --git a/Documentation/RelNotes/2.44.3.txt b/Documentation/RelNotes/2.44.3.txt new file mode 100644 index 0000000000..5862845458 --- /dev/null +++ b/Documentation/RelNotes/2.44.3.txt @@ -0,0 +1,7 @@ +Git v2.44.3 Release Notes +========================= + +This release merges up the fix that appears in v2.40.4, v2.41.3, +v2.42.4 and v2.43.6 to address the security issues CVE-2024-50349 +and CVE-2024-52006; see the release notes for these versions +for details. diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 9c631da5ce..33476e262d 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v2.44.2 +DEF_VER=v2.44.3 LF=' ' diff --git a/RelNotes b/RelNotes index 6ba9e6f4ce..509eba5f1a 120000 --- a/RelNotes +++ b/RelNotes @@ -1 +1 @@ -Documentation/RelNotes/2.44.2.txt \ No newline at end of file +Documentation/RelNotes/2.44.3.txt \ No newline at end of file -- cgit v1.2.3