Skip to content

Commit 817ddd6

Browse files
committed
mingw: refuse to access paths with illegal characters
Certain characters are not admissible in file names on Windows, even if Cygwin/MSYS2 (and therefore, Git for Windows' Bash) pretend that they are, e.g. `:`, `<`, `>`, etc Let's disallow those characters explicitly in Windows builds of Git. Note: just like trailing spaces or periods, it _is_ possible on Windows to create commits adding files with such illegal characters, as long as the operation leaves the worktree untouched. To allow for that, we continue to guard `is_valid_win32_path()` behind the config setting `core.protectNTFS`, so that users _can_ continue to do that, as long as they turn the protections off via that config setting. Among other problems, this prevents Git from trying to write to an "NTFS Alternate Data Stream" (which refers to metadata stored alongside a file, under a special name: "<filename>:<stream-name>"). This fix therefore also prevents an attack vector that was exploited in demonstrations of a number of recently-fixed security bugs. Further reading on illegal characters in Win32 filenames: https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file Signed-off-by: Johannes Schindelin <[email protected]>
1 parent d2c84da commit 817ddd6

File tree

3 files changed

+18
-3
lines changed

3 files changed

+18
-3
lines changed

compat/mingw.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2134,6 +2134,8 @@ int is_valid_win32_path(const char *path)
21342134
if (!protect_ntfs)
21352135
return 1;
21362136

2137+
skip_dos_drive_prefix((char **)&path);
2138+
21372139
for (;;) {
21382140
char c = *(path++);
21392141
switch (c) {
@@ -2155,6 +2157,14 @@ int is_valid_win32_path(const char *path)
21552157
preceding_space_or_period = 1;
21562158
i++;
21572159
continue;
2160+
case ':': /* DOS drive prefix was already skipped */
2161+
case '<': case '>': case '"': case '|': case '?': case '*':
2162+
/* illegal character */
2163+
return 0;
2164+
default:
2165+
if (c > '\0' && c < '\x20')
2166+
/* illegal character */
2167+
return 0;
21582168
}
21592169
preceding_space_or_period = 0;
21602170
i++;

compat/mingw.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -431,8 +431,11 @@ int mingw_offset_1st_component(const char *path);
431431
/**
432432
* Verifies that the given path is a valid one on Windows.
433433
*
434-
* In particular, path segments are disallowed which end in a period or a
435-
* space (except the special directories `.` and `..`).
434+
* In particular, path segments are disallowed which
435+
*
436+
* - end in a period or a space (except the special directories `.` and `..`).
437+
*
438+
* - contain any of the reserved characters, e.g. `:`, `;`, `*`, etc
436439
*
437440
* Returns 1 upon success, otherwise 0.
438441
*/

t/t0060-path-utils.sh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -445,13 +445,15 @@ test_expect_success MINGW 'is_valid_path() on Windows' '
445445
win32 \
446446
"win32 x" \
447447
../hello.txt \
448+
C:\\git \
448449
\
449450
--not \
450451
"win32 " \
451452
"win32 /x " \
452453
"win32." \
453454
"win32 . ." \
454-
.../hello.txt
455+
.../hello.txt \
456+
colon:test
455457
'
456458

457459
test_done

0 commit comments

Comments
 (0)