From 6ed1711ae498f91c78fc12d960f1298c32c5d01d Mon Sep 17 00:00:00 2001 From: Patrick Griffis Date: Fri, 4 Sep 2026 15:18:26 -0500 Subject: [PATCH] auth: Don't send Proxy-Authorization through an established tunnel After a CONNECT tunnel to an HTTPS origin is set up, the actual request travels inside the tunnel directly to the origin server. auth_msg_starting() attached Proxy-Authorization to every message including these, leaking the proxy credentials to the origin. Skip the proxy-auth handling entirely when the message's connection is a tunnel, and clear any Proxy-Authorization header from it. The proxy test suite requires Apache and a CONNECT-tunnel-with-TLS setup that the in-tree harness does not provide, so this has no automated regression test here. Fixes #534 (CVE-2026-66339) --- libsoup/auth/soup-auth-manager.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/libsoup/auth/soup-auth-manager.c b/libsoup/auth/soup-auth-manager.c index c494ceec..fffbe6cf 100644 --- a/libsoup/auth/soup-auth-manager.c +++ b/libsoup/auth/soup-auth-manager.c @@ -15,6 +15,7 @@ #include "soup.h" #include "soup-connection-auth.h" #include "soup-message-private.h" +#include "soup-connection.h" #include "soup-message-headers-private.h" #include "soup-path-map.h" #include "soup-session-private.h" @@ -705,6 +706,8 @@ auth_msg_starting (SoupMessage *msg, gpointer manager) { SoupAuthManagerPrivate *priv = soup_auth_manager_get_instance_private (manager); SoupAuth *auth; + SoupConnection *conn; + gboolean tunnelled; if (soup_message_query_flags (msg, SOUP_MESSAGE_DO_NOT_USE_AUTH_CACHE)) return; @@ -722,6 +725,23 @@ auth_msg_starting (SoupMessage *msg, gpointer manager) update_authorization_header (msg, auth, FALSE); } + /* Proxy-Authorization must only be sent to the proxy itself, never on + * a request travelling through an established CONNECT tunnel to the + * origin server, which would leak the proxy credentials to the origin. + * The CONNECT request that sets the tunnel up is addressed to the + * proxy, so it still needs the header. + */ + conn = soup_message_get_connection (msg); + tunnelled = conn && soup_connection_is_tunnelled (conn) && + soup_message_get_method (msg) != SOUP_METHOD_CONNECT; + g_clear_object (&conn); + if (tunnelled) { + soup_message_set_proxy_auth (msg, NULL); + update_authorization_header (msg, NULL, TRUE); + g_mutex_unlock (&priv->mutex); + return; + } + auth = lookup_proxy_auth (priv, msg); if (auth) { authenticate_auth (manager, auth, msg, FALSE, TRUE, FALSE); -- GitLab