Skip to content

Commit b637a41

Browse files
chooglenttaylorr
authored andcommitted
http: redact curl h2h3 headers in info
With GIT_TRACE_CURL=1 or GIT_CURL_VERBOSE=1, sensitive headers like "Authorization" and "Cookie" get redacted. However, since [1], curl's h2h3 module (invoked when using HTTP/2) also prints headers in its "info", which don't get redacted. For example, echo 'github.com TRUE / FALSE 1698960413304 o foo=bar' >cookiefile && GIT_TRACE_CURL=1 GIT_TRACE_CURL_NO_DATA=1 git \ -c 'http.cookiefile=cookiefile' \ -c 'http.version=' \ ls-remote https://github.com/git/git refs/heads/main 2>output && grep 'cookie' output produces output like: 23:04:16.920495 http.c:678 == Info: h2h3 [cookie: o=foo=bar] 23:04:16.920562 http.c:637 => Send header: cookie: o=<redacted> Teach http.c to check for h2h3 headers in info and redact them using the existing header redaction logic. This fixes the broken redaction logic that we noted in the previous commit, so mark the redaction tests as passing under HTTP2. [1] curl/curl@f8c3724 Helped-by: Jeff King <[email protected]> Signed-off-by: Glen Choo <[email protected]> Signed-off-by: Taylor Blau <[email protected]>
1 parent 73c49a4 commit b637a41

File tree

2 files changed

+44
-9
lines changed

2 files changed

+44
-9
lines changed

http.c

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -560,13 +560,15 @@ static void set_curl_keepalive(CURL *c)
560560
}
561561
#endif
562562

563-
static void redact_sensitive_header(struct strbuf *header)
563+
/* Return 1 if redactions have been made, 0 otherwise. */
564+
static int redact_sensitive_header(struct strbuf *header, size_t offset)
564565
{
566+
int ret = 0;
565567
const char *sensitive_header;
566568

567569
if (trace_curl_redact &&
568-
(skip_iprefix(header->buf, "Authorization:", &sensitive_header) ||
569-
skip_iprefix(header->buf, "Proxy-Authorization:", &sensitive_header))) {
570+
(skip_iprefix(header->buf + offset, "Authorization:", &sensitive_header) ||
571+
skip_iprefix(header->buf + offset, "Proxy-Authorization:", &sensitive_header))) {
570572
/* The first token is the type, which is OK to log */
571573
while (isspace(*sensitive_header))
572574
sensitive_header++;
@@ -575,8 +577,9 @@ static void redact_sensitive_header(struct strbuf *header)
575577
/* Everything else is opaque and possibly sensitive */
576578
strbuf_setlen(header, sensitive_header - header->buf);
577579
strbuf_addstr(header, " <redacted>");
580+
ret = 1;
578581
} else if (trace_curl_redact &&
579-
skip_iprefix(header->buf, "Cookie:", &sensitive_header)) {
582+
skip_iprefix(header->buf + offset, "Cookie:", &sensitive_header)) {
580583
struct strbuf redacted_header = STRBUF_INIT;
581584
const char *cookie;
582585

@@ -612,6 +615,26 @@ static void redact_sensitive_header(struct strbuf *header)
612615

613616
strbuf_setlen(header, sensitive_header - header->buf);
614617
strbuf_addbuf(header, &redacted_header);
618+
ret = 1;
619+
}
620+
return ret;
621+
}
622+
623+
/* Redact headers in info */
624+
static void redact_sensitive_info_header(struct strbuf *header)
625+
{
626+
const char *sensitive_header;
627+
628+
/*
629+
* curl's h2h3 prints headers in info, e.g.:
630+
* h2h3 [<header-name>: <header-val>]
631+
*/
632+
if (trace_curl_redact &&
633+
skip_iprefix(header->buf, "h2h3 [", &sensitive_header)) {
634+
if (redact_sensitive_header(header, sensitive_header - header->buf)) {
635+
/* redaction ate our closing bracket */
636+
strbuf_addch(header, ']');
637+
}
615638
}
616639
}
617640

@@ -629,7 +652,7 @@ static void curl_dump_header(const char *text, unsigned char *ptr, size_t size,
629652

630653
for (header = headers; *header; header++) {
631654
if (hide_sensitive_header)
632-
redact_sensitive_header(*header);
655+
redact_sensitive_header(*header, 0);
633656
strbuf_insertstr((*header), 0, text);
634657
strbuf_insertstr((*header), strlen(text), ": ");
635658
strbuf_rtrim((*header));
@@ -668,14 +691,26 @@ static void curl_dump_data(const char *text, unsigned char *ptr, size_t size)
668691
strbuf_release(&out);
669692
}
670693

694+
static void curl_dump_info(char *data, size_t size)
695+
{
696+
struct strbuf buf = STRBUF_INIT;
697+
698+
strbuf_add(&buf, data, size);
699+
700+
redact_sensitive_info_header(&buf);
701+
trace_printf_key(&trace_curl, "== Info: %s", buf.buf);
702+
703+
strbuf_release(&buf);
704+
}
705+
671706
static int curl_trace(CURL *handle, curl_infotype type, char *data, size_t size, void *userp)
672707
{
673708
const char *text;
674709
enum { NO_FILTER = 0, DO_FILTER = 1 };
675710

676711
switch (type) {
677712
case CURLINFO_TEXT:
678-
trace_printf_key(&trace_curl, "== Info: %s", data);
713+
curl_dump_info(data, size);
679714
break;
680715
case CURLINFO_HEADER_OUT:
681716
text = "=> Send header";

t/t5551-http-fetch-smart.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ test_expect_success 'redirects send auth to new location' '
200200
expect_askpass both user@host auth/smart/repo.git
201201
'
202202

203-
test_expect_success !HTTP2 'GIT_TRACE_CURL redacts auth details' '
203+
test_expect_success 'GIT_TRACE_CURL redacts auth details' '
204204
rm -rf redact-auth trace &&
205205
set_askpass user@host pass@host &&
206206
GIT_TRACE_CURL="$(pwd)/trace" git clone --bare "$HTTPD_URL/auth/smart/repo.git" redact-auth &&
@@ -212,7 +212,7 @@ test_expect_success !HTTP2 'GIT_TRACE_CURL redacts auth details' '
212212
grep -i "Authorization: Basic <redacted>" trace
213213
'
214214

215-
test_expect_success !HTTP2 'GIT_CURL_VERBOSE redacts auth details' '
215+
test_expect_success 'GIT_CURL_VERBOSE redacts auth details' '
216216
rm -rf redact-auth trace &&
217217
set_askpass user@host pass@host &&
218218
GIT_CURL_VERBOSE=1 git clone --bare "$HTTPD_URL/auth/smart/repo.git" redact-auth 2>trace &&
@@ -482,7 +482,7 @@ test_expect_success 'fetch by SHA-1 without tag following' '
482482
--no-tags origin $(cat bar_hash)
483483
'
484484

485-
test_expect_success !HTTP2 'cookies are redacted by default' '
485+
test_expect_success 'cookies are redacted by default' '
486486
rm -rf clone &&
487487
echo "Set-Cookie: Foo=1" >cookies &&
488488
echo "Set-Cookie: Bar=2" >>cookies &&

0 commit comments

Comments
 (0)