mirror of
https://github.com/git-for-windows/git.git
synced 2026-02-04 03:33:01 -06:00
Merge branch 'disallow-control-characters-in-sideband-channel'
This addresses: - CVE-2024-52005: Insufficient neutralization of ANSI escape sequences in sideband payload can be used to mislead Git users into believing that certain remote-generated messages actually originate from Git. Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
This commit is contained in:
commit
cebb56134c
@ -522,6 +522,8 @@ include::config/sequencer.adoc[]
|
||||
|
||||
include::config/showbranch.adoc[]
|
||||
|
||||
include::config/sideband.adoc[]
|
||||
|
||||
include::config/sparse.adoc[]
|
||||
|
||||
include::config/splitindex.adoc[]
|
||||
|
||||
16
Documentation/config/sideband.adoc
Normal file
16
Documentation/config/sideband.adoc
Normal file
@ -0,0 +1,16 @@
|
||||
sideband.allowControlCharacters::
|
||||
By default, control characters that are delivered via the sideband
|
||||
are masked, except ANSI color sequences. This prevents potentially
|
||||
unwanted ANSI escape sequences from being sent to the terminal. Use
|
||||
this config setting to override this behavior:
|
||||
+
|
||||
--
|
||||
color::
|
||||
Allow ANSI color sequences, line feeds and horizontal tabs,
|
||||
but mask all other control characters. This is the default.
|
||||
false::
|
||||
Mask all control characters other than line feeds and
|
||||
horizontal tabs.
|
||||
true::
|
||||
Allow all control characters to be sent to the terminal.
|
||||
--
|
||||
78
sideband.c
78
sideband.c
@ -26,6 +26,12 @@ static struct keyword_entry keywords[] = {
|
||||
{ "error", GIT_COLOR_BOLD_RED },
|
||||
};
|
||||
|
||||
static enum {
|
||||
ALLOW_NO_CONTROL_CHARACTERS = 0,
|
||||
ALLOW_ALL_CONTROL_CHARACTERS = 1,
|
||||
ALLOW_ANSI_COLOR_SEQUENCES = 2
|
||||
} allow_control_characters = ALLOW_ANSI_COLOR_SEQUENCES;
|
||||
|
||||
/* Returns a color setting (GIT_COLOR_NEVER, etc). */
|
||||
static int use_sideband_colors(void)
|
||||
{
|
||||
@ -39,6 +45,25 @@ static int use_sideband_colors(void)
|
||||
if (use_sideband_colors_cached >= 0)
|
||||
return use_sideband_colors_cached;
|
||||
|
||||
switch (git_config_get_maybe_bool("sideband.allowcontrolcharacters", &i)) {
|
||||
case 0: /* Boolean value */
|
||||
allow_control_characters = i ? ALLOW_ALL_CONTROL_CHARACTERS :
|
||||
ALLOW_NO_CONTROL_CHARACTERS;
|
||||
break;
|
||||
case -1: /* non-Boolean value */
|
||||
if (git_config_get_string_tmp("sideband.allowcontrolcharacters",
|
||||
&value))
|
||||
; /* huh? `get_maybe_bool()` returned -1 */
|
||||
else if (!strcmp(value, "color"))
|
||||
allow_control_characters = ALLOW_ANSI_COLOR_SEQUENCES;
|
||||
else
|
||||
warning(_("unrecognized value for `sideband."
|
||||
"allowControlCharacters`: '%s'"), value);
|
||||
break;
|
||||
default:
|
||||
break; /* not configured */
|
||||
}
|
||||
|
||||
if (!git_config_get_string_tmp(key, &value))
|
||||
use_sideband_colors_cached = git_config_colorbool(key, value);
|
||||
else if (!git_config_get_string_tmp("color.ui", &value))
|
||||
@ -66,6 +91,55 @@ void list_config_color_sideband_slots(struct string_list *list, const char *pref
|
||||
list_config_item(list, prefix, keywords[i].keyword);
|
||||
}
|
||||
|
||||
static int handle_ansi_color_sequence(struct strbuf *dest, const char *src, int n)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Valid ANSI color sequences are of the form
|
||||
*
|
||||
* ESC [ [<n> [; <n>]*] m
|
||||
*/
|
||||
|
||||
if (allow_control_characters != ALLOW_ANSI_COLOR_SEQUENCES ||
|
||||
n < 3 || src[0] != '\x1b' || src[1] != '[')
|
||||
return 0;
|
||||
|
||||
for (i = 2; i < n; i++) {
|
||||
if (src[i] == 'm') {
|
||||
strbuf_add(dest, src, i + 1);
|
||||
return i;
|
||||
}
|
||||
if (!isdigit(src[i]) && src[i] != ';')
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void strbuf_add_sanitized(struct strbuf *dest, const char *src, int n)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (allow_control_characters == ALLOW_ALL_CONTROL_CHARACTERS) {
|
||||
strbuf_add(dest, src, n);
|
||||
return;
|
||||
}
|
||||
|
||||
strbuf_grow(dest, n);
|
||||
for (; n && *src; src++, n--) {
|
||||
if (!iscntrl(*src) || *src == '\t' || *src == '\n')
|
||||
strbuf_addch(dest, *src);
|
||||
else if ((i = handle_ansi_color_sequence(dest, src, n))) {
|
||||
src += i;
|
||||
n -= i;
|
||||
} else {
|
||||
strbuf_addch(dest, '^');
|
||||
strbuf_addch(dest, 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 +155,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 +188,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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -98,4 +98,34 @@ 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?\\a\\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_grep "\\^G" stderr &&
|
||||
tr -dc "\\007" <stderr >actual &&
|
||||
test_must_be_empty actual &&
|
||||
|
||||
rm -rf throw-away &&
|
||||
git -c sideband.allowControlCharacters=false \
|
||||
clone --no-local . throw-away 2>stderr &&
|
||||
test_decode_color <stderr >decoded &&
|
||||
test_grep ! RED decoded &&
|
||||
test_grep "\\^G" stderr &&
|
||||
|
||||
rm -rf throw-away &&
|
||||
git -c sideband.allowControlCharacters clone --no-local . throw-away 2>stderr &&
|
||||
test_decode_color <stderr >decoded &&
|
||||
test_grep RED decoded &&
|
||||
tr -dc "\\007" <stderr >actual &&
|
||||
test_file_not_empty actual
|
||||
'
|
||||
|
||||
test_done
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user