curl: fix CVE-2026-6253

This patch applies the upstream backport for CVE-2026-6253.
The upstream fix commit is referenced in [1], and the public
CVE advisory is referenced in [2].

[1] https://github.com/curl/curl/commit/188c2f166a20fa97c2325b2da7d0e5cecc13725f
[2] https://curl.se/docs/CVE-2026-6253.html

(From OE-Core rev: 21a929291fddb4f7c874609f6d5293477fb74ad9)

Signed-off-by: Deepak Rathore <deeratho@cisco.com>
Signed-off-by: Fabien Thomas <fabien.thomas@smile.fr>
Signed-off-by: Paul Barker <paul@pbarker.dev>
This commit is contained in:
Deepak Rathore
2026-08-24 11:43:45 +01:00
committed by Paul Barker
parent 74cc040335
commit 6885998553
2 changed files with 393 additions and 0 deletions
@@ -0,0 +1,392 @@
From eb175878ffa07392d6654127f3d4637d4d335c78 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Fri, 5 Jun 2026 01:18:43 -0700
Subject: [PATCH] http: clear the proxy credentials as well on port or scheme
change
Add tests 2009-2011 to verify switching between proxies with credentials
when the switch is driven by a redirect
Reported-by: Dwij Mehta
Closes #21304
CVE: CVE-2026-6253
Upstream-Status: Backport [https://github.com/curl/curl/commit/188c2f166a20fa97c2325b2da7d0e5cecc13725f]
Backport Changes:
- The upstream lib/http.c hunk adds the credential resets to
Curl_http_follow(). curl-8.7.1 predates that protocol-specific redirect
handler and carries the equivalent logic in lib/transfer.c via
Curl_follow(), so the full upstream lib/http.c hunk was adapted there.
- The upstream Curl_reset_proxypwd() helper includes a CURL_DISABLE_PROXY
fallback. In curl-8.7.1, the proxy credential fields and string slots are
unconditional and the pre-existing code accesses them without that guard,
so this backport retains the target-version behavior instead.
- curl-8.7.1 uses tests/data/Makefile.inc instead of the upstream
tests/data/Makefile.am list.
(cherry picked from commit 188c2f166a20fa97c2325b2da7d0e5cecc13725f)
Signed-off-by: Deepak Rathore <deeratho@cisco.com>
---
lib/transfer.c | 56 ++++++++++++++++++++++++--------
lib/transfer.h | 2 ++
tests/data/Makefile.inc | 1 +
tests/data/test2009 | 70 ++++++++++++++++++++++++++++++++++++++++
tests/data/test2010 | 71 +++++++++++++++++++++++++++++++++++++++++
tests/data/test2011 | 70 ++++++++++++++++++++++++++++++++++++++++
6 files changed, 257 insertions(+), 13 deletions(-)
create mode 100644 tests/data/test2009
create mode 100644 tests/data/test2010
create mode 100644 tests/data/test2011
diff --git a/lib/transfer.c b/lib/transfer.c
index ccd042b80d..a73462928d 100644
--- a/lib/transfer.c
+++ b/lib/transfer.c
@@ -553,6 +553,35 @@ void Curl_init_CONNECT(struct Curl_easy *data)
data->state.upload = (data->state.httpreq == HTTPREQ_PUT);
}
+/*
+ * Restore the user credentials to those set in options.
+ */
+CURLcode Curl_reset_userpwd(struct Curl_easy *data)
+{
+ CURLcode result;
+ if(data->set.str[STRING_USERNAME] || data->set.str[STRING_PASSWORD])
+ data->state.creds_from = CREDS_OPTION;
+ result = Curl_setstropt(&data->state.aptr.user,
+ data->set.str[STRING_USERNAME]);
+ if(!result)
+ result = Curl_setstropt(&data->state.aptr.passwd,
+ data->set.str[STRING_PASSWORD]);
+ return result;
+}
+
+/*
+ * Restore the proxy credentials to those set in options.
+ */
+CURLcode Curl_reset_proxypwd(struct Curl_easy *data)
+{
+ CURLcode result = Curl_setstropt(&data->state.aptr.proxyuser,
+ data->set.str[STRING_PROXYUSERNAME]);
+ if(!result)
+ result = Curl_setstropt(&data->state.aptr.proxypasswd,
+ data->set.str[STRING_PROXYPASSWORD]);
+ return result;
+}
+
/*
* Curl_pretransfer() is called immediately before a transfer starts, and only
* once for one transfer no matter if it has redirects or do multi-pass
@@ -700,21 +729,10 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
return CURLE_OUT_OF_MEMORY;
}
- if(data->set.str[STRING_USERNAME] ||
- data->set.str[STRING_PASSWORD])
- data->state.creds_from = CREDS_OPTION;
- if(!result)
- result = Curl_setstropt(&data->state.aptr.user,
- data->set.str[STRING_USERNAME]);
- if(!result)
- result = Curl_setstropt(&data->state.aptr.passwd,
- data->set.str[STRING_PASSWORD]);
if(!result)
- result = Curl_setstropt(&data->state.aptr.proxyuser,
- data->set.str[STRING_PROXYUSERNAME]);
+ result = Curl_reset_userpwd(data);
if(!result)
- result = Curl_setstropt(&data->state.aptr.proxypasswd,
- data->set.str[STRING_PROXYPASSWORD]);
+ result = Curl_reset_proxypwd(data);
data->req.headerbytecount = 0;
Curl_headers_cleanup(data);
@@ -759,6 +777,7 @@ CURLcode Curl_follow(struct Curl_easy *data,
bool disallowport = FALSE;
bool reachedmax = FALSE;
CURLUcode uc;
+ CURLcode result;
DEBUGASSERT(type != FOLLOW_NONE);
@@ -889,12 +908,23 @@ CURLcode Curl_follow(struct Curl_easy *data,
free(scheme);
}
if(clear) {
+ result = Curl_reset_userpwd(data);
+ if(result) {
+ free(newurl);
+ return result;
+ }
Curl_safefree(data->state.aptr.user);
Curl_safefree(data->state.aptr.passwd);
}
}
}
+ result = Curl_reset_proxypwd(data);
+ if(result) {
+ free(newurl);
+ return result;
+ }
+
if(type == FOLLOW_FAKE) {
/* we're only figuring out the new url if we would've followed locations
but now we're done so we can get out! */
diff --git a/lib/transfer.h b/lib/transfer.h
index e65b2b1472..f1a791f1cf 100644
--- a/lib/transfer.h
+++ b/lib/transfer.h
@@ -31,6 +31,8 @@ char *Curl_checkheaders(const struct Curl_easy *data,
void Curl_init_CONNECT(struct Curl_easy *data);
+CURLcode Curl_reset_userpwd(struct Curl_easy *data);
+CURLcode Curl_reset_proxypwd(struct Curl_easy *data);
CURLcode Curl_pretransfer(struct Curl_easy *data);
CURLcode Curl_posttransfer(struct Curl_easy *data);
diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
index 9fb92742ee..aafd309a9d 100644
--- a/tests/data/Makefile.inc
+++ b/tests/data/Makefile.inc
@@ -231,6 +231,7 @@ test1955 test1956 test1957 test1958 test1959 test1960 test1964 \
test1970 test1971 test1972 test1973 test1974 test1975 \
\
test2000 test2001 test2002 test2003 test2004 test2005 test2006 \
+test2009 test2010 test2011 \
\
test2023 \
test2024 test2025 test2026 test2027 test2028 test2029 test2030 test2031 \
diff --git a/tests/data/test2009 b/tests/data/test2009
new file mode 100644
index 0000000000..d2fd79e0d6
--- /dev/null
+++ b/tests/data/test2009
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="US-ASCII"?>
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP proxy
+http_proxy
+</keywords>
+</info>
+# Server-side
+<reply>
+<connect>
+HTTP/1.1 407 Denied
+
+</connect>
+<data crlf="headers" nocheck="yes">
+HTTP/1.1 301 redirect
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 4
+Content-Type: text/html
+Location: https://another.example/%TESTNUMBER0002
+
+boo
+</data>
+</reply>
+
+# Client-side
+<client>
+<features>
+proxy
+</features>
+<server>
+http
+https
+</server>
+<name>
+proxy credentials via env variables, redirect from http to https
+</name>
+
+<setenv>
+http_proxy=http://user:secret@%HOSTIP:%HTTPPORT
+https_proxy=https://%HOSTIP:%HTTPSPORT/
+</setenv>
+<command>
+http://somewhere.example/ --follow --proxy-insecure
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<protocol crlf="headers">
+GET http://somewhere.example/ HTTP/1.1
+Host: somewhere.example
+Proxy-Authorization: Basic %b64[user:secret]b64%
+User-Agent: curl/%VERSION
+Accept: */*
+Proxy-Connection: Keep-Alive
+
+CONNECT another.example:443 HTTP/1.1
+Host: another.example:443
+User-Agent: curl/%VERSION
+Proxy-Connection: Keep-Alive
+
+</protocol>
+<errorcode>
+7
+</errorcode>
+</verify>
+</testcase>
diff --git a/tests/data/test2010 b/tests/data/test2010
new file mode 100644
index 0000000000..443ae9d2f9
--- /dev/null
+++ b/tests/data/test2010
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="US-ASCII"?>
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP proxy
+http_proxy
+</keywords>
+</info>
+# Server-side
+<reply>
+<connect>
+HTTP/1.1 407 Denied
+
+</connect>
+<data crlf="headers" nocheck="yes">
+HTTP/1.1 301 redirect
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 4
+Content-Type: text/html
+Location: https://another.example/%TESTNUMBER0002
+
+boo
+</data>
+</reply>
+
+# Client-side
+<client>
+<features>
+proxy
+</features>
+<server>
+http
+https
+</server>
+<name>
+proxy credentials via options for two proxies, redirect from http to https
+</name>
+
+<setenv>
+http_proxy=http://%HOSTIP:%HTTPPORT
+https_proxy=https://%HOSTIP:%HTTPSPORT/
+</setenv>
+<command>
+--proxy-user batman:robin http://somewhere.example/ --follow --proxy-insecure
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<protocol crlf="headers">
+GET http://somewhere.example/ HTTP/1.1
+Host: somewhere.example
+Proxy-Authorization: Basic %b64[batman:robin]b64%
+User-Agent: curl/%VERSION
+Accept: */*
+Proxy-Connection: Keep-Alive
+
+CONNECT another.example:443 HTTP/1.1
+Host: another.example:443
+Proxy-Authorization: Basic %b64[batman:robin]b64%
+User-Agent: curl/%VERSION
+Proxy-Connection: Keep-Alive
+
+</protocol>
+<errorcode>
+7
+</errorcode>
+</verify>
+</testcase>
diff --git a/tests/data/test2011 b/tests/data/test2011
new file mode 100644
index 0000000000..dd4e534248
--- /dev/null
+++ b/tests/data/test2011
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="US-ASCII"?>
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP proxy
+http_proxy
+</keywords>
+</info>
+# Server-side
+<reply>
+<connect>
+HTTP/1.1 407 Denied
+
+</connect>
+<data crlf="headers" nocheck="yes">
+HTTP/1.1 301 redirect
+Date: Tue, 09 Nov 2010 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 4
+Content-Type: text/html
+Location: https://another.example/%TESTNUMBER0002
+
+boo
+</data>
+</reply>
+
+# Client-side
+<client>
+<features>
+proxy
+</features>
+<server>
+http
+https
+</server>
+<name>
+proxy creds via env, cross-scheme redirect, --location-trusted
+</name>
+
+<setenv>
+http_proxy=http://user:secret@%HOSTIP:%HTTPPORT
+https_proxy=https://%HOSTIP:%HTTPSPORT/
+</setenv>
+<command>
+http://somewhere.example/ --location-trusted --proxy-insecure
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<protocol crlf="headers">
+GET http://somewhere.example/ HTTP/1.1
+Host: somewhere.example
+Proxy-Authorization: Basic %b64[user:secret]b64%
+User-Agent: curl/%VERSION
+Accept: */*
+Proxy-Connection: Keep-Alive
+
+CONNECT another.example:443 HTTP/1.1
+Host: another.example:443
+User-Agent: curl/%VERSION
+Proxy-Connection: Keep-Alive
+
+</protocol>
+<errorcode>
+7
+</errorcode>
+</verify>
+</testcase>
+1
View File
@@ -39,6 +39,7 @@ SRC_URI = " \
file://CVE-2026-5773.patch \
file://CVE-2026-6276.patch \
file://CVE-2026-5545.patch \
file://CVE-2026-6253.patch \
"
SRC_URI:append:class-nativesdk = " \