Skip to content

Commit d2bc61f

Browse files
committed
Merge branch 'ps/bundle-uri-arbitrary-writes' into maint-2.43
This merges in the fix for CVE-2025-48385. * ps/bundle-uri-arbitrary-writes: bundle-uri: fix arbitrary file writes via parameter injection Signed-off-by: Taylor Blau <[email protected]>
2 parents d61cfed + 35cb1bb commit d2bc61f

File tree

2 files changed

+45
-0
lines changed

2 files changed

+45
-0
lines changed

bundle-uri.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,28 @@ static int download_https_uri_to_file(const char *file, const char *uri)
292292
struct strbuf line = STRBUF_INIT;
293293
int found_get = 0;
294294

295+
/*
296+
* The protocol we speak with git-remote-https(1) uses a space to
297+
* separate between URI and file, so the URI itself must not contain a
298+
* space. If it did, an adversary could change the location where the
299+
* downloaded file is being written to.
300+
*
301+
* Similarly, we use newlines to separate commands from one another.
302+
* Consequently, neither the URI nor the file must contain a newline or
303+
* otherwise an adversary could inject arbitrary commands.
304+
*
305+
* TODO: Restricting newlines in the target paths may break valid
306+
* usecases, even if those are a bit more on the esoteric side.
307+
* If this ever becomes a problem we should probably think about
308+
* alternatives. One alternative could be to use NUL-delimited
309+
* requests in git-remote-http(1). Another alternative could be
310+
* to use URL quoting.
311+
*/
312+
if (strpbrk(uri, " \n"))
313+
return error("bundle-uri: URI is malformed: '%s'", file);
314+
if (strchr(file, '\n'))
315+
return error("bundle-uri: filename is malformed: '%s'", file);
316+
295317
strvec_pushl(&cp.args, "git-remote-https", uri, NULL);
296318
cp.err = -1;
297319
cp.in = -1;

t/t5558-clone-bundle-uri.sh

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1052,6 +1052,29 @@ test_expect_success 'bundles are downloaded once during fetch --all' '
10521052
trace-mult.txt >bundle-fetches &&
10531053
test_line_count = 1 bundle-fetches
10541054
'
1055+
1056+
test_expect_success 'bundles with space in URI are rejected' '
1057+
test_when_finished "rm -rf busted repo" &&
1058+
mkdir -p "$HOME/busted/ /$HOME/repo/.git/objects/bundles" &&
1059+
git clone --bundle-uri="$HTTPD_URL/bogus $HOME/busted/" "$HTTPD_URL/smart/fetch.git" repo 2>err &&
1060+
test_grep "error: bundle-uri: URI is malformed: " err &&
1061+
find busted -type f >files &&
1062+
test_must_be_empty files
1063+
'
1064+
1065+
test_expect_success 'bundles with newline in URI are rejected' '
1066+
test_when_finished "rm -rf busted repo" &&
1067+
git clone --bundle-uri="$HTTPD_URL/bogus\nget $HTTPD_URL/bogus $HOME/busted" "$HTTPD_URL/smart/fetch.git" repo 2>err &&
1068+
test_grep "error: bundle-uri: URI is malformed: " err &&
1069+
test_path_is_missing "$HOME/busted"
1070+
'
1071+
1072+
test_expect_success 'bundles with newline in target path are rejected' '
1073+
git clone --bundle-uri="$HTTPD_URL/bogus" "$HTTPD_URL/smart/fetch.git" "$(printf "escape\nget $HTTPD_URL/bogus .")" 2>err &&
1074+
test_grep "error: bundle-uri: filename is malformed: " err &&
1075+
test_path_is_missing escape
1076+
'
1077+
10551078
# Do not add tests here unless they use the HTTP server, as they will
10561079
# not run unless the HTTP dependencies exist.
10571080

0 commit comments

Comments
 (0)