Fix CVE-2024-50349 CVE-2024-52006
This commit is contained in:
parent
4cbb33984f
commit
579eb9f122
@ -0,0 +1,276 @@
|
||||
From 7725b8100ffbbff2750ee4d61a0fcc1f53a086e8 Mon Sep 17 00:00:00 2001
|
||||
From: Johannes Schindelin <johannes.schindelin@gmx.de>
|
||||
Date: Wed, 30 Oct 2024 13:26:10 +0100
|
||||
Subject: [PATCH] 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
|
||||
<username>@<hostname> 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 <peff@peff.net>
|
||||
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
|
||||
---
|
||||
Documentation/config/credential.txt | 6 ++++++
|
||||
credential.c | 7 ++++++-
|
||||
credential.h | 4 +++-
|
||||
t/t0300-credentials.sh | 20 ++++++++++++++++++++
|
||||
t/t5541-http-push-smart.sh | 6 +++---
|
||||
t/t5550-http-fetch-dumb.sh | 14 +++++++-------
|
||||
t/t5551-http-fetch-smart.sh | 16 ++++++++--------
|
||||
7 files changed, 53 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/Documentation/config/credential.txt b/Documentation/config/credential.txt
|
||||
index 512f3187..fd8113d6 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.<context>.* below, and
|
||||
diff --git a/credential.c b/credential.c
|
||||
index 572f1785..1392a54d 100644
|
||||
--- a/credential.c
|
||||
+++ b/credential.c
|
||||
@@ -67,6 +67,8 @@ static int credential_config_callback(const char *var, const char *value,
|
||||
}
|
||||
else if (!strcmp(key, "usehttppath"))
|
||||
c->use_http_path = git_config_bool(var, value);
|
||||
+ else if (!strcmp(key, "sanitizeprompt"))
|
||||
+ c->sanitize_prompt = git_config_bool(var, value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -179,7 +181,10 @@ static char *credential_ask_one(const char *what, struct credential *c,
|
||||
struct strbuf prompt = STRBUF_INIT;
|
||||
char *r;
|
||||
|
||||
- credential_describe(c, &desc);
|
||||
+ if (c->sanitize_prompt)
|
||||
+ credential_format(c, &desc);
|
||||
+ else
|
||||
+ credential_describe(c, &desc);
|
||||
if (desc.len)
|
||||
strbuf_addf(&prompt, "%s for '%s': ", what, desc.buf);
|
||||
else
|
||||
diff --git a/credential.h b/credential.h
|
||||
index 935b28a7..0364d436 100644
|
||||
--- a/credential.h
|
||||
+++ b/credential.h
|
||||
@@ -119,7 +119,8 @@ struct credential {
|
||||
configured:1,
|
||||
quit:1,
|
||||
use_http_path:1,
|
||||
- username_from_proto:1;
|
||||
+ username_from_proto:1,
|
||||
+ sanitize_prompt:1;
|
||||
|
||||
char *username;
|
||||
char *password;
|
||||
@@ -132,7 +133,10 @@ struct credential {
|
||||
char *path;
|
||||
};
|
||||
|
||||
-#define CREDENTIAL_INIT { STRING_LIST_INIT_DUP }
|
||||
+#define CREDENTIAL_INIT { \
|
||||
+ .helpers = STRING_LIST_INIT_DUP, \
|
||||
+ .sanitize_prompt = 1, \
|
||||
+};
|
||||
|
||||
/* Initialize a credential structure, setting all fields to empty. */
|
||||
void credential_init(struct credential *);
|
||||
diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh
|
||||
index cb91be14..b62c70c1 100755
|
||||
--- a/t/t0300-credentials.sh
|
||||
+++ b/t/t0300-credentials.sh
|
||||
@@ -45,6 +45,10 @@ test_expect_success 'setup helper scripts' '
|
||||
test -z "$pass" || echo password=$pass
|
||||
EOF
|
||||
|
||||
+ write_script git-credential-cntrl-in-username <<-\EOF &&
|
||||
+ printf "username=\\007latrix Lestrange\\n"
|
||||
+ EOF
|
||||
+
|
||||
PATH="$PWD:$PATH"
|
||||
'
|
||||
|
||||
@@ -825,4 +829,20 @@ test_expect_success 'credential config with partial URLs' '
|
||||
test_i18ngrep "skipping credential lookup for key" stderr
|
||||
'
|
||||
|
||||
+BEL="$(printf '\007')"
|
||||
+
|
||||
+test_expect_success 'interactive prompt is sanitized' '
|
||||
+ check fill cntrl-in-username <<-EOF
|
||||
+ protocol=https
|
||||
+ host=example.org
|
||||
+ --
|
||||
+ protocol=https
|
||||
+ host=example.org
|
||||
+ username=${BEL}latrix Lestrange
|
||||
+ password=askpass-password
|
||||
+ --
|
||||
+ askpass: Password for ${SQ}https://%07latrix%20Lestrange@example.org${SQ}:
|
||||
+ EOF
|
||||
+'
|
||||
+
|
||||
test_done
|
||||
diff --git a/t/t5541-http-push-smart.sh b/t/t5541-http-push-smart.sh
|
||||
index d0211cd8..2cd2e1a0 100755
|
||||
--- a/t/t5541-http-push-smart.sh
|
||||
+++ b/t/t5541-http-push-smart.sh
|
||||
@@ -351,7 +351,7 @@ test_expect_success 'push over smart http with auth' '
|
||||
git push "$HTTPD_URL"/auth/smart/test_repo.git &&
|
||||
git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \
|
||||
log -1 --format=%s >actual &&
|
||||
- expect_askpass both user@host &&
|
||||
+ expect_askpass both user%40host &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
@@ -363,7 +363,7 @@ test_expect_success 'push to auth-only-for-push repo' '
|
||||
git push "$HTTPD_URL"/auth-push/smart/test_repo.git &&
|
||||
git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git" \
|
||||
log -1 --format=%s >actual &&
|
||||
- expect_askpass both user@host &&
|
||||
+ expect_askpass both user%40host &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
@@ -393,7 +393,7 @@ test_expect_success 'push into half-auth-complete requires password' '
|
||||
git push "$HTTPD_URL/half-auth-complete/smart/half-auth.git" &&
|
||||
git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/half-auth.git" \
|
||||
log -1 --format=%s >actual &&
|
||||
- expect_askpass both user@host &&
|
||||
+ expect_askpass both user%40host &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
diff --git a/t/t5550-http-fetch-dumb.sh b/t/t5550-http-fetch-dumb.sh
|
||||
index 8f182a3c..5d0e3946 100755
|
||||
--- a/t/t5550-http-fetch-dumb.sh
|
||||
+++ b/t/t5550-http-fetch-dumb.sh
|
||||
@@ -90,13 +90,13 @@ test_expect_success 'http auth can use user/pass in URL' '
|
||||
test_expect_success 'http auth can use just user in URL' '
|
||||
set_askpass wrong pass@host &&
|
||||
git clone "$HTTPD_URL_USER/auth/dumb/repo.git" clone-auth-pass &&
|
||||
- expect_askpass pass user@host
|
||||
+ expect_askpass pass user%40host
|
||||
'
|
||||
|
||||
test_expect_success 'http auth can request both user and pass' '
|
||||
set_askpass user@host pass@host &&
|
||||
git clone "$HTTPD_URL/auth/dumb/repo.git" clone-auth-both &&
|
||||
- expect_askpass both user@host
|
||||
+ expect_askpass both user%40host
|
||||
'
|
||||
|
||||
test_expect_success 'http auth respects credential helper config' '
|
||||
@@ -114,14 +114,14 @@ test_expect_success 'http auth can get username from config' '
|
||||
test_config_global "credential.$HTTPD_URL.username" user@host &&
|
||||
set_askpass wrong pass@host &&
|
||||
git clone "$HTTPD_URL/auth/dumb/repo.git" clone-auth-user &&
|
||||
- expect_askpass pass user@host
|
||||
+ expect_askpass pass user%40host
|
||||
'
|
||||
|
||||
test_expect_success 'configured username does not override URL' '
|
||||
test_config_global "credential.$HTTPD_URL.username" wrong &&
|
||||
set_askpass wrong pass@host &&
|
||||
git clone "$HTTPD_URL_USER/auth/dumb/repo.git" clone-auth-user2 &&
|
||||
- expect_askpass pass user@host
|
||||
+ expect_askpass pass user%40host
|
||||
'
|
||||
|
||||
test_expect_success 'set up repo with http submodules' '
|
||||
@@ -142,7 +142,7 @@ test_expect_success 'cmdline credential config passes to submodule via clone' '
|
||||
set_askpass wrong pass@host &&
|
||||
git -c "credential.$HTTPD_URL.username=user@host" \
|
||||
clone --recursive super super-clone &&
|
||||
- expect_askpass pass user@host
|
||||
+ expect_askpass pass user%40host
|
||||
'
|
||||
|
||||
test_expect_success 'cmdline credential config passes submodule via fetch' '
|
||||
@@ -153,7 +153,7 @@ test_expect_success 'cmdline credential config passes submodule via fetch' '
|
||||
git -C super-clone \
|
||||
-c "credential.$HTTPD_URL.username=user@host" \
|
||||
fetch --recurse-submodules &&
|
||||
- expect_askpass pass user@host
|
||||
+ expect_askpass pass user%40host
|
||||
'
|
||||
|
||||
test_expect_success 'cmdline credential config passes submodule update' '
|
||||
@@ -170,7 +170,7 @@ test_expect_success 'cmdline credential config passes submodule update' '
|
||||
git -C super-clone \
|
||||
-c "credential.$HTTPD_URL.username=user@host" \
|
||||
submodule update &&
|
||||
- expect_askpass pass user@host
|
||||
+ expect_askpass pass user%40host
|
||||
'
|
||||
|
||||
test_expect_success 'fetch changes via http' '
|
||||
diff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh
|
||||
index 0908534f..8a27768d 100755
|
||||
--- a/t/t5551-http-fetch-smart.sh
|
||||
+++ b/t/t5551-http-fetch-smart.sh
|
||||
@@ -181,7 +181,7 @@ test_expect_success 'clone from password-protected repository' '
|
||||
echo two >expect &&
|
||||
set_askpass user@host pass@host &&
|
||||
git clone --bare "$HTTPD_URL/auth/smart/repo.git" smart-auth &&
|
||||
- expect_askpass both user@host &&
|
||||
+ expect_askpass both user%40host &&
|
||||
git --git-dir=smart-auth log -1 --format=%s >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
@@ -199,7 +199,7 @@ test_expect_success 'clone from auth-only-for-objects repository' '
|
||||
echo two >expect &&
|
||||
set_askpass user@host pass@host &&
|
||||
git clone --bare "$HTTPD_URL/auth-fetch/smart/repo.git" half-auth &&
|
||||
- expect_askpass both user@host &&
|
||||
+ expect_askpass both user%40host &&
|
||||
git --git-dir=half-auth log -1 --format=%s >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
@@ -224,7 +224,7 @@ test_expect_success 'redirects send auth to new location' '
|
||||
set_askpass user@host pass@host &&
|
||||
git -c credential.useHttpPath=true \
|
||||
clone $HTTPD_URL/smart-redir-auth/repo.git repo-redir-auth &&
|
||||
- expect_askpass both user@host auth/smart/repo.git
|
||||
+ expect_askpass both user%40host auth/smart/repo.git
|
||||
'
|
||||
|
||||
test_expect_success 'disable dumb http on server' '
|
||||
--
|
||||
2.23.0
|
||||
@ -0,0 +1,98 @@
|
||||
From c903985bf7e772e2d08275c1a95c8a55ab011577 Mon Sep 17 00:00:00 2001
|
||||
From: Johannes Schindelin <johannes.schindelin@gmx.de>
|
||||
Date: Thu, 7 Nov 2024 08:57:52 +0100
|
||||
Subject: [PATCH] credential_format(): also encode <host>[:<port>]
|
||||
|
||||
An upcoming change wants to sanitize the credential password prompt
|
||||
where a URL is displayed that may potentially come from a `.gitmodules`
|
||||
file. To this end, the `credential_format()` function is employed.
|
||||
|
||||
To sanitize the host name (and optional port) part of the URL, we need a
|
||||
new mode of the `strbuf_add_percentencode()` function because the
|
||||
current mode is both too strict and too lenient: too strict because it
|
||||
encodes `:`, `[` and `]` (which should be left unencoded in
|
||||
`<host>:<port>` and in IPv6 addresses), and too lenient because it does
|
||||
not encode invalid host name characters `/`, `_` and `~`.
|
||||
|
||||
So let's introduce and use a new mode specifically to encode the host
|
||||
name and optional port part of a URI, leaving alpha-numerical
|
||||
characters, periods, colons and brackets alone and encoding all others.
|
||||
|
||||
This only leads to a change of behavior for URLs that contain invalid
|
||||
host names.
|
||||
|
||||
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
|
||||
---
|
||||
credential.c | 3 ++-
|
||||
strbuf.c | 4 +++-
|
||||
strbuf.h | 1 +
|
||||
t/t0300-credentials.sh | 13 +++++++++++++
|
||||
4 files changed, 19 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/credential.c b/credential.c
|
||||
index f3201134..572f1785 100644
|
||||
--- a/credential.c
|
||||
+++ b/credential.c
|
||||
@@ -164,7 +164,8 @@ static void credential_format(struct credential *c, struct strbuf *out)
|
||||
strbuf_addch(out, '@');
|
||||
}
|
||||
if (c->host)
|
||||
- strbuf_addstr(out, c->host);
|
||||
+ strbuf_add_percentencode(out, c->host,
|
||||
+ STRBUF_ENCODE_HOST_AND_PORT);
|
||||
if (c->path) {
|
||||
strbuf_addch(out, '/');
|
||||
strbuf_add_percentencode(out, c->path, 0);
|
||||
diff --git a/strbuf.c b/strbuf.c
|
||||
index c383f41a..756b96c5 100644
|
||||
--- a/strbuf.c
|
||||
+++ b/strbuf.c
|
||||
@@ -492,7 +492,9 @@ void strbuf_add_percentencode(struct strbuf *dst, const char *src, int flags)
|
||||
unsigned char ch = src[i];
|
||||
if (ch <= 0x1F || ch >= 0x7F ||
|
||||
(ch == '/' && (flags & STRBUF_ENCODE_SLASH)) ||
|
||||
- strchr(URL_UNSAFE_CHARS, ch))
|
||||
+ ((flags & STRBUF_ENCODE_HOST_AND_PORT) ?
|
||||
+ !isalnum(ch) && !strchr("-.:[]", ch) :
|
||||
+ !!strchr(URL_UNSAFE_CHARS, ch)))
|
||||
strbuf_addf(dst, "%%%02X", (unsigned char)ch);
|
||||
else
|
||||
strbuf_addch(dst, ch);
|
||||
diff --git a/strbuf.h b/strbuf.h
|
||||
index f6dbb968..f9f8bb03 100644
|
||||
--- a/strbuf.h
|
||||
+++ b/strbuf.h
|
||||
@@ -380,6 +380,7 @@ size_t strbuf_expand_dict_cb(struct strbuf *sb,
|
||||
void strbuf_addbuf_percentquote(struct strbuf *dst, const struct strbuf *src);
|
||||
|
||||
#define STRBUF_ENCODE_SLASH 1
|
||||
+#define STRBUF_ENCODE_HOST_AND_PORT 2
|
||||
|
||||
/**
|
||||
* Append the contents of a string to a strbuf, percent-encoding any characters
|
||||
diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh
|
||||
index c66d91e8..cb91be14 100755
|
||||
--- a/t/t0300-credentials.sh
|
||||
+++ b/t/t0300-credentials.sh
|
||||
@@ -514,6 +514,19 @@ test_expect_success 'match percent-encoded values in username' '
|
||||
EOF
|
||||
'
|
||||
|
||||
+test_expect_success 'match percent-encoded values in hostname' '
|
||||
+ test_config "credential.https://a%20b%20c/.helper" "$HELPER" &&
|
||||
+ check fill <<-\EOF
|
||||
+ url=https://a b c/
|
||||
+ --
|
||||
+ protocol=https
|
||||
+ host=a b c
|
||||
+ username=foo
|
||||
+ password=bar
|
||||
+ --
|
||||
+ EOF
|
||||
+'
|
||||
+
|
||||
test_expect_success 'fetch with multiple path components' '
|
||||
test_unconfig credential.helper &&
|
||||
test_config credential.https://example.com/foo/repo.git.helper "verbatim foo bar" &&
|
||||
--
|
||||
2.23.0
|
||||
@ -0,0 +1,160 @@
|
||||
From b01b9b81d36759cdcd07305e78765199e1bc2060 Mon Sep 17 00:00:00 2001
|
||||
From: Johannes Schindelin <johannes.schindelin@gmx.de>
|
||||
Date: Mon, 4 Nov 2024 14:48:22 +0100
|
||||
Subject: [PATCH] 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 <johannes.schindelin@gmx.de>
|
||||
---
|
||||
Documentation/config/credential.txt | 5 +++++
|
||||
credential.c | 21 ++++++++++++++-------
|
||||
credential.h | 4 +++-
|
||||
t/t0300-credentials.sh | 16 ++++++++++++++++
|
||||
4 files changed, 38 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/Documentation/config/credential.txt b/Documentation/config/credential.txt
|
||||
index fd8113d6..9cadca7f 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.<context>.* below, and
|
||||
diff --git a/credential.c b/credential.c
|
||||
index 1392a54d..b76a7309 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,16 +274,20 @@ 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);
|
||||
}
|
||||
|
||||
static int run_credential_helper(struct credential *c,
|
||||
diff --git a/credential.h b/credential.h
|
||||
index 0364d436..2c0b39a9 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 {
|
||||
#define CREDENTIAL_INIT { \
|
||||
.helpers = STRING_LIST_INIT_DUP, \
|
||||
.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 b62c70c1..168ae765 100755
|
||||
--- a/t/t0300-credentials.sh
|
||||
+++ b/t/t0300-credentials.sh
|
||||
@@ -720,6 +720,22 @@ test_expect_success 'url parser rejects embedded newlines' '
|
||||
test_i18ncmp 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
|
||||
--
|
||||
2.23.0
|
||||
59
backport-pre-001-CVE-2024-52006.patch
Normal file
59
backport-pre-001-CVE-2024-52006.patch
Normal file
@ -0,0 +1,59 @@
|
||||
From 356c473295097f4aeaacc1a2dcd70271b7080788 Mon Sep 17 00:00:00 2001
|
||||
From: Nikita Leonov <nykyta.leonov@gmail.com>
|
||||
Date: Sat, 3 Oct 2020 13:29:12 +0000
|
||||
Subject: [PATCH] credential: treat CR/LF as line endings in the credential
|
||||
protocol
|
||||
|
||||
This fix makes using Git credentials more friendly to Windows users: it
|
||||
allows a credential helper to communicate using CR/LF line endings ("DOS
|
||||
line endings" commonly found on Windows) instead of LF-only line endings
|
||||
("Unix line endings").
|
||||
|
||||
Note that this changes the behavior a bit: if a credential helper
|
||||
produces, say, a password with a trailing Carriage Return character,
|
||||
that will now be culled even when the rest of the lines end only in Line
|
||||
Feed characters, indicating that the Carriage Return was not meant to be
|
||||
part of the line ending.
|
||||
|
||||
In practice, it seems _very_ unlikely that something like this happens.
|
||||
Passwords usually need to consist of non-control characters, URLs need
|
||||
to have special characters URL-encoded, and user names, well, are names.
|
||||
|
||||
However, it _does_ help on Windows, where CR/LF line endings are common:
|
||||
as unrecognized commands are simply ignored by the credential machinery,
|
||||
even a command like `quit\r` (which is clearly intended to abort) would
|
||||
simply be ignored (silently) by Git.
|
||||
|
||||
So let's change the credential machinery to accept both CR/LF and LF
|
||||
line endings.
|
||||
|
||||
While we do this for the credential helper protocol, we do _not_ adjust
|
||||
`git credential-cache--daemon` (which won't work on Windows, anyway,
|
||||
because it requires Unix sockets) nor `git credential-store` (which
|
||||
writes the file `~/.git-credentials` which we consider an implementation
|
||||
detail that should be opaque to the user, read: we do expect users _not_
|
||||
to edit this file manually).
|
||||
|
||||
Signed-off-by: Nikita Leonov <nykyta.leonov@gmail.com>
|
||||
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
|
||||
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
||||
---
|
||||
credential.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/credential.c b/credential.c
|
||||
index efc29dc5e1..e5202fbef2 100644
|
||||
--- a/credential.c
|
||||
+++ b/credential.c
|
||||
@@ -202,7 +202,7 @@ int credential_read(struct credential *c, FILE *fp)
|
||||
{
|
||||
struct strbuf line = STRBUF_INIT;
|
||||
|
||||
- while (strbuf_getline_lf(&line, fp) != EOF) {
|
||||
+ while (strbuf_getline(&line, fp) != EOF) {
|
||||
char *key = line.buf;
|
||||
char *value = strchr(key, '=');
|
||||
|
||||
--
|
||||
2.33.0
|
||||
|
||||
100
backport-pre-002-CVE-2024-52006.patch
Normal file
100
backport-pre-002-CVE-2024-52006.patch
Normal file
@ -0,0 +1,100 @@
|
||||
From 5726a6b4012cd41701927a6637b9f2070e7760ee Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?=
|
||||
<avarab@gmail.com>
|
||||
Date: Thu, 1 Jul 2021 12:51:26 +0200
|
||||
Subject: [PATCH] *.c *_init(): define in terms of corresponding *_INIT macro
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Change the common patter in the codebase of duplicating the
|
||||
initialization logic between an *_INIT macro and a
|
||||
corresponding *_init() function to use the macro as the canonical
|
||||
source of truth.
|
||||
|
||||
Now we no longer need to keep the function up-to-date with the macro
|
||||
version. This implements a suggestion by Jeff King who found that
|
||||
under -O2 [1] modern compilers will init new version in place without
|
||||
the extra copy[1]. The performance of a single *_init() won't matter
|
||||
in most cases, but even if it does we're going to be producing
|
||||
efficient machine code to perform these operations.
|
||||
|
||||
1. https://lore.kernel.org/git/YNyrDxUO1PlGJvCn@coredump.intra.peff.net/
|
||||
|
||||
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
|
||||
Signed-off-by: Junio C Hamano <gitster@pobox.com>
|
||||
---
|
||||
credential.c | 4 ++--
|
||||
json-writer.c | 6 ++----
|
||||
run-command.c | 5 ++---
|
||||
strbuf.c | 4 ++--
|
||||
strmap.c | 3 ++-
|
||||
strvec.c | 5 ++---
|
||||
6 files changed, 12 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/credential.c b/credential.c
|
||||
index e5202fbef2..3c05c7c669 100644
|
||||
--- a/credential.c
|
||||
+++ b/credential.c
|
||||
@@ -10,8 +10,8 @@
|
||||
|
||||
void credential_init(struct credential *c)
|
||||
{
|
||||
- memset(c, 0, sizeof(*c));
|
||||
- c->helpers.strdup_strings = 1;
|
||||
+ struct credential blank = CREDENTIAL_INIT;
|
||||
+ memcpy(c, &blank, sizeof(*c));
|
||||
}
|
||||
|
||||
void credential_clear(struct credential *c)
|
||||
diff --git a/json-writer.c b/json-writer.c
|
||||
index aadb9dbddc..f1cfd8fa8c 100644
|
||||
--- a/json-writer.c
|
||||
+++ b/json-writer.c
|
||||
@@ -3,10 +3,8 @@
|
||||
|
||||
void jw_init(struct json_writer *jw)
|
||||
{
|
||||
- strbuf_init(&jw->json, 0);
|
||||
- strbuf_init(&jw->open_stack, 0);
|
||||
- jw->need_comma = 0;
|
||||
- jw->pretty = 0;
|
||||
+ struct json_writer blank = JSON_WRITER_INIT;
|
||||
+ memcpy(jw, &blank, sizeof(*jw));;
|
||||
}
|
||||
|
||||
void jw_release(struct json_writer *jw)
|
||||
diff --git a/run-command.c b/run-command.c
|
||||
index be6bc128cd..8750df16d8 100644
|
||||
--- a/run-command.c
|
||||
+++ b/run-command.c
|
||||
@@ -11,9 +11,8 @@
|
||||
|
||||
void child_process_init(struct child_process *child)
|
||||
{
|
||||
- memset(child, 0, sizeof(*child));
|
||||
- argv_array_init(&child->args);
|
||||
- argv_array_init(&child->env_array);
|
||||
+ struct child_process blank = CHILD_PROCESS_INIT;
|
||||
+ memcpy(child, &blank, sizeof(*child));
|
||||
}
|
||||
|
||||
void child_process_clear(struct child_process *child)
|
||||
diff --git a/strbuf.c b/strbuf.c
|
||||
index 4df30b4549..c8a5789694 100644
|
||||
--- a/strbuf.c
|
||||
+++ b/strbuf.c
|
||||
@@ -52,8 +52,8 @@ char strbuf_slopbuf[1];
|
||||
|
||||
void strbuf_init(struct strbuf *sb, size_t hint)
|
||||
{
|
||||
- sb->alloc = sb->len = 0;
|
||||
- sb->buf = strbuf_slopbuf;
|
||||
+ struct strbuf blank = STRBUF_INIT;
|
||||
+ memcpy(sb, &blank, sizeof(*sb));
|
||||
if (hint)
|
||||
strbuf_grow(sb, hint);
|
||||
}
|
||||
--
|
||||
2.33.0
|
||||
|
||||
13
git.spec
13
git.spec
@ -1,7 +1,7 @@
|
||||
%global gitexecdir %{_libexecdir}/git-core
|
||||
Name: git
|
||||
Version: 2.27.0
|
||||
Release: 20
|
||||
Release: 21
|
||||
Summary: A popular and widely used Version Control System
|
||||
License: GPLv2+ or LGPLv2.1
|
||||
URL: https://git-scm.com/
|
||||
@ -74,6 +74,11 @@ Patch59: backport-CVE-2024-32465-wrapper.c-add-x-un-setenv-and-use-xsetenv-in
|
||||
Patch60: backport-CVE-2024-32465-upload-pack-disable-lazy-fetching-by-default.patch
|
||||
Patch61: backport-CVE-2024-32002-dir-introduce-readdir_skip_dot_and_dotdot-helper.patch
|
||||
Patch62: backport-CVE-2024-32002-submodules-submodule-paths-must-not-contain-symlinks.patch
|
||||
Patch63: backport-pre-001-CVE-2024-52006.patch
|
||||
Patch64: backport-pre-002-CVE-2024-52006.patch
|
||||
Patch65: backport-CVE-2024-50349-credential_format-also-encode-host-port.patch
|
||||
Patch66: backport-CVE-2024-50349-credential-sanitize-the-user-prompt.patch
|
||||
Patch67: backport-CVE-2024-52006-credential-disallow-Carriage-Returns-in-the-protocol.patch
|
||||
|
||||
BuildRequires: gcc gettext
|
||||
BuildRequires: openssl-devel libcurl-devel expat-devel systemd asciidoc xmlto glib2-devel libsecret-devel pcre2-devel desktop-file-utils
|
||||
@ -323,6 +328,12 @@ make %{?_smp_mflags} test
|
||||
%{_mandir}/man7/git*.7.*
|
||||
|
||||
%changelog
|
||||
* Wed Jan 15 2025 fuanan <fuanan3@h-partners.com> - 2.27.0-21
|
||||
- Type:CVE
|
||||
- ID:CVE-2024-50349 CVE-2024-52006
|
||||
- SUG:NA
|
||||
- DESC:Fix CVE-2024-50349 CVE-2024-52006
|
||||
|
||||
* Tue May 21 2024 qiaojijun <qiaojijun@kylinos.cn> - 2.27.0-20
|
||||
- Type:CVE
|
||||
- ID:CVE-2024-32002
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user