From a36384ab94b868b70b39209ced3e89927a14922d Mon Sep 17 00:00:00 2001 From: Alhuda Khan Date: Fri, 26 Jun 2026 02:18:07 +0530 Subject: [PATCH] http: trim custom header name before the Authorization drop A custom header name padded with blanks (`Authorization :`) missed the exact-length compare and slipped past the cross-host Authorization and Cookie drop, forwarding the header to the redirect target. Trim the parsed name in both the request and proxy CONNECT header builders. Closes #22178 --- lib/http.c | 6 +++ lib/http_proxy.c | 3 ++ tests/data/Makefile.am | 2 +- tests/data/test2113 | 94 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 tests/data/test2113 diff --git a/lib/http.c b/lib/http.c index 072b1ed3b4..d952b90ceb 100644 --- a/lib/http.c +++ b/lib/http.c @@ -1805,6 +1805,12 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data, continue; } + /* a field name is a token and carries no surrounding whitespace, so + trim the parsed name before matching. Otherwise `Authorization :` + (space before the colon) slips past the Authorization/Cookie check + below and gets forwarded to another host on a redirect. */ + curlx_str_trimblanks(&name); + /* only send this if the contents was non-blank or done special */ if(data->state.aptr.host && diff --git a/lib/http_proxy.c b/lib/http_proxy.c index b2cb018c10..aa20a52ebe 100644 --- a/lib/http_proxy.c +++ b/lib/http_proxy.c @@ -129,6 +129,9 @@ static CURLcode dynhds_add_custom(struct Curl_easy *data, continue; DEBUGASSERT(curlx_strlen(&name) && value); + /* trim surrounding whitespace so a padded field name (e.g. + `Authorization :`) cannot slip past the Authorization/Cookie check */ + curlx_str_trimblanks(&name); if(data->state.aptr.host && /* a Host: header was sent already, do not pass on any custom Host: header as that will produce *two* in the same request! */ diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am index 0ef33e0adc..2edc771070 100644 --- a/tests/data/Makefile.am +++ b/tests/data/Makefile.am @@ -254,7 +254,7 @@ test2072 test2073 test2074 test2075 test2076 test2077 test2078 test2079 \ test2080 test2081 test2082 test2083 test2084 test2085 test2086 test2087 \ test2088 test2089 test2090 test2091 test2092 \ test2100 test2101 test2102 test2103 test2104 test2105 test2106 test2107 \ -test2108 test2109 \ +test2108 test2109 test2113 \ \ test2200 test2201 test2202 test2203 test2204 test2205 test2206 test2207 \ test2208 \ diff --git a/tests/data/test2113 b/tests/data/test2113 new file mode 100644 index 0000000000..884c0af0a7 --- /dev/null +++ b/tests/data/test2113 @@ -0,0 +1,94 @@ + + + + +HTTP +HTTP proxy +HTTP Basic auth +HTTP proxy Basic auth +followlocation + + +# Server-side + + +HTTP/1.1 302 OK +Date: Tue, 09 Nov 2010 14:49:00 GMT +Server: test-server/fake swsclose +Content-Type: text/html +Funny-head: yesyes +Location: http://goto.second.host.now/%TESTNUMBER0002 +Content-Length: 8 +Connection: close + +contents + + +HTTP/1.1 200 OK +Date: Tue, 09 Nov 2010 14:49:00 GMT +Server: test-server/fake swsclose +Content-Type: text/html +Funny-head: yesyes +Content-Length: 9 + +contents + + + +HTTP/1.1 302 OK +Date: Tue, 09 Nov 2010 14:49:00 GMT +Server: test-server/fake swsclose +Content-Type: text/html +Funny-head: yesyes +Location: http://goto.second.host.now/%TESTNUMBER0002 +Content-Length: 8 +Connection: close + +HTTP/1.1 200 OK +Date: Tue, 09 Nov 2010 14:49:00 GMT +Server: test-server/fake swsclose +Content-Type: text/html +Funny-head: yesyes +Content-Length: 9 + +contents + + + +# Client-side + + +http + + +HTTP custom Authorization: with whitespace before colon and redirect to new host + + +http://first.host.it.is/we/want/that/page/%TESTNUMBER -x %HOSTIP:%HTTPPORT -H "Authorization : s3cr3t" --proxy-user testing:this --location + + +proxy + + + +# Verify data after the test has been "shot" + + +GET http://first.host.it.is/we/want/that/page/%TESTNUMBER HTTP/1.1 +Host: first.host.it.is +Proxy-Authorization: Basic %b64[testing:this]b64% +User-Agent: curl/%VERSION +Accept: */* +Proxy-Connection: Keep-Alive +Authorization : s3cr3t + +GET http://goto.second.host.now/%TESTNUMBER0002 HTTP/1.1 +Host: goto.second.host.now +Proxy-Authorization: Basic %b64[testing:this]b64% +User-Agent: curl/%VERSION +Accept: */* +Proxy-Connection: Keep-Alive + + + +