new file mode 100644
@@ -0,0 +1,346 @@
+From 929cc46864c5f047727a898f361d9bac86e73471 Mon Sep 17 00:00:00 2001
+From: Daniel Stenberg <daniel@haxx.se>
+Date: Fri, 5 Jun 2026 01:20:50 -0700
+Subject: [PATCH] http: clear credentials better on redirect
+
+Verify with test 2506: netrc with redirect using proxy
+
+Updated test 998 which was wrong.
+
+Reported-by: Muhamad Arga Reksapati
+
+Closes #21345
+
+CVE: CVE-2026-6429
+Upstream-Status: Backport [https://github.com/curl/curl/commit/b4024bf808bd558026fdc6096e8457f199ace306]
+
+Backport Changes:
+- curl-8.7.1 carries redirect handling in lib/transfer.c via Curl_follow(),
+ so the same-origin credential clearing logic was adapted there.
+- curl-8.7.1 uses tests/data/Makefile.inc and tests/libtest/Makefile.inc
+ instead of the upstream Automake lists.
+- test998 is not updated in this backport because the older 8.7.1 test data
+ does not carry the upstream drift that motivated that hunk.
+
+(cherry picked from commit b4024bf808bd558026fdc6096e8457f199ace306)
+Signed-off-by: Anil Dongare <adongare@cisco.com>
+---
+ lib/transfer.c | 103 +++++++++++++++++++++----------------
+ tests/data/Makefile.inc | 2 +-
+ tests/data/test2506 | 64 +++++++++++++++++++++++
+ tests/libtest/Makefile.inc | 5 +-
+ tests/libtest/lib2506.c | 71 +++++++++++++++++++++++++
+ 5 files changed, 198 insertions(+), 47 deletions(-)
+ create mode 100644 tests/data/test2506
+ create mode 100644 tests/libtest/lib2506.c
+
+diff --git a/lib/transfer.c b/lib/transfer.c
+index a734629..0f5bd8c 100644
+--- a/lib/transfer.c
++++ b/lib/transfer.c
+@@ -865,49 +865,62 @@ CURLcode Curl_follow(struct Curl_easy *data,
+ if(uc)
+ return Curl_uc_to_curlcode(uc);
+
+- /* Clear auth if this redirects to a different port number or protocol,
+- unless permitted */
+- if(!data->set.allow_auth_to_other_hosts && (type != FOLLOW_FAKE)) {
+- char *portnum;
+- int port;
+- bool clear = FALSE;
+-
+- if(data->set.use_port && data->state.allow_port)
+- /* a custom port is used */
+- port = (int)data->set.use_port;
+- else {
+- uc = curl_url_get(data->state.uh, CURLUPART_PORT, &portnum,
+- CURLU_DEFAULT_PORT);
+- if(uc) {
+- free(newurl);
+- return Curl_uc_to_curlcode(uc);
+- }
+- port = atoi(portnum);
+- free(portnum);
+- }
+- if(port != data->info.conn_remote_port) {
+- infof(data, "Clear auth, redirects to port from %u to %u",
+- data->info.conn_remote_port, port);
+- clear = TRUE;
++ if(type != FOLLOW_FAKE) {
++ bool same_origin;
++ CURLU *u;
++ char *oldscheme = NULL;
++ char *oldhost = NULL;
++ char *oldport = NULL;
++ char *newscheme = NULL;
++ char *newhost = NULL;
++ char *newport = NULL;
++
++ u = curl_url();
++ if(!u) {
++ free(newurl);
++ return CURLE_OUT_OF_MEMORY;
+ }
+- else {
+- char *scheme;
+- const struct Curl_handler *p;
+- uc = curl_url_get(data->state.uh, CURLUPART_SCHEME, &scheme, 0);
+- if(uc) {
+- free(newurl);
+- return Curl_uc_to_curlcode(uc);
+- }
+
+- p = Curl_get_scheme_handler(scheme);
+- if(p && (p->protocol != data->info.conn_protocol)) {
+- infof(data, "Clear auth, redirects scheme from %s to %s",
+- data->info.conn_scheme, scheme);
+- clear = TRUE;
+- }
+- free(scheme);
++ uc = curl_url_set(u, CURLUPART_URL, data->state.url, 0);
++ if(!uc)
++ uc = curl_url_get(u, CURLUPART_SCHEME, &oldscheme, 0);
++ if(!uc)
++ uc = curl_url_get(u, CURLUPART_HOST, &oldhost, 0);
++ if(!uc)
++ uc = curl_url_get(u, CURLUPART_PORT, &oldport, CURLU_DEFAULT_PORT);
++ if(!uc)
++ uc = curl_url_get(data->state.uh, CURLUPART_SCHEME, &newscheme, 0);
++ if(!uc)
++ uc = curl_url_get(data->state.uh, CURLUPART_HOST, &newhost, 0);
++ if(!uc)
++ uc = curl_url_get(data->state.uh, CURLUPART_PORT, &newport,
++ CURLU_DEFAULT_PORT);
++ if(uc) {
++ curl_url_cleanup(u);
++ free(oldscheme);
++ free(oldhost);
++ free(oldport);
++ free(newscheme);
++ free(newhost);
++ free(newport);
++ free(newurl);
++ return Curl_uc_to_curlcode(uc);
+ }
+- if(clear) {
++
++ same_origin = strcasecompare(oldscheme, newscheme) &&
++ strcasecompare(oldhost, newhost) &&
++ !strcmp(oldport, newport);
++
++ curl_url_cleanup(u);
++ free(oldscheme);
++ free(oldhost);
++ free(oldport);
++ free(newscheme);
++ free(newhost);
++ free(newport);
++
++ if((!same_origin && !data->set.allow_auth_to_other_hosts) ||
++ !data->set.str[STRING_USERNAME]) {
+ result = Curl_reset_userpwd(data);
+ if(result) {
+ free(newurl);
+@@ -917,12 +930,12 @@ CURLcode Curl_follow(struct Curl_easy *data,
+ Curl_safefree(data->state.aptr.passwd);
+ }
+ }
+- }
+
+- result = Curl_reset_proxypwd(data);
+- if(result) {
+- free(newurl);
+- return result;
++ result = Curl_reset_proxypwd(data);
++ if(result) {
++ free(newurl);
++ return result;
++ }
+ }
+
+ if(type == FOLLOW_FAKE) {
+diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
+index 9278dac..136b961 100644
+--- a/tests/data/Makefile.inc
++++ b/tests/data/Makefile.inc
+@@ -251,7 +251,7 @@ test2300 test2301 test2302 test2303 test2304 test2305 test2306 test2307 \
+ \
+ test2400 test2401 test2402 test2403 test2404 \
+ \
+-test2500 test2501 test2502 test2503 test2504 \
++test2500 test2501 test2502 test2503 test2504 test2506 \
+ \
+ test2600 test2601 test2602 test2603 \
+ \
+diff --git a/tests/data/test2506 b/tests/data/test2506
+new file mode 100644
+index 0000000..9c65002
+--- /dev/null
++++ b/tests/data/test2506
+@@ -0,0 +1,64 @@
++<?xml version="1.0" encoding="US-ASCII"?>
++<testcase>
++<info>
++<keywords>
++HTTP
++cookies
++</keywords>
++</info>
++
++<reply>
++<data crlf="headers" nocheck="yes">
++HTTP/1.1 301 redirect
++Date: Tue, 09 Nov 2010 14:49:00 GMT
++Content-Length: 3
++Location: http://numbertwo.example/%TESTNUMBER0002
++
++ok
++</data>
++<data2 crlf="headers" nocheck="yes">
++HTTP/1.1 200 OK
++Date: Tue, 09 Nov 2010 14:49:00 GMT
++Content-Length: 4
++
++yes
++</data2>
++</reply>
++
++<client>
++<server>
++http
++</server>
++<features>
++proxy
++</features>
++<tool>
++lib%TESTNUMBER
++</tool>
++<name>
++netrc with redirect using proxy
++</name>
++<file name="%LOGDIR/netrc2506">
++machine site.example login batman password robin
++</file>
++<command>
++http://%HOSTIP:%HTTPPORT http://site.example/ %LOGDIR/netrc2506
++</command>
++</client>
++
++<verify>
++<protocol crlf="headers">
++GET http://site.example/ HTTP/1.1
++Host: site.example
++Authorization: Basic %b64[batman:robin]b64%
++Accept: */*
++Proxy-Connection: Keep-Alive
++
++GET http://numbertwo.example/25060002 HTTP/1.1
++Host: numbertwo.example
++Accept: */*
++Proxy-Connection: Keep-Alive
++
++</protocol>
++</verify>
++</testcase>
+diff --git a/tests/libtest/Makefile.inc b/tests/libtest/Makefile.inc
+index 4653d12..0f140eb 100644
+--- a/tests/libtest/Makefile.inc
++++ b/tests/libtest/Makefile.inc
+@@ -75,7 +75,7 @@ noinst_PROGRAMS = chkhostname libauthretry libntlmconnect libprereq \
+ lib1970 lib1971 lib1972 lib1973 lib1974 lib1975 \
+ lib2301 lib2302 lib2304 lib2305 lib2306 \
+ lib2402 lib2404 \
+- lib2502 lib2504 \
++ lib2502 lib2504 lib2506 \
+ lib3010 lib3025 lib3026 lib3027 \
+ lib3100 lib3101 lib3102 lib3103
+
+@@ -687,6 +687,9 @@ lib2502_LDADD = $(TESTUTIL_LIBS)
+ lib2504_SOURCES = lib2504.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+ lib2504_LDADD = $(TESTUTIL_LIBS)
+
++lib2506_SOURCES = lib2506.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
++lib2506_LDADD = $(TESTUTIL_LIBS)
++
+ lib3010_SOURCES = lib3010.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+ lib3010_LDADD = $(TESTUTIL_LIBS)
+
+diff --git a/tests/libtest/lib2506.c b/tests/libtest/lib2506.c
+new file mode 100644
+index 0000000..8b3b342
+--- /dev/null
++++ b/tests/libtest/lib2506.c
+@@ -0,0 +1,71 @@
++/***************************************************************************
++ * _ _ ____ _
++ * Project ___| | | | _ \| |
++ * / __| | | | |_) | |
++ * | (__| |_| | _ <| |___
++ * \___|\___/|_| \_\_____|
++ *
++ * Copyright (C) Linus Nielsen Feltzing <linus@haxx.se>
++ *
++ * This software is licensed as described in the file COPYING, which
++ * you should have received as part of this distribution. The terms
++ * are also available at https://curl.se/docs/copyright.html.
++ *
++ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
++ * copies of the Software, and permit persons to whom the Software is
++ * furnished to do so, under the terms of the COPYING file.
++ *
++ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
++ * KIND, either express or implied.
++ *
++ * SPDX-License-Identifier: curl
++ *
++ ***************************************************************************/
++#include "first.h"
++
++#include "testtrace.h"
++
++static size_t sink2506(char *ptr, size_t size, size_t nmemb, void *ud)
++{
++ (void)ptr;
++ (void)ud;
++ return size * nmemb;
++}
++
++static CURLcode test_lib2506(const char *URL)
++{
++ CURL *curl;
++ CURLcode result = CURLE_OUT_OF_MEMORY;
++
++ if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
++ curl_mfprintf(stderr, "curl_global_init() failed\n");
++ return TEST_ERR_MAJOR_BAD;
++ }
++
++ curl = curl_easy_init();
++ if(!curl) {
++ curl_mfprintf(stderr, "curl_easy_init() failed\n");
++ curl_global_cleanup();
++ return TEST_ERR_MAJOR_BAD;
++ }
++
++ test_setopt(curl, CURLOPT_WRITEFUNCTION, sink2506);
++ test_setopt(curl, CURLOPT_PROXY, URL);
++ test_setopt(curl, CURLOPT_URL, libtest_arg2);
++ test_setopt(curl, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
++ test_setopt(curl, CURLOPT_NETRC_FILE, libtest_arg3);
++ test_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
++ test_setopt(curl, CURLOPT_VERBOSE, 1L);
++
++ /* CURLOPT_UNRESTRICTED_AUTH should not make a difference because the
++ credentials come from netrc */
++ test_setopt(curl, CURLOPT_UNRESTRICTED_AUTH, 1L);
++
++ result = curl_easy_perform(curl);
++
++test_cleanup:
++ curl_easy_cleanup(curl);
++ curl_global_cleanup();
++
++ return result;
++}
+--
+2.43.7
@@ -39,6 +39,7 @@ SRC_URI = " \
file://CVE-2026-5545.patch \
file://CVE-2026-6253.patch \
file://CVE-2026-6276.patch \
+ file://CVE-2026-6429.patch \
"
SRC_URI:append:class-nativesdk = " \