Skip to content

Commit efe3874

Browse files
committed
Sync with v2.26.1
2 parents 9fadedd + de49261 commit efe3874

16 files changed

+158
-6
lines changed

Documentation/RelNotes/2.17.4.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
Git v2.17.4 Release Notes
2+
=========================
3+
4+
This release is to address the security issue: CVE-2020-5260
5+
6+
Fixes since v2.17.3
7+
-------------------
8+
9+
* With a crafted URL that contains a newline in it, the credential
10+
helper machinery can be fooled to give credential information for
11+
a wrong host. The attack has been made impossible by forbidding
12+
a newline character in any value passed via the credential
13+
protocol.
14+
15+
Credit for finding the vulnerability goes to Felix Wilhelm of Google
16+
Project Zero.

Documentation/RelNotes/2.18.3.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Git v2.18.3 Release Notes
2+
=========================
3+
4+
This release merges the security fix that appears in v2.17.4; see
5+
the release notes for that version for details.

Documentation/RelNotes/2.19.4.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Git v2.19.4 Release Notes
2+
=========================
3+
4+
This release merges the security fix that appears in v2.17.4; see
5+
the release notes for that version for details.

Documentation/RelNotes/2.20.3.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Git v2.20.3 Release Notes
2+
=========================
3+
4+
This release merges the security fix that appears in v2.17.4; see
5+
the release notes for that version for details.

Documentation/RelNotes/2.21.2.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Git v2.21.2 Release Notes
2+
=========================
3+
4+
This release merges the security fix that appears in v2.17.4; see
5+
the release notes for that version for details.

Documentation/RelNotes/2.22.3.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Git v2.22.3 Release Notes
2+
=========================
3+
4+
This release merges the security fix that appears in v2.17.4; see
5+
the release notes for that version for details.

Documentation/RelNotes/2.23.2.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Git v2.23.2 Release Notes
2+
=========================
3+
4+
This release merges the security fix that appears in v2.17.4; see
5+
the release notes for that version for details.

Documentation/RelNotes/2.24.2.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Git v2.24.2 Release Notes
2+
=========================
3+
4+
This release merges the security fix that appears in v2.17.4; see
5+
the release notes for that version for details.

Documentation/RelNotes/2.25.3.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Git v2.25.3 Release Notes
2+
=========================
3+
4+
This release merges the security fix that appears in v2.17.4; see
5+
the release notes for that version for details.

Documentation/RelNotes/2.26.1.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Git v2.26.1 Release Notes
2+
=========================
3+
4+
This release merges the security fix that appears in v2.17.4; see
5+
the release notes for that version for details.

credential.c

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,8 @@ static void credential_write_item(FILE *fp, const char *key, const char *value)
226226
{
227227
if (!value)
228228
return;
229+
if (strchr(value, '\n'))
230+
die("credential value for %s contains newline", key);
229231
fprintf(fp, "%s=%s\n", key, value);
230232
}
231233

@@ -353,7 +355,22 @@ void credential_reject(struct credential *c)
353355
c->approved = 0;
354356
}
355357

356-
void credential_from_url(struct credential *c, const char *url)
358+
static int check_url_component(const char *url, int quiet,
359+
const char *name, const char *value)
360+
{
361+
if (!value)
362+
return 0;
363+
if (!strchr(value, '\n'))
364+
return 0;
365+
366+
if (!quiet)
367+
warning(_("url contains a newline in its %s component: %s"),
368+
name, url);
369+
return -1;
370+
}
371+
372+
int credential_from_url_gently(struct credential *c, const char *url,
373+
int quiet)
357374
{
358375
const char *at, *colon, *cp, *slash, *host, *proto_end;
359376

@@ -367,7 +384,7 @@ void credential_from_url(struct credential *c, const char *url)
367384
*/
368385
proto_end = strstr(url, "://");
369386
if (!proto_end)
370-
return;
387+
return 0;
371388
cp = proto_end + 3;
372389
at = strchr(cp, '@');
373390
colon = strchr(cp, ':');
@@ -406,4 +423,21 @@ void credential_from_url(struct credential *c, const char *url)
406423
while (p > c->path && *p == '/')
407424
*p-- = '\0';
408425
}
426+
427+
if (check_url_component(url, quiet, "username", c->username) < 0 ||
428+
check_url_component(url, quiet, "password", c->password) < 0 ||
429+
check_url_component(url, quiet, "protocol", c->protocol) < 0 ||
430+
check_url_component(url, quiet, "host", c->host) < 0 ||
431+
check_url_component(url, quiet, "path", c->path) < 0)
432+
return -1;
433+
434+
return 0;
435+
}
436+
437+
void credential_from_url(struct credential *c, const char *url)
438+
{
439+
if (credential_from_url_gently(c, url, 0) < 0) {
440+
warning(_("skipping credential lookup for url: %s"), url);
441+
credential_clear(c);
442+
}
409443
}

credential.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,21 @@ void credential_reject(struct credential *);
173173
int credential_read(struct credential *, FILE *);
174174
void credential_write(const struct credential *, FILE *);
175175

176-
/* Parse a URL into broken-down credential fields. */
176+
/*
177+
* Parse a url into a credential struct, replacing any existing contents.
178+
*
179+
* If the url can't be parsed (e.g., a missing "proto://" component), the
180+
* resulting credential will be empty but we'll still return success from the
181+
* "gently" form.
182+
*
183+
* If we encounter a component which cannot be represented as a credential
184+
* value (e.g., because it contains a newline), the "gently" form will return
185+
* an error but leave the broken state in the credential object for further
186+
* examination. The non-gentle form will issue a warning to stderr and return
187+
* an empty credential.
188+
*/
177189
void credential_from_url(struct credential *, const char *url);
190+
int credential_from_url_gently(struct credential *, const char *url, int quiet);
178191

179192
int credential_match(const struct credential *have,
180193
const struct credential *want);

fsck.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "packfile.h"
1616
#include "submodule-config.h"
1717
#include "config.h"
18+
#include "credential.h"
1819
#include "help.h"
1920

2021
static struct oidset gitmodules_found = OIDSET_INIT;
@@ -910,6 +911,19 @@ static int fsck_tag(const struct object_id *oid, const char *buffer,
910911
return ret;
911912
}
912913

914+
static int check_submodule_url(const char *url)
915+
{
916+
struct credential c = CREDENTIAL_INIT;
917+
int ret;
918+
919+
if (looks_like_command_line_option(url))
920+
return -1;
921+
922+
ret = credential_from_url_gently(&c, url, 1);
923+
credential_clear(&c);
924+
return ret;
925+
}
926+
913927
struct fsck_gitmodules_data {
914928
const struct object_id *oid;
915929
struct fsck_options *options;
@@ -935,7 +949,7 @@ static int fsck_gitmodules_fn(const char *var, const char *value, void *vdata)
935949
"disallowed submodule name: %s",
936950
name);
937951
if (!strcmp(key, "url") && value &&
938-
looks_like_command_line_option(value))
952+
check_submodule_url(value) < 0)
939953
data->ret |= report(data->options,
940954
data->oid, OBJ_BLOB,
941955
FSCK_MSG_GITMODULES_URL,

t/lib-credential.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ check() {
1919
false
2020
fi &&
2121
test_cmp expect-stdout stdout &&
22-
test_cmp expect-stderr stderr
22+
test_i18ncmp expect-stderr stderr
2323
}
2424

2525
read_chunk() {

t/t0300-credentials.sh

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,4 +436,18 @@ test_expect_success 'empty helper spec resets helper list' '
436436
EOF
437437
'
438438

439+
test_expect_success 'url parser ignores embedded newlines' '
440+
check fill <<-EOF
441+
url=https://one.example.com?%0ahost=two.example.com/
442+
--
443+
username=askpass-username
444+
password=askpass-password
445+
--
446+
warning: url contains a newline in its host component: https://one.example.com?%0ahost=two.example.com/
447+
warning: skipping credential lookup for url: https://one.example.com?%0ahost=two.example.com/
448+
askpass: Username:
449+
askpass: Password:
450+
EOF
451+
'
452+
439453
test_done

t/t7416-submodule-dash-url.sh

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/bin/sh
22

3-
test_description='check handling of .gitmodule url with dash'
3+
test_description='check handling of disallowed .gitmodule urls'
44
. ./test-lib.sh
55

66
test_expect_success 'create submodule with protected dash in url' '
@@ -60,4 +60,20 @@ test_expect_success 'trailing backslash is handled correctly' '
6060
test_i18ngrep ! "unknown option" err
6161
'
6262

63+
test_expect_success 'fsck rejects embedded newline in url' '
64+
# create an orphan branch to avoid existing .gitmodules objects
65+
git checkout --orphan newline &&
66+
cat >.gitmodules <<-\EOF &&
67+
[submodule "foo"]
68+
url = "https://one.example.com?%0ahost=two.example.com/foo.git"
69+
EOF
70+
git add .gitmodules &&
71+
git commit -m "gitmodules with newline" &&
72+
test_when_finished "rm -rf dst" &&
73+
git init --bare dst &&
74+
git -C dst config transfer.fsckObjects true &&
75+
test_must_fail git push dst HEAD 2>err &&
76+
grep gitmodulesUrl err
77+
'
78+
6379
test_done

0 commit comments

Comments
 (0)