]> git.ipfire.org Git - thirdparty/git.git/commitdiff
sideband: mask control characters
authorJohannes Schindelin <johannes.schindelin@gmx.de>
Thu, 5 Mar 2026 23:34:46 +0000 (15:34 -0800)
committerJunio C Hamano <gitster@pobox.com>
Fri, 6 Mar 2026 21:52:28 +0000 (13:52 -0800)
The output of `git clone` is a vital component for understanding what
has happened when things go wrong. However, these logs are partially
under the control of the remote server (via the "sideband", which
typically contains what the remote `git pack-objects` process sends to
`stderr`), and is currently not sanitized by Git.

This makes Git susceptible to ANSI escape sequence injection (see
CWE-150, https://cwe.mitre.org/data/definitions/150.html), which allows
attackers to corrupt terminal state, to hide information, and even to
insert characters into the input buffer (i.e. as if the user had typed
those characters).

To plug this vulnerability, disallow any control character in the
sideband, replacing them instead with the common `^<letter/symbol>`
(e.g. `^[` for `\x1b`, `^A` for `\x01`).

There is likely a need for more fine-grained controls instead of using a
"heavy hammer" like this, which will be introduced subsequently.

Helped-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
sideband.c
t/t5409-colorize-remote-messages.sh

index ea7c25211ef7e1c8a80cb60475ee43457c8c13f1..c1bbadccac682bc46d7c2382ed9aaacdba0f97d5 100644 (file)
@@ -66,6 +66,19 @@ void list_config_color_sideband_slots(struct string_list *list, const char *pref
                list_config_item(list, prefix, keywords[i].keyword);
 }
 
+static void strbuf_add_sanitized(struct strbuf *dest, const char *src, int n)
+{
+       strbuf_grow(dest, n);
+       for (; n && *src; src++, n--) {
+               if (!iscntrl(*src) || *src == '\t' || *src == '\n') {
+                       strbuf_addch(dest, *src);
+               } else {
+                       strbuf_addch(dest, '^');
+                       strbuf_addch(dest, *src == 0x7f ? '?' : 0x40 + *src);
+               }
+       }
+}
+
 /*
  * Optionally highlight one keyword in remote output if it appears at the start
  * of the line. This should be called for a single line only, which is
@@ -81,7 +94,7 @@ static void maybe_colorize_sideband(struct strbuf *dest, const char *src, int n)
        int i;
 
        if (!want_color_stderr(use_sideband_colors())) {
-               strbuf_add(dest, src, n);
+               strbuf_add_sanitized(dest, src, n);
                return;
        }
 
@@ -114,7 +127,7 @@ static void maybe_colorize_sideband(struct strbuf *dest, const char *src, int n)
                }
        }
 
-       strbuf_add(dest, src, n);
+       strbuf_add_sanitized(dest, src, n);
 }
 
 
index fa5de4500a4f50d48067ef6b1c05491b360a11f4..aa5b57057148e0d4a5d72d2b7f010cb9c9e1f0ce 100755 (executable)
@@ -98,4 +98,16 @@ test_expect_success 'fallback to color.ui' '
        grep "<BOLD;RED>error<RESET>: error" decoded
 '
 
+test_expect_success 'disallow (color) control sequences in sideband' '
+       write_script .git/color-me-surprised <<-\EOF &&
+       printf "error: Have you \\033[31mread\\033[m this?\\n" >&2
+       exec "$@"
+       EOF
+       test_config_global uploadPack.packObjectsHook ./color-me-surprised &&
+       test_commit need-at-least-one-commit &&
+       git clone --no-local . throw-away 2>stderr &&
+       test_decode_color <stderr >decoded &&
+       test_grep ! RED decoded
+'
+
 test_done