public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
* [rpms/curl] f44: Resolves: CVE-2026-8927 - env-set cross-proxy Digest auth state leak
@ 2026-08-24 14:03 Jan Macku
  0 siblings, 0 replies; only message in thread
From: Jan Macku @ 2026-08-24 14:03 UTC (permalink / raw)
  To: git-commits

A new commit has been pushed.

Repo   : rpms/curl
Branch : f44
Commit : 79b6ec61a5e6b675fd2b854f06b32d42f8c1cde0
Author : Jan Macku <jamacku@redhat.com>
Date   : 2026-08-24T13:37:29+02:00
Stats  : +341/-0 in 2 file(s)
URL    : https://src.fedoraproject.org/rpms/curl/c/79b6ec61a5e6b675fd2b854f06b32d42f8c1cde0?branch=f44

Log:
Resolves: CVE-2026-8927 - env-set cross-proxy Digest auth state leak

---
diff --git a/0018-curl-8.18.0-CVE-2026-8927.patch b/0018-curl-8.18.0-CVE-2026-8927.patch
new file mode 100644
index 0000000..fb9e5c8
--- /dev/null
+++ b/0018-curl-8.18.0-CVE-2026-8927.patch
@@ -0,0 +1,337 @@
+From 0c19379d6c470c2dda708d70bc68a0ed80757737 Mon Sep 17 00:00:00 2001
+From: Daniel Stenberg <daniel@haxx.se>
+Date: Mon, 18 May 2026 23:47:11 +0200
+Subject: [PATCH] url: detect proxy changes read from environment
+
+When a proxy is set from an environment variable, detect if that proxy
+is not the same as previously and flush state.
+
+Verified by test1647: verify changing proxy with env variables and make
+sure Digest state is flushed in the second use
+
+Closes #21666
+
+(cherry picked from commit 5c225384b8d52c67ce8259c6e4203bc57aacb567)
+---
+ lib/url.c                  |  11 ++++
+ lib/urldata.h              |   1 +
+ tests/data/Makefile.am     |   2 +
+ tests/data/test1647        | 103 +++++++++++++++++++++++++++++++
+ tests/libtest/Makefile.inc |   1 +
+ tests/libtest/lib1647.c    | 120 +++++++++++++++++++++++++++++++++++++
+ 6 files changed, 238 insertions(+)
+ create mode 100644 tests/data/test1647
+ create mode 100644 tests/libtest/lib1647.c
+
+diff --git a/lib/url.c b/lib/url.c
+index 603fec68b6..033e65369a 100644
+--- a/lib/url.c
++++ b/lib/url.c
+@@ -80,6 +80,7 @@
+ #include "escape.h"
+ #include "curl_share.h"
+ #include "http_digest.h"
++#include "vauth/vauth.h"
+ #include "multiif.h"
+ #include "getinfo.h"
+ #include "pop3.h"
+@@ -323,6 +324,9 @@ CURLcode Curl_close(struct Curl_easy **datap)
+   Curl_freeset(data);
+   Curl_headers_cleanup(data);
+   Curl_netrc_cleanup(&data->state.netrc);
++#ifndef CURL_DISABLE_DIGEST_AUTH
++  curlx_free(data->state.envproxy);
++#endif
+   curlx_free(data);
+   return CURLE_OK;
+ }
+@@ -2532,6 +2536,14 @@ static CURLcode create_conn_helper_init_proxy(struct Curl_easy *data,
+       result = CURLE_UNSUPPORTED_PROTOCOL;
+       goto out;
+ #else
++#ifndef CURL_DISABLE_DIGEST_AUTH
++      if(!Curl_safecmp(data->state.envproxy, proxy)) {
++        /* proxy changed */
++        Curl_auth_digest_cleanup(&data->state.proxydigest);
++        curlx_free(data->state.envproxy);
++        data->state.envproxy = curlx_strdup(proxy);
++      }
++#endif
+       /* force this connection's protocol to become HTTP if compatible */
+       if(!(conn->handler->protocol & PROTO_FAMILY_HTTP)) {
+         if((conn->handler->flags & PROTOPT_PROXY_AS_HTTP) &&
+diff --git a/lib/urldata.h b/lib/urldata.h
+index 221317e47e..1de8c4bfb1 100644
+--- a/lib/urldata.h
++++ b/lib/urldata.h
+@@ -967,6 +967,7 @@ struct UrlState {
+   void (*prev_signal)(int sig);
+ #endif
+ #ifndef CURL_DISABLE_DIGEST_AUTH
++  char *envproxy; /* last proxy string used for proxy-related state */
+   struct digestdata digest;      /* state data for host Digest auth */
+   struct digestdata proxydigest; /* state data for proxy Digest auth */
+ #endif
+diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am
+index 57e7508751..2a1c87ddc3 100644
+--- a/tests/data/Makefile.am
++++ b/tests/data/Makefile.am
+@@ -212,6 +212,8 @@ test1580 test1581 test1582 test1583 test1584 test1585 \
+ test1588 \
+ test1629 \
+ \
++test1647 \
++\
+ test1590 test1591 test1592 test1593 test1594 test1595 test1596 test1597 \
+ test1598 test1599 test1600 test1601 test1602 test1603 test1604 test1605 \
+ test1606 test1607 test1608 test1609 test1610 test1611 test1612 test1613 \
+diff --git a/tests/data/test1647 b/tests/data/test1647
+new file mode 100644
+index 0000000000..a87487fa9f
+--- /dev/null
++++ b/tests/data/test1647
+@@ -0,0 +1,103 @@
++<?xml version="1.0" encoding="US-ASCII"?>
++<testcase>
++<info>
++<keywords>
++HTTP
++HTTP GET
++HTTP proxy
++HTTP proxy Digest auth
++multi
++</keywords>
++</info>
++
++# Server-side
++<reply>
++
++# this is returned first since we get no proxy-auth
++<data crlf="headers" nocheck="yes">
++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.
++</data>
++
++# then this is returned when we get proxy-auth
++<data1000 crlf="headers">
++HTTP/1.1 200 OK
++Content-Length: 21
++Server: no
++
++Nice proxy auth sir!
++</data1000>
++
++<connect crlf="headers">
++HTTP/1.1 401 OK
++Content-Length: 21
++Server: no
++
++Denied access. Leave
++</connect>
++
++</reply>
++
++# Client-side
++<client>
++<server>
++http
++https-proxy
++https
++</server>
++# tool is what to use instead of 'curl'
++<tool>
++lib%TESTNUMBER
++</tool>
++<features>
++!SSPI
++crypto
++proxy
++digest
++Debug
++</features>
++<setenv>
++http_proxy=%HOSTIP:%HTTPPORT
++https_proxy=https://%HOSTIP:%HTTPSPROXYPORT
++CURL_ENTROPY=99376
++</setenv>
++<name>
++HTTP proxy auth Digest, then change proxy with env var and do it again
++</name>
++<command>
++http://test.remote.example.com/path/%TESTNUMBER https://another.example.com:%HTTPSPORT/ daniel:monkey123 another:bump456
++</command>
++</client>
++
++# Verify data after the test has been "shot"
++<verify>
++<protocol crlf="headers">
++GET http://test.remote.example.com/path/%TESTNUMBER HTTP/1.1
++Host: test.remote.example.com
++Accept: */*
++Proxy-Connection: Keep-Alive
++
++GET http://test.remote.example.com/path/%TESTNUMBER HTTP/1.1
++Host: test.remote.example.com
++Proxy-Authorization: Digest username="daniel", realm="weirdorealm", nonce="12345", uri="/path/%TESTNUMBER", response="7a1672891aff03248887b1a6674b8096"
++Accept: */*
++Proxy-Connection: Keep-Alive
++
++</protocol>
++
++<proxy crlf="headers">
++CONNECT another.example.com:%HTTPSPORT HTTP/1.1
++Host: another.example.com:%HTTPSPORT
++Proxy-Connection: Keep-Alive
++
++</proxy>
++
++# CONNECT fails
++<errorcode>
++7
++</errorcode>
++</verify>
++</testcase>
+diff --git a/tests/libtest/Makefile.inc b/tests/libtest/Makefile.inc
+index 76014f926a..0f8a2ea506 100644
+--- a/tests/libtest/Makefile.inc
++++ b/tests/libtest/Makefile.inc
+@@ -100,6 +100,7 @@ TESTS_C = \
+   lib1582.c lib1588.c \
+   lib1591.c lib1592.c lib1593.c lib1594.c                     lib1597.c \
+   lib1598.c lib1599.c \
++  lib1647.c \
+   lib1662.c \
+   lib1686.c \
+   lib1900.c lib1901.c lib1902.c lib1903.c lib1905.c lib1906.c lib1907.c \
+diff --git a/tests/libtest/lib1647.c b/tests/libtest/lib1647.c
+new file mode 100644
+index 0000000000..8060e1bfe9
+--- /dev/null
++++ b/tests/libtest/lib1647.c
+@@ -0,0 +1,120 @@
++/***************************************************************************
++ *                                  _   _ ____  _
++ *  Project                     ___| | | |  _ \| |
++ *                             / __| | | | |_) | |
++ *                            | (__| |_| |  _ <| |___
++ *                             \___|\___/|_| \_\_____|
++ *
++ * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, 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 = the first URL
++ * argv2 = URL2
++ * argv3 = credentials 1
++ * argv4 = credentials 2
++ */
++
++#include "first.h"
++
++/* this is meant to pick up the proxy from the environment variable */
++static CURLcode init1647(CURL *curl, const char *url, const char *userpwd)
++{
++  CURLcode result = CURLE_OK;
++
++  res_easy_setopt(curl, CURLOPT_URL, url);
++  if(result)
++    goto init_failed;
++
++  res_easy_setopt(curl, CURLOPT_PROXYUSERPWD, userpwd);
++  if(result)
++    goto init_failed;
++
++  res_easy_setopt(curl, CURLOPT_PROXYAUTH, CURLAUTH_DIGEST);
++  if(result)
++    goto init_failed;
++
++  res_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
++  if(result)
++    goto init_failed;
++
++  res_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
++  if(result)
++    goto init_failed;
++
++  res_easy_setopt(curl, CURLOPT_PROXY_SSL_VERIFYPEER, 0L);
++  if(result)
++    goto init_failed;
++
++  res_easy_setopt(curl, CURLOPT_PROXY_SSL_VERIFYHOST, 0L);
++  if(result)
++    goto init_failed;
++
++  res_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
++  if(result)
++    goto init_failed;
++
++  return CURLE_OK; /* success */
++
++init_failed:
++  return result; /* failure */
++}
++
++static CURLcode run1647(CURL *curl, const char *url, const char *userpwd)
++{
++  CURLcode result = CURLE_OK;
++
++  result = init1647(curl, url, userpwd);
++  if(result)
++    return result;
++
++  return curl_easy_perform(curl);
++}
++
++static CURLcode test_lib1647(const char *URL)
++{
++  CURLcode result = CURLE_OK;
++  CURL *curl = NULL;
++
++  res_global_init(CURL_GLOBAL_ALL);
++  if(result)
++    return result;
++
++  curl = curl_easy_init();
++  if(!curl) {
++    curl_mfprintf(stderr, "curl_easy_init() failed\n");
++    curl_global_cleanup();
++    return TEST_ERR_MAJOR_BAD;
++  }
++
++  start_test_timing();
++
++  curl_mprintf("--- First get '%s'\n", URL);
++  result = run1647(curl, URL, libtest_arg3);
++  if(result)
++    goto test_cleanup;
++
++  curl_mprintf("--- Then get '%s'\n", libtest_arg2);
++  result = run1647(curl, libtest_arg2, libtest_arg4);
++
++test_cleanup:
++
++  /* proper cleanup sequence - type PB */
++
++  curl_easy_cleanup(curl);
++  curl_global_cleanup();
++  return result;
++}
+-- 
+2.55.0
+

diff --git a/curl.spec b/curl.spec
index dcffdc6..cb7ef26 100644
--- a/curl.spec
+++ b/curl.spec
@@ -75,6 +75,9 @@ Patch016: 0016-curl-8.18.0-CVE-2026-8286.patch
 # Fix SASL double-free (CVE-2026-8925)
 Patch017: 0017-curl-8.18.0-CVE-2026-8925.patch
 
+# Fix env-set cross-proxy Digest auth state leak (CVE-2026-8927)
+Patch018: 0018-curl-8.18.0-CVE-2026-8927.patch
+
 # patch making libcurl multilib ready
 Patch101: 0101-curl-7.32.0-multilib.patch
 
@@ -504,6 +507,7 @@ rm -f ${RPM_BUILD_ROOT}%{_mandir}/man1/wcurl.1*
 - Fix proto-default skips SSH verification (CVE-2026-12064)
 - Fix wrong STARTTLS connection reuse (CVE-2026-8286)
 - Fix SASL double-free (CVE-2026-8925)
+- Fix env-set cross-proxy Digest auth state leak (CVE-2026-8927)
 
 * Wed Jul 29 2026 Jan Macku <jamacku@redhat.com> - 8.18.0-8
 - Fix trailing dot domain super cookie (CVE-2026-8924)

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2026-08-24 14:03 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-08-24 14:03 [rpms/curl] f44: Resolves: CVE-2026-8927 - env-set cross-proxy Digest auth state leak Jan Macku

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox