new file mode 100644
@@ -0,0 +1,391 @@
+From c33bf4f354de43890aa6fd9dc52872a9f799068c 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:
+- curl-8.7.1 carries the redirect logic in lib/transfer.c via Curl_follow(),
+ so the credential reset changes were adapted there.
+- The upstream Curl_reset_proxypwd() helper also includes a
+ CURL_DISABLE_PROXY fallback hunk; that hunk is not carried in this 8.7.1
+ backport.
+- 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: Anil Dongare <adongare@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 ccd042b..a734629 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 e65b2b1..f1a791f 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 9fb9274..aafd309 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 0000000..d2fd79e
+--- /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 0000000..443ae9d
+--- /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 0000000..dd4e534
+--- /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>
+--
+2.43.7
@@ -37,6 +37,7 @@ SRC_URI = " \
file://CVE-2026-3783.patch \
file://CVE-2026-3784.patch \
file://CVE-2026-5545.patch \
+ file://CVE-2026-6253.patch \
"
SRC_URI:append:class-nativesdk = " \