Version in base suite: 8.14.1-2+deb13u3 Base version: curl_8.14.1-2+deb13u3 Target version: curl_8.14.1-2+deb13u4 Base file: /srv/ftp-master.debian.org/ftp/pool/main/c/curl/curl_8.14.1-2+deb13u3.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/c/curl/curl_8.14.1-2+deb13u4.dsc changelog | 22 patches/CVE-2025-10148.patch | 2 patches/CVE-2025-13034.patch | 5 patches/CVE-2025-14524.patch | 40 patches/CVE-2025-14819.patch | 71 + patches/CVE-2026-1965_1.patch | 139 +++ patches/CVE-2026-1965_2.patch | 27 patches/CVE-2026-3783.patch | 134 +++ patches/CVE-2026-3784.patch | 165 +++ patches/CVE-2026-3805.patch | 65 + patches/CVE-2026-4873.patch | 46 + patches/CVE-2026-5545.patch | 39 patches/CVE-2026-5773.patch | 44 + patches/CVE-2026-6253.patch | 386 +++++++++ patches/CVE-2026-6276.patch | 377 +++++++++ patches/CVE-2026-6429.patch | 345 ++++++++ patches/CVE-2026-7168.patch | 417 ++++++++++ patches/cookie-don-t-treat-the-leading-slash-as-trailing.patch | 6 patches/curl_path_make_SFTP_handle_a_path.patch | 3 patches/series | 21 patches/tool_getparam_fix_ftp_pasv.patch | 113 +- patches/tool_operate_fix_return_code_when_retry_is_used_but_not_triggered.patch | 139 +-- patches/wcurl-Fix-example-for-continue-at.patch | 1 patches/wcurl-Set-CURL_OPTIONS-right-before-the-url.patch | 1 24 files changed, 2445 insertions(+), 163 deletions(-) dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpkmwdjl84/curl_8.14.1-2+deb13u3.dsc: no acceptable signature found dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmpkmwdjl84/curl_8.14.1-2+deb13u4.dsc: no acceptable signature found diff -Nru curl-8.14.1/debian/changelog curl-8.14.1/debian/changelog --- curl-8.14.1/debian/changelog 2026-01-30 02:20:09.000000000 +0000 +++ curl-8.14.1/debian/changelog 2026-05-08 01:36:52.000000000 +0000 @@ -1,3 +1,25 @@ +curl (8.14.1-2+deb13u4) trixie; urgency=medium + + * Import upstream patches for 13 CVE fixes: + - CVE-2025-14524 + - CVE-2025-14819 + - CVE-2026-1965 + - CVE-2026-3783 + - CVE-2026-3784 + - CVE-2026-3805 + - CVE-2026-4873 + - CVE-2026-5545 + - CVE-2026-5773 + - CVE-2026-6253 + - CVE-2026-6276 + - CVE-2026-6429 + - CVE-2026-7168 + * d/p/CVE-2025-10148.patch: drop format-patch artefacts + * d/p/CVE-2025-13034.patch: refresh after gbp pq round-trip + * d/p: refresh patch series after gbp pq round-trip + + -- Samuel Henrique Thu, 07 May 2026 18:36:52 -0700 + curl (8.14.1-2+deb13u3) trixie; urgency=medium * Team upload. diff -Nru curl-8.14.1/debian/patches/CVE-2025-10148.patch curl-8.14.1/debian/patches/CVE-2025-10148.patch --- curl-8.14.1/debian/patches/CVE-2025-10148.patch 2026-01-30 02:20:09.000000000 +0000 +++ curl-8.14.1/debian/patches/CVE-2025-10148.patch 2026-05-08 01:36:52.000000000 +0000 @@ -1,4 +1,3 @@ -From 84db7a9eae8468c0445b15aa806fa7fa806fa0f2 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 8 Sep 2025 14:14:15 +0200 Subject: [PATCH] ws: get a new mask for each new outgoing frame @@ -11,7 +10,6 @@ Changes: * Refresh patch context for lib/ws.c * Adapt return value to current function return type - --- lib/ws.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff -Nru curl-8.14.1/debian/patches/CVE-2025-13034.patch curl-8.14.1/debian/patches/CVE-2025-13034.patch --- curl-8.14.1/debian/patches/CVE-2025-13034.patch 2026-01-30 02:20:09.000000000 +0000 +++ curl-8.14.1/debian/patches/CVE-2025-13034.patch 2026-05-08 01:36:52.000000000 +0000 @@ -1,6 +1,7 @@ From: Daniel Stenberg Date: Fri, 14 Nov 2025 16:42:23 +0100 -Subject: [PATCH] vquic-tls/gnutls: call Curl_gtls_verifyserver unconditionally +Subject: [PATCH] vquic-tls/gnutls: call Curl_gtls_verifyserver + unconditionally Closes #19531 @@ -21,7 +22,7 @@ 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/lib/vquic/vquic-tls.c b/lib/vquic/vquic-tls.c -index 2a5be13..b8b0e6b 100644 +index 2a5be13..e5c3ee9 100644 --- a/lib/vquic/vquic-tls.c +++ b/lib/vquic/vquic-tls.c @@ -169,13 +169,11 @@ CURLcode Curl_vquic_tls_verify_peer(struct curl_tls_ctx *ctx, diff -Nru curl-8.14.1/debian/patches/CVE-2025-14524.patch curl-8.14.1/debian/patches/CVE-2025-14524.patch --- curl-8.14.1/debian/patches/CVE-2025-14524.patch 1970-01-01 00:00:00.000000000 +0000 +++ curl-8.14.1/debian/patches/CVE-2025-14524.patch 2026-05-08 01:36:52.000000000 +0000 @@ -0,0 +1,40 @@ +From: Daniel Stenberg +Date: Wed, 10 Dec 2025 11:40:47 +0100 +Subject: [PATCH] curl_sasl: if redirected, require permission to use bearer + +Closes #19933 + +Backported-by: Samuel Henrique + * Refresh patch context for lib/curl_sasl.c +--- + lib/curl_sasl.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/lib/curl_sasl.c b/lib/curl_sasl.c +index 4fcbaac..8706491 100644 +--- a/lib/curl_sasl.c ++++ b/lib/curl_sasl.c +@@ -356,7 +356,10 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data, + data->set.str[STRING_SERVICE_NAME] : + sasl->params->service; + #endif +- const char *oauth_bearer = data->set.str[STRING_BEARER]; ++ const char *oauth_bearer = ++ (!data->state.this_is_a_follow || data->set.allow_auth_to_other_hosts) ? ++ data->set.str[STRING_BEARER] : NULL; ++ + struct bufref nullmsg; + + Curl_conn_get_host(data, FIRSTSOCKET, &hostname, &disp_hostname, &port); +@@ -543,7 +546,10 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data, + data->set.str[STRING_SERVICE_NAME] : + sasl->params->service; + #endif +- const char *oauth_bearer = data->set.str[STRING_BEARER]; ++ const char *oauth_bearer = ++ (!data->state.this_is_a_follow || data->set.allow_auth_to_other_hosts) ? ++ data->set.str[STRING_BEARER] : NULL; ++ + struct bufref serverdata; + + Curl_conn_get_host(data, FIRSTSOCKET, &hostname, &disp_hostname, &port); diff -Nru curl-8.14.1/debian/patches/CVE-2025-14819.patch curl-8.14.1/debian/patches/CVE-2025-14819.patch --- curl-8.14.1/debian/patches/CVE-2025-14819.patch 1970-01-01 00:00:00.000000000 +0000 +++ curl-8.14.1/debian/patches/CVE-2025-14819.patch 2026-05-08 01:36:52.000000000 +0000 @@ -0,0 +1,71 @@ +From: Daniel Stenberg +Date: Wed, 17 Dec 2025 10:54:16 +0100 +Subject: [PATCH] openssl: toggling CURLSSLOPT_NO_PARTIALCHAIN makes a + different CA cache + +Reported-by: Stanislav Fort + +Closes #20009 + +Backported-by: Samuel Henrique + * Refresh patch context for lib/vtls/openssl.c +--- + lib/vtls/openssl.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c +index 0ce09ca..b6d03f8 100644 +--- a/lib/vtls/openssl.c ++++ b/lib/vtls/openssl.c +@@ -3457,6 +3457,7 @@ struct ossl_x509_share { + char *CAfile; /* CAfile path used to generate X509 store */ + X509_STORE *store; /* cached X509 store or NULL if none */ + struct curltime time; /* when the cached store was created */ ++ BIT(no_partialchain); /* keep partial chain state */ + }; + + static void oss_x509_share_free(void *key, size_t key_len, void *p) +@@ -3491,12 +3492,16 @@ ossl_cached_x509_store_expired(const struct Curl_easy *data, + + static bool + ossl_cached_x509_store_different(struct Curl_cfilter *cf, ++ const struct Curl_easy *data, + const struct ossl_x509_share *mb) + { + struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); ++ struct ssl_config_data *ssl_config = ++ Curl_ssl_cf_get_config(cf, CURL_UNCONST(data)); ++ if(mb->no_partialchain != ssl_config->no_partialchain) ++ return TRUE; + if(!mb->CAfile || !conn_config->CAfile) + return mb->CAfile != conn_config->CAfile; +- + return strcmp(mb->CAfile, conn_config->CAfile); + } + +@@ -3513,7 +3518,7 @@ static X509_STORE *ossl_get_cached_x509_store(struct Curl_cfilter *cf, + sizeof(MPROTO_OSSL_X509_KEY)-1) : NULL; + if(share && share->store && + !ossl_cached_x509_store_expired(data, share) && +- !ossl_cached_x509_store_different(cf, share)) { ++ !ossl_cached_x509_store_different(cf, data, share)) { + store = share->store; + } + +@@ -3550,6 +3555,8 @@ static void ossl_set_cached_x509_store(struct Curl_cfilter *cf, + + if(X509_STORE_up_ref(store)) { + char *CAfile = NULL; ++ struct ssl_config_data *ssl_config = ++ Curl_ssl_cf_get_config(cf, CURL_UNCONST(data)); + + if(conn_config->CAfile) { + CAfile = strdup(conn_config->CAfile); +@@ -3567,6 +3574,7 @@ static void ossl_set_cached_x509_store(struct Curl_cfilter *cf, + share->time = curlx_now(); + share->store = store; + share->CAfile = CAfile; ++ share->no_partialchain = ssl_config->no_partialchain; + } + } + diff -Nru curl-8.14.1/debian/patches/CVE-2026-1965_1.patch curl-8.14.1/debian/patches/CVE-2026-1965_1.patch --- curl-8.14.1/debian/patches/CVE-2026-1965_1.patch 1970-01-01 00:00:00.000000000 +0000 +++ curl-8.14.1/debian/patches/CVE-2026-1965_1.patch 2026-05-08 01:36:52.000000000 +0000 @@ -0,0 +1,139 @@ +From: Daniel Stenberg +Date: Thu, 5 Feb 2026 08:34:21 +0100 +Subject: [PATCH] url: fix reuse of connections using HTTP Negotiate + +Assume Negotiate means connection-based + +Reported-by: Zhicheng Chen +Closes #20534 + +Backported-by: Samuel Henrique + * Refresh patch context for lib/url.c + * Swap needle->scheme->protocol with needle->handler->protocol, + upstream changed it after the release we ship, at: + https://github.com/curl/curl/commit/8edc0338f30f458f812f9ea355de1240771fa343. +--- + lib/url.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 82 insertions(+), 5 deletions(-) + +diff --git a/lib/url.c b/lib/url.c +index 10e37ec..d9b2166 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -817,6 +817,8 @@ struct url_conn_match { + BIT(may_multiplex); + BIT(want_ntlm_http); + BIT(want_proxy_ntlm_http); ++ BIT(want_nego_http); ++ BIT(want_proxy_nego_http); + + BIT(wait_pipe); + BIT(force_reuse); +@@ -1239,6 +1241,63 @@ static bool url_match_auth_ntlm(struct connectdata *conn, + #define url_match_auth_ntlm(c,m) ((void)c, (void)m, TRUE) + #endif + ++#ifdef USE_SPNEGO ++static bool url_match_auth_nego(struct connectdata *conn, ++ struct url_conn_match *m) ++{ ++ /* If we are looking for an HTTP+Negotiate connection, check if this is ++ already authenticating with the right credentials. If not, keep looking ++ so that we can reuse Negotiate connections if possible. */ ++ if(m->want_nego_http) { ++ if(Curl_timestrcmp(m->needle->user, conn->user) || ++ Curl_timestrcmp(m->needle->passwd, conn->passwd)) ++ return FALSE; ++ } ++ else if(conn->http_negotiate_state != GSS_AUTHNONE) { ++ /* Connection is using Negotiate auth but we do not want Negotiate */ ++ return FALSE; ++ } ++ ++#ifndef CURL_DISABLE_PROXY ++ /* Same for Proxy Negotiate authentication */ ++ if(m->want_proxy_nego_http) { ++ /* Both conn->http_proxy.user and conn->http_proxy.passwd can be ++ * NULL */ ++ if(!conn->http_proxy.user || !conn->http_proxy.passwd) ++ return FALSE; ++ ++ if(Curl_timestrcmp(m->needle->http_proxy.user, ++ conn->http_proxy.user) || ++ Curl_timestrcmp(m->needle->http_proxy.passwd, ++ conn->http_proxy.passwd)) ++ return FALSE; ++ } ++ else if(conn->proxy_negotiate_state != GSS_AUTHNONE) { ++ /* Proxy connection is using Negotiate auth but we do not want Negotiate */ ++ return FALSE; ++ } ++#endif ++ if(m->want_ntlm_http || m->want_proxy_ntlm_http) { ++ /* Credentials are already checked, we may use this connection. We MUST ++ * use a connection where it has already been fully negotiated. If it has ++ * not, we keep on looking for a better one. */ ++ m->found = conn; ++ if((m->want_nego_http && ++ (conn->http_negotiate_state != GSS_AUTHNONE)) || ++ (m->want_proxy_nego_http && ++ (conn->proxy_negotiate_state != GSS_AUTHNONE))) { ++ /* We must use this connection, no other */ ++ m->force_reuse = TRUE; ++ return TRUE; ++ } ++ return FALSE; /* get another */ ++ } ++ return TRUE; ++} ++#else ++#define url_match_auth_nego(c, m) ((void)c, (void)m, TRUE) ++#endif ++ + static bool url_match_conn(struct connectdata *conn, void *userdata) + { + struct url_conn_match *m = userdata; +@@ -1281,6 +1340,11 @@ static bool url_match_conn(struct connectdata *conn, void *userdata) + else if(m->force_reuse) + return TRUE; + ++ if(!url_match_auth_nego(conn, m)) ++ return FALSE; ++ else if(m->force_reuse) ++ return TRUE; ++ + if(!url_match_multiplex_limits(conn, m)) + return FALSE; + +@@ -1347,13 +1411,26 @@ ConnectionExists(struct Curl_easy *data, + match.may_multiplex = xfer_may_multiplex(data, needle); + + #ifdef USE_NTLM +- match.want_ntlm_http = ((data->state.authhost.want & CURLAUTH_NTLM) && +- (needle->handler->protocol & PROTO_FAMILY_HTTP)); ++ match.want_ntlm_http = ++ (data->state.authhost.want & CURLAUTH_NTLM) && ++ (needle->handler->protocol & PROTO_FAMILY_HTTP); + #ifndef CURL_DISABLE_PROXY + match.want_proxy_ntlm_http = +- (needle->bits.proxy_user_passwd && +- (data->state.authproxy.want & CURLAUTH_NTLM) && +- (needle->handler->protocol & PROTO_FAMILY_HTTP)); ++ needle->bits.proxy_user_passwd && ++ (data->state.authproxy.want & CURLAUTH_NTLM) && ++ (needle->handler->protocol & PROTO_FAMILY_HTTP); ++#endif ++#endif ++ ++#if !defined(CURL_DISABLE_HTTP) && defined(USE_SPNEGO) ++ match.want_nego_http = ++ (data->state.authhost.want & CURLAUTH_NEGOTIATE) && ++ (needle->handler->protocol & PROTO_FAMILY_HTTP); ++#ifndef CURL_DISABLE_PROXY ++ match.want_proxy_nego_http = ++ needle->bits.proxy_user_passwd && ++ (data->state.authproxy.want & CURLAUTH_NEGOTIATE) && ++ (needle->handler->protocol & PROTO_FAMILY_HTTP); + #endif + #endif + diff -Nru curl-8.14.1/debian/patches/CVE-2026-1965_2.patch curl-8.14.1/debian/patches/CVE-2026-1965_2.patch --- curl-8.14.1/debian/patches/CVE-2026-1965_2.patch 1970-01-01 00:00:00.000000000 +0000 +++ curl-8.14.1/debian/patches/CVE-2026-1965_2.patch 2026-05-08 01:36:52.000000000 +0000 @@ -0,0 +1,27 @@ +From: Daniel Stenberg +Date: Sat, 21 Feb 2026 18:11:41 +0100 +Subject: [PATCH] url: fix copy and paste url_match_auth_nego mistake + +Follow-up to 34fa034 +Reported-by: dahmono on github +Closes #20662 + +Backported-by: Samuel Henrique + * Refresh patch context for lib/url.c +--- + lib/url.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/url.c b/lib/url.c +index d9b2166..0c9b878 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -1277,7 +1277,7 @@ static bool url_match_auth_nego(struct connectdata *conn, + return FALSE; + } + #endif +- if(m->want_ntlm_http || m->want_proxy_ntlm_http) { ++ if(m->want_nego_http || m->want_proxy_nego_http) { + /* Credentials are already checked, we may use this connection. We MUST + * use a connection where it has already been fully negotiated. If it has + * not, we keep on looking for a better one. */ diff -Nru curl-8.14.1/debian/patches/CVE-2026-3783.patch curl-8.14.1/debian/patches/CVE-2026-3783.patch --- curl-8.14.1/debian/patches/CVE-2026-3783.patch 1970-01-01 00:00:00.000000000 +0000 +++ curl-8.14.1/debian/patches/CVE-2026-3783.patch 2026-05-08 01:36:52.000000000 +0000 @@ -0,0 +1,134 @@ +From: Daniel Stenberg +Date: Fri, 6 Mar 2026 23:13:07 +0100 +Subject: [PATCH] http: only send bearer if auth is allowed + +Verify with test 2006 + +Closes #20843 + +Backported-by: Samuel Henrique + * Refresh patch context for lib/http.c + * Adapt the new tests/data/test2006: reuse the + existing test486 as the base (similarity-copy in the diff), keep the + test definition structurally as upstream wants but also drop the two + now-stale "#" comment lines that already differ between upstream's and + our test486. +--- + lib/http.c | 5 +++-- + tests/data/Makefile.am | 2 +- + tests/data/{test486 => test2006} | 43 +++++++++++++++++----------------------- + 3 files changed, 22 insertions(+), 28 deletions(-) + copy tests/data/{test486 => test2006} (83%) + +diff --git a/lib/http.c b/lib/http.c +index 5942d31..4e15784 100644 +--- a/lib/http.c ++++ b/lib/http.c +@@ -696,8 +696,9 @@ output_auth_headers(struct Curl_easy *data, + #ifndef CURL_DISABLE_BEARER_AUTH + if(authstatus->picked == CURLAUTH_BEARER) { + /* Bearer */ +- if((!proxy && data->set.str[STRING_BEARER] && +- !Curl_checkheaders(data, STRCONST("Authorization")))) { ++ if(!proxy && data->set.str[STRING_BEARER] && ++ Curl_auth_allowed_to_host(data) && ++ !Curl_checkheaders(data, STRCONST("Authorization"))) { + auth = "Bearer"; + result = http_output_bearer(data); + if(result) +diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am +index ab21e0e..934ba80 100644 +--- a/tests/data/Makefile.am ++++ b/tests/data/Makefile.am +@@ -242,7 +242,7 @@ test1955 test1956 test1957 test1958 test1959 test1960 test1964 \ + test1970 test1971 test1972 test1973 test1974 test1975 test1976 test1977 \ + test1978 test1979 test1980 \ + \ +-test2000 test2001 test2002 test2003 test2004 test2005 \ ++test2000 test2001 test2002 test2003 test2004 test2005 test2006 \ + \ + test2023 \ + test2024 test2025 test2026 test2027 test2028 test2029 test2030 test2031 \ +diff --git a/tests/data/test486 b/tests/data/test2006 +similarity index 83% +copy from tests/data/test486 +copy to tests/data/test2006 +index 53efae5..4b8b269 100644 +--- a/tests/data/test486 ++++ b/tests/data/test2006 +@@ -1,3 +1,4 @@ ++ + + + +@@ -5,7 +6,6 @@ netrc + HTTP + + +-# + # Server-side + + +@@ -59,7 +59,6 @@ target + + + +-# + # Client-side + + +@@ -69,37 +68,31 @@ http + proxy + + +-.netrc with redirect and "default" with no password or login ++.netrc default with redirect plus oauth2-bearer + + +---netrc --netrc-file %LOGDIR/netrc%TESTNUMBER -L -x http://%HOSTIP:%HTTPPORT/ http://a.com/ ++--netrc --netrc-file %LOGDIR/netrc%TESTNUMBER --oauth2-bearer SECRET_TOKEN -L -x http://%HOSTIP:%HTTPPORT/ http://a.com/ + + +- +-machine a.com +- login alice +- password alicespassword +- +-default +- ++default login testuser password testpass + + + + +- +-GET http://a.com/ HTTP/1.1 +-Host: a.com +-Authorization: Basic %b64[alice:alicespassword]b64% +-User-Agent: curl/%VERSION +-Accept: */* +-Proxy-Connection: Keep-Alive +- +-GET http://b.com/%TESTNUMBER0002 HTTP/1.1 +-Host: b.com +-User-Agent: curl/%VERSION +-Accept: */* +-Proxy-Connection: Keep-Alive +- ++ ++GET http://a.com/ HTTP/1.1 ++Host: a.com ++Authorization: Bearer SECRET_TOKEN ++User-Agent: curl/%VERSION ++Accept: */* ++Proxy-Connection: Keep-Alive ++ ++GET http://b.com/%TESTNUMBER0002 HTTP/1.1 ++Host: b.com ++User-Agent: curl/%VERSION ++Accept: */* ++Proxy-Connection: Keep-Alive ++ + + + diff -Nru curl-8.14.1/debian/patches/CVE-2026-3784.patch curl-8.14.1/debian/patches/CVE-2026-3784.patch --- curl-8.14.1/debian/patches/CVE-2026-3784.patch 1970-01-01 00:00:00.000000000 +0000 +++ curl-8.14.1/debian/patches/CVE-2026-3784.patch 2026-05-08 01:36:52.000000000 +0000 @@ -0,0 +1,165 @@ +From: Stefan Eissing +Date: Fri, 6 Mar 2026 14:54:09 +0100 +Subject: [PATCH] proxy-auth: additional tests + +Also eliminate the special handling for socks proxy match. + +Closes #20837 + +Backported-by: Samuel Henrique + * Refresh patch context for lib/url.c +--- + lib/url.c | 30 +++++++----------------------- + tests/http/test_13_proxy_auth.py | 20 ++++++++++++++++++++ + tests/http/testenv/curl.py | 18 +++++++++++++++--- + 3 files changed, 42 insertions(+), 26 deletions(-) + +diff --git a/lib/url.c b/lib/url.c +index 0c9b878..efd50a0 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -640,34 +640,19 @@ proxy_info_matches(const struct proxy_info *data, + { + if((data->proxytype == needle->proxytype) && + (data->port == needle->port) && +- strcasecompare(data->host.name, needle->host.name)) ++ curl_strequal(data->host.name, needle->host.name)) { ++ ++ if(Curl_timestrcmp(data->user, needle->user) || ++ Curl_timestrcmp(data->passwd, needle->passwd)) ++ return FALSE; + return TRUE; +- ++ } + return FALSE; + } + +-static bool +-socks_proxy_info_matches(const struct proxy_info *data, +- const struct proxy_info *needle) +-{ +- if(!proxy_info_matches(data, needle)) +- return FALSE; +- +- /* the user information is case-sensitive +- or at least it is not defined as case-insensitive +- see https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.1 */ +- +- /* curl_strequal does a case insensitive comparison, +- so do not use it here! */ +- if(Curl_timestrcmp(data->user, needle->user) || +- Curl_timestrcmp(data->passwd, needle->passwd)) +- return FALSE; +- return TRUE; +-} + #else + /* disabled, will not get called */ + #define proxy_info_matches(x,y) FALSE +-#define socks_proxy_info_matches(x,y) FALSE + #endif + + /* A connection has to have been idle for a shorter time than 'maxage_conn' +@@ -982,8 +967,7 @@ static bool url_match_proxy_use(struct connectdata *conn, + return FALSE; + + if(m->needle->bits.socksproxy && +- !socks_proxy_info_matches(&m->needle->socks_proxy, +- &conn->socks_proxy)) ++ !proxy_info_matches(&m->needle->socks_proxy, &conn->socks_proxy)) + return FALSE; + + if(m->needle->bits.httpproxy) { +diff --git a/tests/http/test_13_proxy_auth.py b/tests/http/test_13_proxy_auth.py +index 6a9a7e6..727557a 100644 +--- a/tests/http/test_13_proxy_auth.py ++++ b/tests/http/test_13_proxy_auth.py +@@ -167,3 +167,23 @@ class TestProxyAuth: + '--negotiate', '--proxy-user', 'proxy:proxy' + ]) + r1.check_response(count=1, http_status=200) ++ ++ def test_13_10_tunnels_mixed_auth(self, env: Env, httpd, configures_httpd): ++ self.httpd_configure(env, httpd) ++ curl = CurlClient(env=env) ++ url1 = f'http://localhost:{env.http_port}/data.json?1' ++ url2 = f'http://localhost:{env.http_port}/data.json?2' ++ url3 = f'http://localhost:{env.http_port}/data.json?3' ++ xargs1 = curl.get_proxy_args(proxys=False, tunnel=True) ++ xargs1.extend(['--proxy-user', 'proxy:proxy']) # good auth ++ xargs2 = curl.get_proxy_args(proxys=False, tunnel=True) ++ xargs2.extend(['--proxy-user', 'ungood:ungood']) # bad auth ++ xargs3 = curl.get_proxy_args(proxys=False, tunnel=True) ++ # no auth ++ r = curl.http_download(urls=[url1, url2, url3], alpn_proto='http/1.1', with_stats=True, ++ url_options={url1: xargs1, url2: xargs2, url3: xargs3}) ++ # only url1 succeeds, others fail, no connection reuse ++ assert r.stats[0]['http_code'] == 200, f'{r.dump_logs()}' ++ assert r.stats[1]['http_code'] == 0, f'{r.dump_logs()}' ++ assert r.stats[2]['http_code'] == 0, f'{r.dump_logs()}' ++ assert r.total_connects == 3, f'{r.dump_logs()}' +diff --git a/tests/http/testenv/curl.py b/tests/http/testenv/curl.py +index eb4d5d3..ec3bcb0 100644 +--- a/tests/http/testenv/curl.py ++++ b/tests/http/testenv/curl.py +@@ -543,7 +543,8 @@ class CurlClient: + with_profile: bool = False, + with_tcpdump: bool = False, + no_save: bool = False, +- extra_args: Optional[List[str]] = None): ++ extra_args: Optional[List[str]] = None), ++ url_options: Optional[Dict[str,List[str]]] = None): + if extra_args is None: + extra_args = [] + if no_save: +@@ -585,6 +586,7 @@ class CurlClient: + ]) + return self._raw(urls, alpn_proto=alpn_proto, options=extra_args, + with_stats=with_stats, ++ url_options=url_options, + with_headers=with_headers, + with_profile=with_profile, + with_tcpdump=with_tcpdump) +@@ -824,6 +826,7 @@ class CurlClient: + + def _raw(self, urls, intext='', timeout=None, options=None, insecure=False, + alpn_proto: Optional[str] = None, ++ url_options=None, + force_resolve=True, + with_stats=False, + with_headers=True, +@@ -833,7 +836,8 @@ class CurlClient: + args = self._complete_args( + urls=urls, timeout=timeout, options=options, insecure=insecure, + alpn_proto=alpn_proto, force_resolve=force_resolve, +- with_headers=with_headers, def_tracing=def_tracing) ++ with_headers=with_headers, def_tracing=def_tracing, ++ url_options=url_options) + r = self._run(args, intext=intext, with_stats=with_stats, + with_profile=with_profile, with_tcpdump=with_tcpdump) + if r.exit_code == 0 and with_headers: +@@ -843,8 +847,10 @@ class CurlClient: + def _complete_args(self, urls, timeout=None, options=None, + insecure=False, force_resolve=True, + alpn_proto: Optional[str] = None, ++ url_options=None, + with_headers: bool = True, + def_tracing: bool = True): ++ url_sep = [] + if not isinstance(urls, list): + urls = [urls] + +@@ -864,7 +870,13 @@ class CurlClient: + active_options = options[options.index('--next') + 1:] + + for url in urls: +- u = urlparse(urls[0]) ++ args.extend(url_sep) ++ if url_options is not None: ++ url_sep = ['--next'] ++ ++ u = urlparse(url) ++ if url_options is not None and url in url_options: ++ args.extend(url_options[url]) + if options: + args.extend(options) + if alpn_proto is not None: diff -Nru curl-8.14.1/debian/patches/CVE-2026-3805.patch curl-8.14.1/debian/patches/CVE-2026-3805.patch --- curl-8.14.1/debian/patches/CVE-2026-3805.patch 1970-01-01 00:00:00.000000000 +0000 +++ curl-8.14.1/debian/patches/CVE-2026-3805.patch 2026-05-08 01:36:52.000000000 +0000 @@ -0,0 +1,65 @@ +From: Stefan Eissing +Date: Sun, 8 Mar 2026 14:30:00 +0100 +Subject: [PATCH] smb: free the path in the request struct properly + +Closes #20854 + +Backported-by: Samuel Henrique + * Refresh patch context for lib/smb.c +--- + lib/smb.c | 20 +++++++++++--------- + 1 file changed, 11 insertions(+), 9 deletions(-) + +diff --git a/lib/smb.c b/lib/smb.c +index ceca956..d527977 100644 +--- a/lib/smb.c ++++ b/lib/smb.c +@@ -448,9 +448,7 @@ static void smb_easy_dtor(void *key, size_t klen, void *entry) + struct smb_request *req = entry; + (void)key; + (void)klen; +- /* `req->path` points to somewhere in `struct smb_conn` which is +- * kept at the connection meta. If the connection is destroyed first, +- * req->path points to free'd memory. */ ++ Curl_safefree(req->path); + free(req); + } + +@@ -1230,7 +1228,7 @@ static CURLcode smb_parse_url_path(struct Curl_easy *data, + struct smb_request *req) + { + char *path; +- char *slash; ++ char *slash, *s; + CURLcode result; + + /* URL decode the path */ +@@ -1239,6 +1237,7 @@ static CURLcode smb_parse_url_path(struct Curl_easy *data, + return result; + + /* Parse the path for the share */ ++ Curl_safefree(smbc->share); + smbc->share = strdup((*path == '/' || *path == '\\') ? path + 1 : path); + free(path); + if(!smbc->share) +@@ -1258,12 +1257,15 @@ static CURLcode smb_parse_url_path(struct Curl_easy *data, + /* Parse the path for the file path converting any forward slashes into + backslashes */ + *slash++ = 0; +- req->path = slash; +- +- for(; *slash; slash++) { +- if(*slash == '/') +- *slash = '\\'; ++ for(s = slash; *s; s++) { ++ if(*s == '/') ++ *s = '\\'; + } ++ /* keep a copy at easy struct to not share this with connection state */ ++ req->path = strdup(slash); ++ if(!req->path) ++ return CURLE_OUT_OF_MEMORY; ++ + return CURLE_OK; + } + diff -Nru curl-8.14.1/debian/patches/CVE-2026-4873.patch curl-8.14.1/debian/patches/CVE-2026-4873.patch --- curl-8.14.1/debian/patches/CVE-2026-4873.patch 1970-01-01 00:00:00.000000000 +0000 +++ curl-8.14.1/debian/patches/CVE-2026-4873.patch 2026-05-08 01:36:52.000000000 +0000 @@ -0,0 +1,46 @@ +From: Daniel Stenberg +Date: Tue, 24 Mar 2026 08:35:08 +0100 +Subject: [PATCH] url: do not reuse a non-tls starttls connection if new + requires TLS + +Reported-by: Arkadi Vainbrand + +Closes #21082 + +Backported-by: Samuel Henrique + * Refresh patch context for lib/url.c +--- + lib/url.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/lib/url.c b/lib/url.c +index efd50a0..dab5093 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -804,7 +804,7 @@ struct url_conn_match { + BIT(want_proxy_ntlm_http); + BIT(want_nego_http); + BIT(want_proxy_nego_http); +- ++ BIT(req_tls); /* require TLS use from a clear-text start */ + BIT(wait_pipe); + BIT(force_reuse); + BIT(seen_pending_conn); +@@ -955,6 +955,9 @@ static bool url_match_ssl_use(struct connectdata *conn, + if(get_protocol_family(conn->handler) != m->needle->handler->protocol) + return FALSE; + } ++ else if(m->req_tls) ++ /* a clear-text STARTTLS protocol with required TLS */ ++ return FALSE; + return TRUE; + } + +@@ -1417,6 +1420,7 @@ ConnectionExists(struct Curl_easy *data, + (needle->handler->protocol & PROTO_FAMILY_HTTP); + #endif + #endif ++ match.req_tls = data->set.use_ssl >= CURLUSESSL_CONTROL; + + /* Find a connection in the pool that matches what "data + needle" + * requires. If a suitable candidate is found, it is attached to "data". */ diff -Nru curl-8.14.1/debian/patches/CVE-2026-5545.patch curl-8.14.1/debian/patches/CVE-2026-5545.patch --- curl-8.14.1/debian/patches/CVE-2026-5545.patch 1970-01-01 00:00:00.000000000 +0000 +++ curl-8.14.1/debian/patches/CVE-2026-5545.patch 2026-05-08 01:36:52.000000000 +0000 @@ -0,0 +1,39 @@ +From: Stefan Eissing +Date: Thu, 2 Apr 2026 11:33:39 +0200 +Subject: [PATCH] url: improve connection reuse on negotiate + +Check state of negotiate to allow proper connection reuse. + +Closes #21203 + +Backported-by: Samuel Henrique + * Refresh patch context for lib/url.c +--- + lib/url.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/lib/url.c b/lib/url.c +index dab5093..b36eb21 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -1172,11 +1172,17 @@ static bool url_match_auth_ntlm(struct connectdata *conn, + if(m->want_ntlm_http) { + if(Curl_timestrcmp(m->needle->user, conn->user) || + Curl_timestrcmp(m->needle->passwd, conn->passwd)) { +- + /* we prefer a credential match, but this is at least a connection +- that can be reused and "upgraded" to NTLM */ +- if(conn->http_ntlm_state == NTLMSTATE_NONE) ++ that can be reused and "upgraded" to NTLM if it does ++ not have any auth ongoing. */ ++#ifdef USE_SPNEGO ++ if((conn->http_ntlm_state == NTLMSTATE_NONE) ++ && (conn->http_negotiate_state == GSS_AUTHNONE)) { ++#else ++ if(conn->http_ntlm_state == NTLMSTATE_NONE) { ++#endif + m->found = conn; ++ } + return FALSE; + } + } diff -Nru curl-8.14.1/debian/patches/CVE-2026-5773.patch curl-8.14.1/debian/patches/CVE-2026-5773.patch --- curl-8.14.1/debian/patches/CVE-2026-5773.patch 1970-01-01 00:00:00.000000000 +0000 +++ curl-8.14.1/debian/patches/CVE-2026-5773.patch 2026-05-08 01:36:52.000000000 +0000 @@ -0,0 +1,44 @@ +From: Daniel Stenberg +Date: Sun, 5 Apr 2026 18:23:35 +0200 +Subject: [PATCH] protocol: disable connection reuse for SMB(S) + +Connections should only be reused when using the same "share" (and +perhaps some additional conditions), but instead of fixing this flaw, +this change completely disables connection reuse for SMB. This protocol +is about to get dropped soon anyway. + +Reported-by: Osama Hamad +Closes #21238 + +Backported-by: Samuel Henrique + * Upstream removes PROTOPT_CONN_REUSE from the SMB and SMBS scheme + registrations in lib/protocol.c. That flag (and the lib/protocol.c scheme + registry itself) only exists from upstream commit + feea96851230c7a5a11feaffa0a5e4a4d30e5e63 ("conncontrol: reuse handling", Nov + 2025) onward, so neither is present in 8.14.1. In 8.14.1 SMB connection + reuse is instead controlled at runtime via connkeep() / connclose(), and + lib/smb.c explicitly calls connkeep() in smb_connect() to mark SMB + connections as eligible for reuse. Replace that connkeep() with a + connclose() so SMB connections are marked as not-reusable, achieving the + same effect as the upstream change. +--- + lib/smb.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/lib/smb.c b/lib/smb.c +index d527977..3fd47ab 100644 +--- a/lib/smb.c ++++ b/lib/smb.c +@@ -511,8 +511,10 @@ static CURLcode smb_connect(struct Curl_easy *data, bool *done) + if(!smbc->send_buf) + return CURLE_OUT_OF_MEMORY; + +- /* Multiple requests are allowed with this connection */ +- connkeep(conn, "SMB default"); ++ /* SMB does not allow connection reuse: connections should only be reused ++ when using the same "share" (and possibly other conditions), but rather ++ than implementing that, mark every SMB connection as not reusable. */ ++ connclose(conn, "SMB does not allow connection reuse"); + + /* Parse the username, domain, and password */ + slash = strchr(conn->user, '/'); diff -Nru curl-8.14.1/debian/patches/CVE-2026-6253.patch curl-8.14.1/debian/patches/CVE-2026-6253.patch --- curl-8.14.1/debian/patches/CVE-2026-6253.patch 1970-01-01 00:00:00.000000000 +0000 +++ curl-8.14.1/debian/patches/CVE-2026-6253.patch 2026-05-08 01:36:52.000000000 +0000 @@ -0,0 +1,386 @@ +From: Daniel Stenberg +Date: Mon, 13 Apr 2026 17:17:23 +0200 +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 + +Backported-by: Samuel Henrique + * Refresh patch context for lib/http.c, lib/transfer.c and + lib/transfer.h. + * Carry the new tests/data/test2009-2011 from upstream verbatim + here; further test-runner-compatibility tweaks (crlf="headers" + -> crlf="yes", --follow -> --location, expected exit code) were also + applied. +--- + lib/http.c | 12 +++++++++ + lib/transfer.c | 51 +++++++++++++++++++++++++----------- + lib/transfer.h | 2 ++ + tests/data/Makefile.am | 1 + + tests/data/test2009 | 70 +++++++++++++++++++++++++++++++++++++++++++++++++ + tests/data/test2010 | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++ + tests/data/test2011 | 70 +++++++++++++++++++++++++++++++++++++++++++++++++ + 7 files changed, 262 insertions(+), 15 deletions(-) + create mode 100644 tests/data/test2009 + create mode 100644 tests/data/test2010 + create mode 100644 tests/data/test2011 + +diff --git a/lib/http.c b/lib/http.c +index 4e15784..1e701b2 100644 +--- a/lib/http.c ++++ b/lib/http.c +@@ -1309,12 +1309,24 @@ CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl, + free(scheme); + } + if(clear) { ++ CURLcode result = Curl_reset_userpwd(data); ++ if(result) { ++ free(follow_url); ++ return result; ++ } + Curl_safefree(data->state.aptr.user); + Curl_safefree(data->state.aptr.passwd); + } + } + } + DEBUGASSERT(follow_url); ++ { ++ CURLcode result = Curl_reset_proxypwd(data); ++ if(result) { ++ free(follow_url); ++ return result; ++ } ++ } + + if(type == FOLLOW_FAKE) { + /* we are only figuring out the new URL if we would have followed locations +diff --git a/lib/transfer.c b/lib/transfer.c +index ef7d7f1..7290c95 100644 +--- a/lib/transfer.c ++++ b/lib/transfer.c +@@ -520,6 +520,40 @@ 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) ++{ ++#ifndef CURL_DISABLE_PROXY ++ 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; ++#else ++ (void)data; ++ return CURLE_OK; ++#endif ++} ++ + /* + * 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 +@@ -663,23 +697,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]); ++ result = Curl_reset_userpwd(data); + if(!result) +- result = Curl_setstropt(&data->state.aptr.passwd, +- data->set.str[STRING_PASSWORD]); +-#ifndef CURL_DISABLE_PROXY +- if(!result) +- 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]); +-#endif ++ result = Curl_reset_proxypwd(data); + + data->req.headerbytecount = 0; + Curl_headers_cleanup(data); +diff --git a/lib/transfer.h b/lib/transfer.h +index 2c355e0..938f3aa 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_sendrecv(struct Curl_easy *data, struct curltime *nowp); +diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am +index 934ba80..3bc144f 100644 +--- a/tests/data/Makefile.am ++++ b/tests/data/Makefile.am +@@ -243,6 +243,7 @@ test1970 test1971 test1972 test1973 test1974 test1975 test1976 test1977 \ + test1978 test1979 test1980 \ + \ + 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..b51001e +--- /dev/null ++++ b/tests/data/test2009 +@@ -0,0 +1,70 @@ ++ ++ ++ ++ ++HTTP ++HTTP proxy ++http_proxy ++ ++ ++# Server-side ++ ++ ++HTTP/1.1 407 Denied ++ ++ ++ ++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 ++ ++ ++ ++# Client-side ++ ++ ++proxy ++ ++ ++http ++https ++ ++ ++proxy credentials via env variables, redirect from http to https ++ ++ ++ ++http_proxy=http://user:secret@%HOSTIP:%HTTPPORT ++https_proxy=https://%HOSTIP:%HTTPSPORT/ ++ ++ ++http://somewhere.example/ --location --proxy-insecure ++ ++ ++ ++# Verify data after the test has been "shot" ++ ++ ++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 ++ ++ ++ ++56 ++ ++ ++ +diff --git a/tests/data/test2010 b/tests/data/test2010 +new file mode 100644 +index 0000000..9feb051 +--- /dev/null ++++ b/tests/data/test2010 +@@ -0,0 +1,71 @@ ++ ++ ++ ++ ++HTTP ++HTTP proxy ++http_proxy ++ ++ ++# Server-side ++ ++ ++HTTP/1.1 407 Denied ++ ++ ++ ++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 ++ ++ ++ ++# Client-side ++ ++ ++proxy ++ ++ ++http ++https ++ ++ ++proxy credentials via options for two proxies, redirect from http to https ++ ++ ++ ++http_proxy=http://%HOSTIP:%HTTPPORT ++https_proxy=https://%HOSTIP:%HTTPSPORT/ ++ ++ ++--proxy-user batman:robin http://somewhere.example/ --location --proxy-insecure ++ ++ ++ ++# Verify data after the test has been "shot" ++ ++ ++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 ++ ++ ++ ++56 ++ ++ ++ +diff --git a/tests/data/test2011 b/tests/data/test2011 +new file mode 100644 +index 0000000..98778e2 +--- /dev/null ++++ b/tests/data/test2011 +@@ -0,0 +1,70 @@ ++ ++ ++ ++ ++HTTP ++HTTP proxy ++http_proxy ++ ++ ++# Server-side ++ ++ ++HTTP/1.1 407 Denied ++ ++ ++ ++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 ++ ++ ++ ++# Client-side ++ ++ ++proxy ++ ++ ++http ++https ++ ++ ++proxy creds via env, cross-scheme redirect, --location-trusted ++ ++ ++ ++http_proxy=http://user:secret@%HOSTIP:%HTTPPORT ++https_proxy=https://%HOSTIP:%HTTPSPORT/ ++ ++ ++http://somewhere.example/ --location-trusted --proxy-insecure ++ ++ ++ ++# Verify data after the test has been "shot" ++ ++ ++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 ++ ++ ++ ++56 ++ ++ ++ diff -Nru curl-8.14.1/debian/patches/CVE-2026-6276.patch curl-8.14.1/debian/patches/CVE-2026-6276.patch --- curl-8.14.1/debian/patches/CVE-2026-6276.patch 1970-01-01 00:00:00.000000000 +0000 +++ curl-8.14.1/debian/patches/CVE-2026-6276.patch 2026-05-08 01:36:52.000000000 +0000 @@ -0,0 +1,377 @@ +From: Daniel Stenberg +Date: Tue, 14 Apr 2026 08:51:44 +0200 +Subject: [PATCH] urldata: move cookiehost to struct SingleRequest + +To make it scoped for the single request appropriately. + +Reported-by: Muhamad Arga Reksapati + +Verify with libtest 2504: a custom Host *disabled* on reused handle + +Closes #21312 + +Backported-by: Samuel Henrique + * lib/http.c: upstream refactored the relevant code into a separate + http_set_aptr_host() function; in 8.14.1 the equivalent code is + still inline in http_host(). Apply the same logic (free the new + per-request field, store the parsed Host into req.cookiehost + instead of aptr.cookiehost, read from the new location in the two + cookie lookup sites). + * lib/request.c, lib/request.h: upstream's struct SingleRequest in + the patch context has userpwd / proxyuserpwd fields not present in + 8.14.1; place the new cookiehost field and its Curl_safefree() call + accordingly. Use Curl_safefree (8.14.1) rather than upstream's + curlx_safefree, which does not exist in this version. + * lib/url.c, lib/urldata.h: applied as upstream, modulo Curl_safefree + vs curlx_safefree. + * tests/data/test2504: regression test from upstream, with + crlf="headers" -> crlf="yes" so the 8.14.1 test runner (which only + recognises crlf="yes") correctly converts header newlines on both + the server-side data and the expected protocol block. + * tests/libtest/lib2504.c: rewritten to use the 8.14.1 libtest + harness (test.h / CURLcode test(char *URL) / easy_init / + test_setopt / goto test_cleanup) instead of upstream's newer + first.h-based harness. Test logic is identical. +--- + lib/http.c | 14 ++++--- + lib/request.c | 3 ++ + lib/request.h | 1 + + lib/url.c | 2 +- + lib/urldata.h | 3 -- + tests/data/Makefile.am | 2 +- + tests/data/{test1901 => test2504} | 40 ++++++++----------- + tests/libtest/Makefile.inc | 5 ++- + tests/libtest/{lib1511.c => lib2504.c} | 71 ++++++++++++++++++++-------------- + 9 files changed, 77 insertions(+), 64 deletions(-) + copy tests/data/{test1901 => test2504} (53%) + copy tests/libtest/{lib1511.c => lib2504.c} (51%) + +diff --git a/lib/http.c b/lib/http.c +index 1e701b2..68657e5 100644 +--- a/lib/http.c ++++ b/lib/http.c +@@ -1903,6 +1903,9 @@ static CURLcode http_host(struct Curl_easy *data, struct connectdata *conn) + data->state.first_remote_protocol = conn->handler->protocol; + } + Curl_safefree(aptr->host); ++#ifndef CURL_DISABLE_COOKIES ++ Curl_safefree(data->req.cookiehost); ++#endif + + ptr = Curl_checkheaders(data, STRCONST("Host")); + if(ptr && (!data->state.this_is_a_follow || +@@ -1937,8 +1940,7 @@ static CURLcode http_host(struct Curl_easy *data, struct connectdata *conn) + if(colon) + *colon = 0; /* The host must not include an embedded port number */ + } +- free(aptr->cookiehost); +- aptr->cookiehost = cookiehost; ++ data->req.cookiehost = cookiehost; + } + #endif + +@@ -2452,8 +2454,8 @@ static CURLcode http_cookies(struct Curl_easy *data, + int rc = 1; + + if(data->cookies && data->state.cookie_engine) { +- const char *host = data->state.aptr.cookiehost ? +- data->state.aptr.cookiehost : conn->host.name; ++ const char *host = data->req.cookiehost ? ++ data->req.cookiehost : conn->host.name; + const bool secure_context = + conn->handler->protocol&(CURLPROTO_HTTPS|CURLPROTO_WSS) || + strcasecompare("localhost", host) || +@@ -3287,8 +3289,8 @@ static CURLcode http_header(struct Curl_easy *data, + if(v) { + /* If there is a custom-set Host: name, use it here, or else use + * real peer hostname. */ +- const char *host = data->state.aptr.cookiehost ? +- data->state.aptr.cookiehost : conn->host.name; ++ const char *host = data->req.cookiehost ? ++ data->req.cookiehost : conn->host.name; + const bool secure_context = + conn->handler->protocol&(CURLPROTO_HTTPS|CURLPROTO_WSS) || + strcasecompare("localhost", host) || +diff --git a/lib/request.c b/lib/request.c +index f937a7f..7f365e7 100644 +--- a/lib/request.c ++++ b/lib/request.c +@@ -119,6 +119,9 @@ void Curl_req_hard_reset(struct SingleRequest *req, struct Curl_easy *data) + struct curltime t0 = {0, 0}; + + Curl_safefree(req->newurl); ++#ifndef CURL_DISABLE_COOKIES ++ Curl_safefree(req->cookiehost); ++#endif + Curl_client_reset(data); + if(req->sendbuf_init) + Curl_bufq_reset(&req->sendbuf); +diff --git a/lib/request.h b/lib/request.h +index 74d9f53..00f094c 100644 +--- a/lib/request.h ++++ b/lib/request.h +@@ -100,6 +100,7 @@ struct SingleRequest { + wanted */ + + #ifndef CURL_DISABLE_COOKIES ++ char *cookiehost; + unsigned char setcookies; + #endif + BIT(header); /* incoming data has HTTP header */ +diff --git a/lib/url.c b/lib/url.c +index b36eb21..8a638f3 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -317,7 +317,7 @@ CURLcode Curl_close(struct Curl_easy **datap) + Curl_safefree(data->state.aptr.ref); + Curl_safefree(data->state.aptr.host); + #ifndef CURL_DISABLE_COOKIES +- Curl_safefree(data->state.aptr.cookiehost); ++ Curl_safefree(data->req.cookiehost); + #endif + #ifndef CURL_DISABLE_RTSP + Curl_safefree(data->state.aptr.rtsp_transport); +diff --git a/lib/urldata.h b/lib/urldata.h +index 45052e8..4ddb0f7 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -1241,9 +1241,6 @@ struct UrlState { + char *rangeline; + char *ref; + char *host; +-#ifndef CURL_DISABLE_COOKIES +- char *cookiehost; +-#endif + #ifndef CURL_DISABLE_RTSP + char *rtsp_transport; + #endif +diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am +index 3bc144f..0e9b4f2 100644 +--- a/tests/data/Makefile.am ++++ b/tests/data/Makefile.am +@@ -264,7 +264,7 @@ test2308 test2309 \ + \ + test2400 test2401 test2402 test2403 test2404 test2405 test2406 \ + \ +-test2500 test2501 test2502 test2503 \ ++test2500 test2501 test2502 test2503 test2504 \ + \ + test2600 test2601 test2602 test2603 test2604 \ + \ +diff --git a/tests/data/test1901 b/tests/data/test2504 +similarity index 53% +copy from tests/data/test1901 +copy to tests/data/test2504 +index 143a5f1..704701c 100644 +--- a/tests/data/test1901 ++++ b/tests/data/test2504 +@@ -1,9 +1,9 @@ ++ + + + + HTTP +-HTTP POST +-CURLOPT_READFUNCTION ++cookies + + + +@@ -11,10 +11,12 @@ CURLOPT_READFUNCTION + + + HTTP/1.1 200 OK +-Content-Length: 6 +-Content-Type: text/html ++Date: Tue, 09 Nov 2010 14:49:00 GMT ++Server: server.example.com ++Content-Length: 47 ++Set-Cookie: sid=SECRET123; Path=/ + +--foo- ++file contents should appear once for each file + + + +@@ -23,37 +25,27 @@ Content-Type: text/html + + http + +- +- +-Chunked HTTP POST from callback with CURLOPT_POSTFIELDSIZE set +- + + lib%TESTNUMBER + +- ++ ++custom Host with cookie, handle reuse, no custom Host: ++ + +-http://%HOSTIP:%HTTPPORT/boom ++http://%HOSTIP:%HTTPPORT + + + + # Verify data after the test has been "shot" + + +-POST /boom HTTP/1.1 +-Host: %HOSTIP:%HTTPPORT ++GET / HTTP/1.1 ++Host: victim.internal + Accept: */* +-Transfer-Encoding: chunked +-Content-Type: application/x-www-form-urlencoded + +-3 +-one +-3 +-two +-5 +-three +-4 +-four +-0 ++GET / HTTP/1.1 ++Host: %HOSTIP:%HTTPPORT ++Accept: */* + + + +diff --git a/tests/libtest/Makefile.inc b/tests/libtest/Makefile.inc +index d130d51..788cffa 100644 +--- a/tests/libtest/Makefile.inc ++++ b/tests/libtest/Makefile.inc +@@ -77,7 +77,7 @@ LIBTESTPROGS = libauthretry libntlmconnect libprereq \ + lib1970 lib1971 lib1972 lib1973 lib1974 lib1975 lib1977 lib1978 \ + lib2301 lib2302 lib2304 lib2306 lib2308 lib2309 \ + lib2402 lib2404 lib2405 \ +- lib2502 \ ++ lib2502 lib2504 \ + lib2700 \ + lib3010 lib3025 lib3026 lib3027 \ + lib3100 lib3101 lib3102 lib3103 lib3104 lib3105 lib3207 lib3208 +@@ -721,6 +721,9 @@ lib2405_LDADD = $(TESTUTIL_LIBS) + lib2502_SOURCES = lib2502.c $(SUPPORTFILES) $(TESTUTIL) $(TSTTRACE) $(WARNLESS) + lib2502_LDADD = $(TESTUTIL_LIBS) + ++lib2504_SOURCES = lib2504.c $(SUPPORTFILES) $(TESTUTIL) $(TSTTRACE) $(WARNLESS) ++lib2504_LDADD = $(TESTUTIL_LIBS) ++ + lib2700_SOURCES = lib2700.c $(SUPPORTFILES) $(TESTUTIL) $(TSTTRACE) $(MULTIBYTE) + lib2700_LDADD = $(TESTUTIL_LIBS) + +diff --git a/tests/libtest/lib1511.c b/tests/libtest/lib2504.c +similarity index 51% +copy from tests/libtest/lib1511.c +copy to tests/libtest/lib2504.c +index abc1356..0202764 100644 +--- a/tests/libtest/lib1511.c ++++ b/tests/libtest/lib2504.c +@@ -5,7 +5,7 @@ + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * +- * Copyright (C) Daniel Stenberg, , et al. ++ * Copyright (C) Linus Nielsen Feltzing + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms +@@ -23,53 +23,68 @@ + ***************************************************************************/ + #include "test.h" + ++#include "testtrace.h" ++#include "testutil.h" ++#include "warnless.h" + #include "memdebug.h" + ++static size_t sink2504(char *ptr, size_t size, size_t nmemb, void *ud) ++{ ++ (void)ptr; ++ (void)ud; ++ return size * nmemb; ++} ++ ++static void dump_cookies2504(CURL *h, const char *tag) ++{ ++ struct curl_slist *cookies = NULL; ++ struct curl_slist *nc; ++ CURLcode rc = curl_easy_getinfo(h, CURLINFO_COOKIELIST, &cookies); ++ ++ curl_mprintf("== %s ==\n", tag); ++ if(rc) { ++ curl_mprintf("getinfo error: %d\n", (int)rc); ++ return; ++ } ++ for(nc = cookies; nc; nc = nc->next) ++ puts(nc->data); ++ curl_slist_free_all(cookies); ++} ++ + CURLcode test(char *URL) + { +- long unmet; + CURL *curl = NULL; + CURLcode res = CURLE_OK; ++ struct curl_slist *hdrs = NULL; + + global_init(CURL_GLOBAL_ALL); + + easy_init(curl); + +- easy_setopt(curl, CURLOPT_URL, URL); +- easy_setopt(curl, CURLOPT_HEADER, 1L); +- easy_setopt(curl, CURLOPT_TIMECONDITION, (long)CURL_TIMECOND_IFMODSINCE); +- +- /* TIMEVALUE in the future */ +- easy_setopt(curl, CURLOPT_TIMEVALUE, 1566210680L); +- +- res = curl_easy_perform(curl); +- if(res) +- goto test_cleanup; +- +- curl_easy_getinfo(curl, CURLINFO_CONDITION_UNMET, &unmet); +- if(unmet != 1L) { +- res = TEST_ERR_FAILURE; /* not correct */ ++ hdrs = curl_slist_append(hdrs, "Host: victim.internal"); ++ if(!hdrs) { ++ res = CURLE_OUT_OF_MEMORY; + goto test_cleanup; + } + +- /* TIMEVALUE in the past */ +- easy_setopt(curl, CURLOPT_TIMEVALUE, 1L); ++ test_setopt(curl, CURLOPT_WRITEFUNCTION, sink2504); ++ test_setopt(curl, CURLOPT_COOKIEFILE, ""); ++ test_setopt(curl, CURLOPT_HTTPHEADER, hdrs); ++ test_setopt(curl, CURLOPT_URL, URL); + + res = curl_easy_perform(curl); +- if(res) +- goto test_cleanup; ++ curl_mprintf("req1=%d\n", (int)res); ++ dump_cookies2504(curl, "after request 1"); + +- curl_easy_getinfo(curl, CURLINFO_CONDITION_UNMET, &unmet); +- if(unmet) { +- res = TEST_ERR_FAILURE; /* not correct */ +- goto test_cleanup; +- } ++ test_setopt(curl, CURLOPT_HTTPHEADER, NULL); ++ test_setopt(curl, CURLOPT_URL, URL); + +- res = TEST_ERR_SUCCESS; /* this is where we should be */ ++ res = curl_easy_perform(curl); ++ curl_mprintf("req2=%d\n", (int)res); ++ dump_cookies2504(curl, "after request 2"); + + test_cleanup: +- +- /* always cleanup */ ++ curl_slist_free_all(hdrs); + curl_easy_cleanup(curl); + curl_global_cleanup(); + diff -Nru curl-8.14.1/debian/patches/CVE-2026-6429.patch curl-8.14.1/debian/patches/CVE-2026-6429.patch --- curl-8.14.1/debian/patches/CVE-2026-6429.patch 1970-01-01 00:00:00.000000000 +0000 +++ curl-8.14.1/debian/patches/CVE-2026-6429.patch 2026-05-08 01:36:52.000000000 +0000 @@ -0,0 +1,345 @@ +From: Daniel Stenberg +Date: Thu, 16 Apr 2026 14:26:20 +0200 +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 + +Backported-by: Samuel Henrique + * lib/http.c: upstream rewrites the relevant block in + Curl_http_follow() entirely, replacing the manual port/scheme + comparison with a Curl_url_same_origin() call against a parsed + copy of data->state.url. Neither Curl_url_same_origin nor the + required Curl_bufref_ptr(&data->state.url) accessor exist in + 8.14.1 (state.url is a plain char *). Instead, keep the existing + port/scheme check in place and add the new "no STRING_USERNAME" + case as a short-circuit ahead of it: when no explicit username + was set, force clear=TRUE unconditionally; otherwise fall back + to the historical port/scheme test. Use Curl_safefree (8.14.1) + rather than upstream's curlx_safefree. + * tests/data/test998: drop the now-stale Authorization header line + in the second request of the verify block. Upstream uses the + %b64[alberto:einstein]b64% placeholder while 8.14.1 still has + it pre-encoded as YWxiZXJ0bzplaW5zdGVpbg==; either way the line + needs to go away because the fix now clears those credentials + on the cross-host redirect. + * tests/data/test2506: regression test from upstream, with + crlf="headers" -> crlf="yes" so the 8.14.1 test runner correctly + applies CRLF to header lines on both the server-side data and + the expected protocol block. + * tests/libtest/lib2506.c: rewritten to use the 8.14.1 libtest + harness (test.h / CURLcode test(char *URL) / easy_init / + test_setopt with goto test_cleanup) instead of upstream's newer + first.h-based one. Test logic is identical. +--- + lib/http.c | 77 ++++++++++++++++++---------------- + tests/data/Makefile.am | 2 +- + tests/data/test2506 | 64 ++++++++++++++++++++++++++++ + tests/data/test998 | 1 - + tests/libtest/Makefile.inc | 5 ++- + tests/libtest/{lib1558.c => lib2506.c} | 47 ++++++++++----------- + 6 files changed, 134 insertions(+), 62 deletions(-) + create mode 100644 tests/data/test2506 + copy tests/libtest/{lib1558.c => lib2506.c} (64%) + +diff --git a/lib/http.c b/lib/http.c +index 68657e5..cc5df34 100644 +--- a/lib/http.c ++++ b/lib/http.c +@@ -1266,47 +1266,54 @@ CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl, + 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; ++ /* Clear auth on redirect when: ++ - this redirects to a different port or protocol (unless permitted), or ++ - no explicit username was set (the credentials came from netrc or ++ similar, and must not be carried across a redirect at all). */ ++ if(type != FOLLOW_FAKE) { + 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(follow_url); +- 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); ++ if(!data->set.str[STRING_USERNAME]) + clear = TRUE; +- } +- else { +- char *scheme; +- const struct Curl_handler *p; +- uc = curl_url_get(data->state.uh, CURLUPART_SCHEME, &scheme, 0); +- if(uc) { +- free(follow_url); +- return Curl_uc_to_curlcode(uc); ++ else if(!data->set.allow_auth_to_other_hosts) { ++ char *portnum; ++ int port; ++ ++ 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(follow_url); ++ return Curl_uc_to_curlcode(uc); ++ } ++ port = atoi(portnum); ++ free(portnum); + } +- +- 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); ++ 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; + } +- free(scheme); ++ else { ++ char *scheme; ++ const struct Curl_handler *p; ++ uc = curl_url_get(data->state.uh, CURLUPART_SCHEME, &scheme, 0); ++ if(uc) { ++ free(follow_url); ++ 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); ++ } + } + if(clear) { + CURLcode result = Curl_reset_userpwd(data); +diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am +index 70d45c6..7e4163d 100644 +--- a/tests/data/Makefile.am ++++ b/tests/data/Makefile.am +@@ -265,7 +265,7 @@ test2308 test2309 \ + \ + test2400 test2401 test2402 test2403 test2404 test2405 test2406 \ + \ +-test2500 test2501 test2502 test2503 test2504 \ ++test2500 test2501 test2502 test2503 test2504 test2506 \ + \ + test2600 test2601 test2602 test2603 test2604 \ + \ +diff --git a/tests/data/test2506 b/tests/data/test2506 +new file mode 100644 +index 0000000..305e3d0 +--- /dev/null ++++ b/tests/data/test2506 +@@ -0,0 +1,64 @@ ++ ++ ++ ++ ++HTTP ++cookies ++ ++ ++ ++ ++ ++HTTP/1.1 301 redirect ++Date: Tue, 09 Nov 2010 14:49:00 GMT ++Content-Length: 3 ++Location: http://numbertwo.example/%TESTNUMBER0002 ++ ++ok ++ ++ ++HTTP/1.1 200 OK ++Date: Tue, 09 Nov 2010 14:49:00 GMT ++Content-Length: 4 ++ ++yes ++ ++ ++ ++ ++ ++http ++ ++ ++proxy ++ ++ ++lib%TESTNUMBER ++ ++ ++netrc with redirect using proxy ++ ++ ++machine site.example login batman password robin ++ ++ ++http://%HOSTIP:%HTTPPORT http://site.example/ %LOGDIR/netrc2506 ++ ++ ++ ++ ++ ++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 ++ ++ ++ ++ +diff --git a/tests/data/test998 b/tests/data/test998 +index c3a8f51..091c235 100644 +--- a/tests/data/test998 ++++ b/tests/data/test998 +@@ -82,7 +82,6 @@ Proxy-Connection: Keep-Alive + + GET http://somewhere.else.example/a/path/9980002 HTTP/1.1 + Host: somewhere.else.example +-Authorization: Basic YWxiZXJ0bzplaW5zdGVpbg== + User-Agent: curl/%VERSION + Accept: */* + Proxy-Connection: Keep-Alive +diff --git a/tests/libtest/Makefile.inc b/tests/libtest/Makefile.inc +index bdbd8b5..284be0c 100644 +--- a/tests/libtest/Makefile.inc ++++ b/tests/libtest/Makefile.inc +@@ -77,7 +77,7 @@ LIBTESTPROGS = libauthretry libntlmconnect libprereq \ + lib1970 lib1971 lib1972 lib1973 lib1974 lib1975 lib1977 lib1978 \ + lib2301 lib2302 lib2304 lib2306 lib2308 lib2309 \ + lib2402 lib2404 lib2405 \ +- lib2502 lib2504 \ ++ lib2502 lib2504 lib2506 \ + lib2700 \ + lib3010 lib3025 lib3026 lib3027 \ + lib3100 lib3101 lib3102 lib3103 lib3104 lib3105 lib3207 lib3208 +@@ -727,6 +727,9 @@ lib2502_LDADD = $(TESTUTIL_LIBS) + lib2504_SOURCES = lib2504.c $(SUPPORTFILES) $(TESTUTIL) $(TSTTRACE) $(WARNLESS) + lib2504_LDADD = $(TESTUTIL_LIBS) + ++lib2506_SOURCES = lib2506.c $(SUPPORTFILES) $(TESTUTIL) $(TSTTRACE) $(WARNLESS) ++lib2506_LDADD = $(TESTUTIL_LIBS) ++ + lib2700_SOURCES = lib2700.c $(SUPPORTFILES) $(TESTUTIL) $(TSTTRACE) $(MULTIBYTE) + lib2700_LDADD = $(TESTUTIL_LIBS) + +diff --git a/tests/libtest/lib1558.c b/tests/libtest/lib2506.c +similarity index 64% +copy from tests/libtest/lib1558.c +copy to tests/libtest/lib2506.c +index 9bb18ca..86d5a50 100644 +--- a/tests/libtest/lib1558.c ++++ b/tests/libtest/lib2506.c +@@ -5,7 +5,7 @@ + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * +- * Copyright (C) Daniel Stenberg, , et al. ++ * Copyright (C) Linus Nielsen Feltzing + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms +@@ -23,45 +23,44 @@ + ***************************************************************************/ + #include "test.h" + ++#include "testtrace.h" + #include "testutil.h" + #include "warnless.h" + #include "memdebug.h" + ++static size_t sink2506(char *ptr, size_t size, size_t nmemb, void *ud) ++{ ++ (void)ptr; ++ (void)ud; ++ return size * nmemb; ++} ++ + CURLcode test(char *URL) + { +- CURLcode res = CURLE_OK; + CURL *curl = NULL; +- long protocol = 0; ++ CURLcode res = CURLE_OK; + + global_init(CURL_GLOBAL_ALL); +- easy_init(curl); + +- easy_setopt(curl, CURLOPT_URL, URL); +- res = curl_easy_perform(curl); +- if(res) { +- curl_mfprintf(stderr, "curl_easy_perform() returned %d (%s)\n", +- res, curl_easy_strerror(res)); +- goto test_cleanup; +- } +- +- res = curl_easy_getinfo(curl, CURLINFO_PROTOCOL, &protocol); +- if(res) { +- curl_mfprintf(stderr, "curl_easy_getinfo() returned %d (%s)\n", +- res, curl_easy_strerror(res)); +- goto test_cleanup; +- } ++ easy_init(curl); + +- curl_mprintf("Protocol: %lx\n", protocol); ++ test_setopt(curl, CURLOPT_WRITEFUNCTION, sink2506); ++ test_setopt(curl, CURLOPT_PROXY, URL); ++ test_setopt(curl, CURLOPT_URL, libtest_arg2); ++ test_setopt(curl, CURLOPT_NETRC, (long)CURL_NETRC_OPTIONAL); ++ test_setopt(curl, CURLOPT_NETRC_FILE, libtest_arg3); ++ test_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); ++ test_setopt(curl, CURLOPT_VERBOSE, 1L); + +- curl_easy_cleanup(curl); +- curl_global_cleanup(); ++ /* CURLOPT_UNRESTRICTED_AUTH should not make a difference because the ++ credentials come from netrc */ ++ test_setopt(curl, CURLOPT_UNRESTRICTED_AUTH, 1L); + +- return CURLE_OK; ++ res = curl_easy_perform(curl); + + test_cleanup: +- + curl_easy_cleanup(curl); + curl_global_cleanup(); + +- return res; /* return the final return code */ ++ return res; + } diff -Nru curl-8.14.1/debian/patches/CVE-2026-7168.patch curl-8.14.1/debian/patches/CVE-2026-7168.patch --- curl-8.14.1/debian/patches/CVE-2026-7168.patch 1970-01-01 00:00:00.000000000 +0000 +++ curl-8.14.1/debian/patches/CVE-2026-7168.patch 2026-05-08 01:36:52.000000000 +0000 @@ -0,0 +1,417 @@ +From: Daniel Stenberg +Date: Mon, 27 Apr 2026 09:14:51 +0200 +Subject: [PATCH] setopt: clear proxy auth properties when switching + +Verify with test 1588 + +Closes #21453 + +Backported-by: Samuel Henrique + * lib/setopt.c: upstream's CURLOPT_PROXY case lives in a dedicated + setopt_cptr_proxy() function; in 8.14.1 it is still inline in the + setopt_cptr() switch. The setproxy() helper is added directly + above setopt_cptr() and the inline Curl_setstropt() call is + swapped for setproxy(). + * lib/vauth/vauth.h: upstream's hunk also adds a no-op + Curl_auth_is_digest_supported() macro to the CURL_DISABLE_DIGEST_AUTH + branch, but our 8.14.1 vauth.h has no such #else branch (the file + ends the digest block with a bare #endif). Add only the + Curl_auth_digest_cleanup(x) no-op macro inside a new #else, which + is the part actually needed by setproxy() in disable-digest builds. + * tests/data/test1588: regression test from upstream with two changes: + crlf="headers" -> crlf="yes" so the 8.14.1 test runner correctly + applies CRLF to header lines on both the server-side data and the + expected protocol block; and the "digest" entry in is + dropped because the 8.14.1 curlinfo emits the feature toggle as + "digest-auth" rather than "digest", so the unmodified feature gate + would always SKIP the test on this branch. Other digest-auth tests + (e.g. test1061) similarly do not list "digest" as a required + feature. + * tests/libtest/lib1588.c: rewritten to use the 8.14.1 libtest + harness (test.h / CURLcode test(char *URL) / easy_init / easy_setopt + with goto test_cleanup) instead of upstream's newer first.h-based + one. The init1588() helper also reuses the parent's test_cleanup + label rather than upstream's separate init_failed label, since + 8.14.1's easy_setopt jumps directly to test_cleanup. +--- + lib/setopt.c | 17 +++++- + lib/vauth/vauth.h | 2 + + tests/data/Makefile.am | 1 + + tests/data/{test540 => test1588} | 109 +++++++++++++++++----------------- + tests/libtest/Makefile.inc | 5 +- + tests/libtest/lib1588.c | 124 +++++++++++++++++++++++++++++++++++++++ + 6 files changed, 200 insertions(+), 58 deletions(-) + copy tests/data/{test540 => test1588} (64%) + create mode 100644 tests/libtest/lib1588.c + +diff --git a/lib/setopt.c b/lib/setopt.c +index d5ddf6d..fddef99 100644 +--- a/lib/setopt.c ++++ b/lib/setopt.c +@@ -54,6 +54,7 @@ + #include "tftp.h" + #include "strdup.h" + #include "escape.h" ++#include "vauth/vauth.h" + + /* The last 3 #include files should be in this order */ + #include "curl_printf.h" +@@ -1662,6 +1663,20 @@ static CURLcode setopt_pointers(struct Curl_easy *data, CURLoption option, + return result; + } + ++#ifndef CURL_DISABLE_PROXY ++static CURLcode setproxy(struct Curl_easy *data, const char *proxy) ++{ ++ if((data->set.str[STRING_PROXY] && proxy) && ++ /* there was one set, is this a new one? */ ++ !strcmp(data->set.str[STRING_PROXY], proxy)) ++ return CURLE_OK; /* same one as before */ ++ ++ Curl_auth_digest_cleanup(&data->state.proxydigest); ++ memset(&data->state.authproxy, 0, sizeof(data->state.authproxy)); ++ return Curl_setstropt(&data->set.str[STRING_PROXY], proxy); ++} ++#endif ++ + static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option, + char *ptr) + { +@@ -1949,7 +1964,7 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option, + * Setting it to NULL, means no proxy but allows the environment variables + * to decide for us (if CURLOPT_SOCKS_PROXY setting it to NULL). + */ +- return Curl_setstropt(&data->set.str[STRING_PROXY], ptr); ++ return setproxy(data, ptr); + + case CURLOPT_PRE_PROXY: + /* +diff --git a/lib/vauth/vauth.h b/lib/vauth/vauth.h +index 58b13f5..af73b14 100644 +--- a/lib/vauth/vauth.h ++++ b/lib/vauth/vauth.h +@@ -117,6 +117,8 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data, + + /* This is used to clean up the digest specific data */ + void Curl_auth_digest_cleanup(struct digestdata *digest); ++#else ++#define Curl_auth_digest_cleanup(x) + #endif /* !CURL_DISABLE_DIGEST_AUTH */ + + #ifdef USE_GSASL +diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am +index 0e9b4f2..70d45c6 100644 +--- a/tests/data/Makefile.am ++++ b/tests/data/Makefile.am +@@ -209,6 +209,7 @@ test1550 test1551 test1552 test1553 test1554 test1555 test1556 test1557 \ + test1558 test1559 test1560 test1561 test1562 test1563 test1564 test1565 \ + test1566 test1567 test1568 test1569 test1570 test1571 test1572 test1573 \ + test1574 test1575 test1576 test1577 test1578 test1579 test1580 test1581 \ ++test1588 \ + \ + test1590 test1591 test1592 test1593 test1594 test1595 test1596 test1597 \ + test1598 \ +diff --git a/tests/data/test540 b/tests/data/test1588 +similarity index 64% +copy from tests/data/test540 +copy to tests/data/test1588 +index ef13108..6428cd7 100644 +--- a/tests/data/test540 ++++ b/tests/data/test1588 +@@ -1,3 +1,4 @@ ++ + + + +@@ -11,46 +12,43 @@ multi + + # Server-side + +- +-connection-monitor +- + + # this is returned first since we get no proxy-auth +- +-HTTP/1.1 407 Authorization Required to proxy me my dear +-Proxy-Authenticate: Digest realm="weirdorealm", nonce="12345" +-Content-Length: 33 +- ++ ++HTTP/1.1 407 Authorization Required to proxy me my dear ++Proxy-Authenticate: Digest realm="weirdorealm", nonce="12345" ++Content-Length: 33 ++ + And you should ignore this data. + + + # then this is returned when we get proxy-auth +- +-HTTP/1.1 200 OK +-Content-Length: 21 +-Server: no +- ++ ++HTTP/1.1 200 OK ++Content-Length: 21 ++Server: no ++ + Nice proxy auth sir! + + +- +-HTTP/1.1 407 Authorization Required to proxy me my dear +-Proxy-Authenticate: Digest realm="weirdorealm", nonce="12345" +-Content-Length: 33 +- +-HTTP/1.1 200 OK +-Content-Length: 21 +-Server: no +- ++ ++HTTP/1.1 407 Authorization Required to proxy me my dear ++Proxy-Authenticate: Digest realm="weirdorealm", nonce="12345" ++Content-Length: 33 ++ ++HTTP/1.1 200 OK ++Content-Length: 21 ++Server: no ++ + Nice proxy auth sir! +-HTTP/1.1 407 Authorization Required to proxy me my dear +-Proxy-Authenticate: Digest realm="weirdorealm", nonce="12345" +-Content-Length: 33 +- +-HTTP/1.1 200 OK +-Content-Length: 21 +-Server: no +- ++HTTP/1.1 407 Authorization Required to proxy me my dear ++Proxy-Authenticate: Digest realm="weirdorealm", nonce="12345" ++Content-Length: 33 ++ ++HTTP/1.1 200 OK ++Content-Length: 21 ++Server: no ++ + Nice proxy auth sir! + + +@@ -70,39 +68,38 @@ crypto + proxy + + +-HTTP proxy auth Digest multi API re-using connection ++HTTP proxy auth Digest, then change proxy and do it again + + +-http://test.remote.example.com/path/%TESTNUMBER http://%HOSTIP:%HTTPPORT silly:person custom.set.host.name ++http://test.remote.example.com/path/%TESTNUMBER %HOSTIP %HTTPPORT silly:person custom.set.host.name + + + + # Verify data after the test has been "shot" + +- +-GET http://test.remote.example.com/path/%TESTNUMBER HTTP/1.1 +-Host: custom.set.host.name +-Accept: */* +-Proxy-Connection: Keep-Alive +- +-GET http://test.remote.example.com/path/%TESTNUMBER HTTP/1.1 +-Host: custom.set.host.name +-Proxy-Authorization: Digest username="silly", realm="weirdorealm", nonce="12345", uri="/path/%TESTNUMBER", response="ca507dcf189196b6a5374d3233042261" +-Accept: */* +-Proxy-Connection: Keep-Alive +- +-GET http://test.remote.example.com/path/%TESTNUMBER HTTP/1.1 +-Host: custom.set.host.name +-Accept: */* +-Proxy-Connection: Keep-Alive +- +-GET http://test.remote.example.com/path/%TESTNUMBER HTTP/1.1 +-Host: custom.set.host.name +-Proxy-Authorization: Digest username="silly", realm="weirdorealm", nonce="12345", uri="/path/%TESTNUMBER", response="ca507dcf189196b6a5374d3233042261" +-Accept: */* +-Proxy-Connection: Keep-Alive +- +-[DISCONNECT] ++ ++GET http://test.remote.example.com/path/1588 HTTP/1.1 ++Host: test.remote.example.com ++Accept: */* ++Proxy-Connection: Keep-Alive ++ ++GET http://test.remote.example.com/path/1588 HTTP/1.1 ++Host: test.remote.example.com ++Proxy-Authorization: Digest username="silly", realm="weirdorealm", nonce="12345", uri="/path/1588", response="d0b2f000c7e3fca24452b5810713404a" ++Accept: */* ++Proxy-Connection: Keep-Alive ++ ++GET http://test.remote.example.com/path/1588 HTTP/1.1 ++Host: test.remote.example.com ++Accept: */* ++Proxy-Connection: Keep-Alive ++ ++GET http://test.remote.example.com/path/1588 HTTP/1.1 ++Host: test.remote.example.com ++Proxy-Authorization: Digest username="silly", realm="weirdorealm", nonce="12345", uri="/path/1588", response="d0b2f000c7e3fca24452b5810713404a" ++Accept: */* ++Proxy-Connection: Keep-Alive ++ + + + +diff --git a/tests/libtest/Makefile.inc b/tests/libtest/Makefile.inc +index 788cffa..bdbd8b5 100644 +--- a/tests/libtest/Makefile.inc ++++ b/tests/libtest/Makefile.inc +@@ -63,7 +63,7 @@ LIBTESTPROGS = libauthretry libntlmconnect libprereq \ + lib1540 lib1541 lib1542 lib1543 lib1545 \ + lib1550 lib1551 lib1552 lib1553 lib1554 lib1555 lib1556 lib1557 \ + lib1558 lib1559 lib1560 lib1564 lib1565 lib1567 lib1568 lib1569 lib1571 \ +- lib1576 lib1578 \ ++ lib1576 lib1578 lib1588 \ + lib1591 lib1592 lib1593 lib1594 lib1596 lib1597 lib1598 \ + \ + lib1662 \ +@@ -541,6 +541,9 @@ lib1576_SOURCES = lib1576.c $(SUPPORTFILES) + lib1578_SOURCES = lib1576.c $(SUPPORTFILES) + lib1578_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1578 + ++lib1588_SOURCES = lib1588.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) ++lib1588_LDADD = $(TESTUTIL_LIBS) ++ + lib1591_SOURCES = lib1591.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) + lib1591_LDADD = $(TESTUTIL_LIBS) + +diff --git a/tests/libtest/lib1588.c b/tests/libtest/lib1588.c +new file mode 100644 +index 0000000..b4022b3 +--- /dev/null ++++ b/tests/libtest/lib1588.c +@@ -0,0 +1,124 @@ ++/*************************************************************************** ++ * _ _ ____ _ ++ * Project ___| | | | _ \| | ++ * / __| | | | |_) | | ++ * | (__| |_| | _ <| |___ ++ * \___|\___/|_| \_\_____| ++ * ++ * Copyright (C) Daniel Stenberg, , et al. ++ * ++ * 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 ++ * ++ ***************************************************************************/ ++/* ++ * argv1 = URL ++ * argv2 = proxy host ++ * argv3 = proxy port ++ * argv4 = proxyuser:password ++ */ ++ ++#include "test.h" ++ ++#include "testutil.h" ++#include "warnless.h" ++#include "memdebug.h" ++ ++static CURLcode init1588(CURL *curl, const char *url, ++ const char *userpwd, const char *proxy) ++{ ++ CURLcode res = CURLE_OK; ++ ++ easy_setopt(curl, CURLOPT_URL, url); ++ easy_setopt(curl, CURLOPT_PROXY, proxy); ++ easy_setopt(curl, CURLOPT_PROXYUSERPWD, userpwd); ++ easy_setopt(curl, CURLOPT_PROXYAUTH, (long)CURLAUTH_DIGEST); ++ easy_setopt(curl, CURLOPT_VERBOSE, 1L); ++ easy_setopt(curl, CURLOPT_HEADER, 1L); ++ ++test_cleanup: ++ return res; ++} ++ ++static CURLcode run1588(CURL *curl, const char *url, const char *userpwd, ++ const char *proxy) ++{ ++ CURLcode res = init1588(curl, url, userpwd, proxy); ++ if(res) ++ return res; ++ return curl_easy_perform(curl); ++} ++ ++CURLcode test(char *URL) ++{ ++ CURLcode res = CURLE_OK; ++ CURL *curl = NULL; ++ const char *proxyuserpws = libtest_arg4; ++ struct curl_slist *host = NULL; ++ struct curl_slist *host2 = NULL; ++ char proxy1_resolve[128]; ++ char proxy2_resolve[128]; ++ char proxy1_connect[128]; ++ char proxy2_connect[128]; ++ ++ if(!libtest_arg2 || !libtest_arg3 || !libtest_arg4) ++ return TEST_ERR_MAJOR_BAD; ++ ++ curl_msnprintf(proxy1_resolve, sizeof(proxy1_resolve), ++ "firstproxy:%s:%s", libtest_arg3, libtest_arg2); ++ curl_msnprintf(proxy2_resolve, sizeof(proxy2_resolve), ++ "secondproxy:%s:%s", libtest_arg3, libtest_arg2); ++ ++ /* we connect to the fake host name but the right port number */ ++ curl_msnprintf(proxy1_connect, sizeof(proxy1_connect), ++ "firstproxy:%s", libtest_arg3); ++ curl_msnprintf(proxy2_connect, sizeof(proxy2_connect), ++ "secondproxy:%s", libtest_arg3); ++ ++ global_init(CURL_GLOBAL_ALL); ++ ++ easy_init(curl); ++ ++ host = curl_slist_append(NULL, proxy1_resolve); ++ if(!host) { ++ res = CURLE_OUT_OF_MEMORY; ++ goto test_cleanup; ++ } ++ host2 = curl_slist_append(host, proxy2_resolve); ++ if(!host2) { ++ res = CURLE_OUT_OF_MEMORY; ++ goto test_cleanup; ++ } ++ host = host2; ++ ++ start_test_timing(); ++ ++ easy_setopt(curl, CURLOPT_RESOLVE, host); ++ ++ res = run1588(curl, URL, proxyuserpws, proxy1_connect); ++ if(res) ++ goto test_cleanup; ++ ++ curl_mfprintf(stderr, "lib1588: now we do the request again\n"); ++ ++ res = run1588(curl, URL, proxyuserpws, proxy2_connect); ++ ++test_cleanup: ++ ++ /* proper cleanup sequence - type PB */ ++ ++ curl_easy_cleanup(curl); ++ curl_global_cleanup(); ++ curl_slist_free_all(host); ++ return res; ++} diff -Nru curl-8.14.1/debian/patches/cookie-don-t-treat-the-leading-slash-as-trailing.patch curl-8.14.1/debian/patches/cookie-don-t-treat-the-leading-slash-as-trailing.patch --- curl-8.14.1/debian/patches/cookie-don-t-treat-the-leading-slash-as-trailing.patch 2026-01-30 02:20:09.000000000 +0000 +++ curl-8.14.1/debian/patches/cookie-don-t-treat-the-leading-slash-as-trailing.patch 2026-05-08 01:36:52.000000000 +0000 @@ -1,4 +1,3 @@ -From c6ae07c6a541e0e96d0040afb62b45dd37711300 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 11 Aug 2025 20:23:05 +0200 Subject: [PATCH] cookie: don't treat the leading slash as trailing @@ -13,7 +12,7 @@ 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/cookie.c b/lib/cookie.c -index 914a4aca1..b72dd99bc 100644 +index 1a8426c..bfdd4ad 100644 --- a/lib/cookie.c +++ b/lib/cookie.c @@ -296,9 +296,9 @@ static char *sanitize_cookie_path(const char *cookie_path) @@ -49,6 +48,3 @@ if(sep) cllen = sep - clist->spath; else --- -2.47.3 - diff -Nru curl-8.14.1/debian/patches/curl_path_make_SFTP_handle_a_path.patch curl-8.14.1/debian/patches/curl_path_make_SFTP_handle_a_path.patch --- curl-8.14.1/debian/patches/curl_path_make_SFTP_handle_a_path.patch 2026-01-30 02:20:09.000000000 +0000 +++ curl-8.14.1/debian/patches/curl_path_make_SFTP_handle_a_path.patch 2026-05-08 01:36:52.000000000 +0000 @@ -1,4 +1,3 @@ -From 0ede81dcc61844cecce8904fb4de24319afeb024 Mon Sep 17 00:00:00 2001 From: Carlos Henrique Lima Melara Date: Thu, 5 Jun 2025 14:29:06 +0200 Subject: [PATCH] curl_path: make SFTP handle a path like /~ properly. @@ -12,7 +11,7 @@ 1 file changed, 6 insertions(+) diff --git a/lib/vssh/curl_path.c b/lib/vssh/curl_path.c -index 117d2e6009f6..474a5ecb8e27 100644 +index 117d2e6..474a5ec 100644 --- a/lib/vssh/curl_path.c +++ b/lib/vssh/curl_path.c @@ -84,6 +84,12 @@ CURLcode Curl_getworkingpath(struct Curl_easy *data, diff -Nru curl-8.14.1/debian/patches/series curl-8.14.1/debian/patches/series --- curl-8.14.1/debian/patches/series 2026-01-30 02:20:09.000000000 +0000 +++ curl-8.14.1/debian/patches/series 2026-05-08 01:36:52.000000000 +0000 @@ -1,19 +1,26 @@ ZZZgnutls-build.patch build-Divide-mit-krb5-gssapi-link-flags-between-LDFLAGS-a.patch 11_omit-directories-from-config.patch - -# Post 8.14.1 patches tool_getparam_fix_ftp_pasv.patch curl_path_make_SFTP_handle_a_path.patch tool_operate_fix_return_code_when_retry_is_used_but_not_triggered.patch - -# CVE-2025-9086 cookie-don-t-treat-the-leading-slash-as-trailing.patch - CVE-2025-10148.patch - wcurl-Set-CURL_OPTIONS-right-before-the-url.patch wcurl-Fix-example-for-continue-at.patch -# CVE-2025-11563 wcurl-CVE-2025-11563.patch CVE-2025-13034.patch +CVE-2025-14524.patch +CVE-2025-14819.patch +CVE-2026-1965_1.patch +CVE-2026-1965_2.patch +CVE-2026-3783.patch +CVE-2026-3784.patch +CVE-2026-3805.patch +CVE-2026-4873.patch +CVE-2026-5545.patch +CVE-2026-6253.patch +CVE-2026-5773.patch +CVE-2026-6276.patch +CVE-2026-7168.patch +CVE-2026-6429.patch diff -Nru curl-8.14.1/debian/patches/tool_getparam_fix_ftp_pasv.patch curl-8.14.1/debian/patches/tool_getparam_fix_ftp_pasv.patch --- curl-8.14.1/debian/patches/tool_getparam_fix_ftp_pasv.patch 2026-01-30 02:20:09.000000000 +0000 +++ curl-8.14.1/debian/patches/tool_getparam_fix_ftp_pasv.patch 2026-05-08 01:36:52.000000000 +0000 @@ -1,4 +1,3 @@ -From 5f805eec1149c218145097ec2a24ac7fb7d46f25 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Fri, 6 Jun 2025 10:21:09 -0700 Subject: [PATCH] tool_getparam: fix --ftp-pasv @@ -13,15 +12,15 @@ Fixes #17545 Closes #17547 --- - docs/cmdline-opts/ftp-pasv.md | 3 +- - src/tool_getparam.c | 8 ++--- - tests/data/Makefile.am | 2 +- - tests/data/test1547 | 59 +++++++++++++++++++++++++++++++++++ - 4 files changed, 66 insertions(+), 6 deletions(-) - create mode 100644 tests/data/test1547 + docs/cmdline-opts/ftp-pasv.md | 3 ++- + src/tool_getparam.c | 8 ++++---- + tests/data/Makefile.am | 2 +- + tests/data/{test1153 => test1547} | 9 +++------ + 4 files changed, 10 insertions(+), 12 deletions(-) + copy tests/data/{test1153 => test1547} (88%) diff --git a/docs/cmdline-opts/ftp-pasv.md b/docs/cmdline-opts/ftp-pasv.md -index 964f9769ae59..02deee30ded8 100644 +index 964f976..02deee3 100644 --- a/docs/cmdline-opts/ftp-pasv.md +++ b/docs/cmdline-opts/ftp-pasv.md @@ -6,7 +6,8 @@ Help: Send PASV/EPSV instead of PORT @@ -35,7 +34,7 @@ - disable-epsv Example: diff --git a/src/tool_getparam.c b/src/tool_getparam.c -index 51156e46b97e..6d7020987d0a 100644 +index 51156e4..6d70209 100644 --- a/src/tool_getparam.c +++ b/src/tool_getparam.c @@ -153,7 +153,7 @@ static const struct LongShort aliases[]= { @@ -68,7 +67,7 @@ /* socks5 proxy to use, and resolves the name locally and passes on the resolved address */ diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am -index 1ef85cd3a2da..446674605835 100644 +index 1ef85cd..4466746 100644 --- a/tests/data/Makefile.am +++ b/tests/data/Makefile.am @@ -203,7 +203,7 @@ test1508 test1509 test1510 test1511 test1512 test1513 test1514 test1515 \ @@ -80,68 +79,40 @@ \ test1550 test1551 test1552 test1553 test1554 test1555 test1556 test1557 \ test1558 test1559 test1560 test1561 test1562 test1563 test1564 test1565 \ -diff --git a/tests/data/test1547 b/tests/data/test1547 -new file mode 100644 -index 000000000000..244151a5abd1 ---- /dev/null +diff --git a/tests/data/test1153 b/tests/data/test1547 +similarity index 88% +copy from tests/data/test1153 +copy to tests/data/test1547 +index 56ed840..244151a 100644 +--- a/tests/data/test1153 +++ b/tests/data/test1547 -@@ -0,0 +1,59 @@ -+ +@@ -1,4 +1,5 @@ + +# Based on test100 & test101 -+ -+ -+FTP -+PASV -+LIST -+ -+ -+# -+# Server-side -+ -+ -+total 20 -+drwxr-xr-x 8 98 98 512 Oct 22 13:06 . -+drwxr-xr-x 8 98 98 512 Oct 22 13:06 .. -+drwxr-xr-x 2 98 98 512 May 2 1996 curl-releases -+-r--r--r-- 1 0 1 35 Jul 16 1996 README -+lrwxrwxrwx 1 0 1 7 Dec 9 1999 bin -> usr/bin -+dr-xr-xr-x 2 0 1 512 Oct 1 1997 dev -+drwxrwxrwx 2 98 98 512 May 29 16:04 download.html -+dr-xr-xr-x 2 0 1 512 Nov 30 1995 etc -+drwxrwxrwx 2 98 1 512 Oct 30 14:33 pub -+dr-xr-xr-x 5 0 1 512 Oct 1 1997 usr -+ -+ -+ -+# -+# Client-side -+ -+ -+ftp -+ -+ + + + FTP +@@ -9,10 +10,6 @@ LIST + # + # Server-side + +- +-REPLY PWD 257 "/""hello""" +- +- + + total 20 + drwxr-xr-x 8 98 98 512 Oct 22 13:06 . +@@ -35,10 +32,10 @@ dr-xr-xr-x 5 0 1 512 Oct 1 1997 usr + ftp + + +-FTP with quoted double quotes +FTP dir list PASV overriding PORT -+ -+ + + +-ftp://%HOSTIP:%FTPPORT/test-%TESTNUMBER/ +ftp://%HOSTIP:%FTPPORT/test-%TESTNUMBER/ -P %CLIENTIP --ftp-pasv -+ -+ -+ -+# -+# Verify data after the test has been "shot" -+ -+ -+QUIT -+ -+ -+USER anonymous -+PASS ftp@example.com -+PWD -+CWD test-%TESTNUMBER -+EPSV -+TYPE A -+LIST -+QUIT -+ -+ -+ + + + diff -Nru curl-8.14.1/debian/patches/tool_operate_fix_return_code_when_retry_is_used_but_not_triggered.patch curl-8.14.1/debian/patches/tool_operate_fix_return_code_when_retry_is_used_but_not_triggered.patch --- curl-8.14.1/debian/patches/tool_operate_fix_return_code_when_retry_is_used_but_not_triggered.patch 2026-01-30 02:20:09.000000000 +0000 +++ curl-8.14.1/debian/patches/tool_operate_fix_return_code_when_retry_is_used_but_not_triggered.patch 2026-05-08 01:36:52.000000000 +0000 @@ -1,4 +1,3 @@ -From b42776b4f4a6e9c9f5e3ff49d7bf610ad99c45c9 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 9 Jun 2025 08:37:49 +0200 Subject: [PATCH] tool_operate: fix return code when --retry is used but not @@ -10,14 +9,14 @@ Fixes #17554 Closes #17559 --- - src/tool_operate.c | 3 +- - tests/data/Makefile.am | 2 +- - tests/data/test752 | 72 ++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 75 insertions(+), 2 deletions(-) - create mode 100644 tests/data/test752 + src/tool_operate.c | 3 ++- + tests/data/Makefile.am | 2 +- + tests/data/{test499 => test752} | 19 +++++++++++++------ + 3 files changed, 16 insertions(+), 8 deletions(-) + copy tests/data/{test499 => test752} (80%) diff --git a/src/tool_operate.c b/src/tool_operate.c -index 24e79e6f61fa..2397de1686d9 100644 +index 24e79e6..2397de1 100644 --- a/src/tool_operate.c +++ b/src/tool_operate.c @@ -548,8 +548,9 @@ static CURLcode retrycheck(struct OperationConfig *config, @@ -32,7 +31,7 @@ diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am -index 446674605835..ab21e0e220be 100644 +index 4466746..ab21e0e 100644 --- a/tests/data/Makefile.am +++ b/tests/data/Makefile.am @@ -107,7 +107,7 @@ test709 test710 test711 test712 test713 test714 test715 test716 test717 \ @@ -44,81 +43,77 @@ \ test780 test781 test782 test783 test784 test785 test786 test787 test788 \ test789 test790 test791 \ -diff --git a/tests/data/test752 b/tests/data/test752 -new file mode 100644 -index 000000000000..00f14909d125 ---- /dev/null +diff --git a/tests/data/test499 b/tests/data/test752 +similarity index 80% +copy from tests/data/test499 +copy to tests/data/test752 +index d4040b0..00f1490 100644 +--- a/tests/data/test499 +++ b/tests/data/test752 -@@ -0,0 +1,72 @@ -+ -+ -+ -+HTTP -+HTTP GET +@@ -3,14 +3,16 @@ + + HTTP + HTTP GET +-f +--retry -+ -+ -+ -+# -+# Server-side -+ + + + + # + # Server-side + +- +-HTTP/1.1 200 OK + +HTTP/1.1 404 nopes -+Date: Tue, 09 Nov 2010 14:49:00 GMT -+Server: test-server/fake -+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT -+ETag: "21025-dc7-39462498" -+Accept-Ranges: bytes -+Content-Length: 6 -+Connection: close -+Content-Type: text/html -+Funny-head: yesyes -+ -+-foo- -+ + Date: Tue, 09 Nov 2010 14:49:00 GMT + Server: test-server/fake + Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT +@@ -23,8 +25,9 @@ Funny-head: yesyes + + -foo- + + -+ + +-HTTP/1.1 200 OK +HTTP/1.1 404 nopes -+Date: Tue, 09 Nov 2010 14:49:00 GMT -+Server: test-server/fake -+Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT -+ETag: "21025-dc7-39462498" -+Accept-Ranges: bytes -+Content-Length: 6 -+Connection: close -+Content-Type: text/html -+Funny-head: yesyes -+ -+ -+ + Date: Tue, 09 Nov 2010 14:49:00 GMT + Server: test-server/fake + Last-Modified: Tue, 13 Jun 2000 12:10:00 GMT +@@ -34,6 +37,7 @@ Content-Length: 6 + Connection: close + Content-Type: text/html + Funny-head: yesyes + -+# -+# Client-side -+ -+ -+http -+ -+ + + + +@@ -44,10 +48,10 @@ Funny-head: yesyes + http + + +-HTTP HEAD to server still sending a body +--retry and -f on a HTTP 404 response -+ -+ + + +-http://%HOSTIP:%HTTPPORT/%TESTNUMBER -I +http://%HOSTIP:%HTTPPORT/%TESTNUMBER -f --retry 1 -+ -+ -+ -+# -+# Verify data after the test has been "shot" -+ -+ + + + +@@ -55,11 +59,14 @@ http://%HOSTIP:%HTTPPORT/%TESTNUMBER -I + # Verify data after the test has been "shot" + + +-HEAD /%TESTNUMBER HTTP/1.1 +GET /%TESTNUMBER HTTP/1.1 -+Host: %HOSTIP:%HTTPPORT -+User-Agent: curl/%VERSION -+Accept: */* -+ -+ + Host: %HOSTIP:%HTTPPORT + User-Agent: curl/%VERSION + Accept: */* + + + +22 + -+ -+ + + diff -Nru curl-8.14.1/debian/patches/wcurl-Fix-example-for-continue-at.patch curl-8.14.1/debian/patches/wcurl-Fix-example-for-continue-at.patch --- curl-8.14.1/debian/patches/wcurl-Fix-example-for-continue-at.patch 2026-01-30 02:20:09.000000000 +0000 +++ curl-8.14.1/debian/patches/wcurl-Fix-example-for-continue-at.patch 2026-05-08 01:36:52.000000000 +0000 @@ -1,4 +1,3 @@ -From 946caf42d51ada8e11f19f7d06268dfc18a589fe Mon Sep 17 00:00:00 2001 From: Samuel Henrique Date: Sun, 21 Sep 2025 18:58:46 +0200 Subject: [PATCH] Fix example for "continue-at" diff -Nru curl-8.14.1/debian/patches/wcurl-Set-CURL_OPTIONS-right-before-the-url.patch curl-8.14.1/debian/patches/wcurl-Set-CURL_OPTIONS-right-before-the-url.patch --- curl-8.14.1/debian/patches/wcurl-Set-CURL_OPTIONS-right-before-the-url.patch 2026-01-30 02:20:09.000000000 +0000 +++ curl-8.14.1/debian/patches/wcurl-Set-CURL_OPTIONS-right-before-the-url.patch 2026-05-08 01:36:52.000000000 +0000 @@ -1,4 +1,3 @@ -From 57f544e831fcad6eca21760a3233b6b3f7e36fce Mon Sep 17 00:00:00 2001 From: Samuel Henrique Date: Sun, 21 Sep 2025 19:32:46 +0200 Subject: [PATCH] Set CURL_OPTIONS right before the url