Repository navigation
http: ignore Proxy-Authenticate unless the response comes from a proxy - #23002
Closed
MegaManSec wants to merge 1 commit into
Closed
MegaManSec wants to merge 1 commit into
MegaManSec wants to merge 1 commit into
Conversation
MegaManSec
force-pushed
the
proxy-digest-direct-poison
branch
from
September 18, 2026 22:17
e88ec61 to
b8cd52b
Compare
bagder
approved these changes
Sep 19, 2026
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
CONNECT-tunneled origin responses can still poison proxy authentication state because the proxy peer remains present.
Get a fresh assessment by requesting another Copilot review.
Review effort: Balanced
Findings: 1
What changed in this PR
Prevents direct-origin 407 responses from contaminating HTTP proxy authentication state.
Changes:
- Ignores proxy-authentication headers when no HTTP proxy peer exists.
- Makes stale Digest state reset fail closed.
- Adds regression test 1616.
| File | Description |
|---|---|
lib/http.c |
Gates proxy-auth challenge handling. |
lib/http_digest.c |
Strengthens Digest origin validation. |
tests/libtest/lib1616.c |
Exercises proxy-state contamination. |
tests/libtest/Makefile.inc |
Registers the libtest. |
tests/data/test1616 |
Defines responses and expected requests. |
tests/data/Makefile.am |
Registers test 1616. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
A 407 response was parsed for proxy authentication without checking where it came from, so a host reached directly, or an origin reached through a CONNECT tunnel, could set the proxy auth state. A later request to the proxy then sent a Proxy-Authorization built from the realm and nonce of that host, before the proxy challenged. The proxy peer stays set for tunnels, so gate on origin_is_proxy, the same condition Curl_http_output_auth() uses to emit these headers. Also flush the Digest state when it has no origin. Add test 1616.
MegaManSec
force-pushed
the
proxy-digest-direct-poison
branch
from
September 19, 2026 09:04
b8cd52b to
b26865b
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

The
407+Proxy-authenticate:handler inhttp_header_p()does not check where the response came from, unlike theProxy-Connection:branch right above it. A host reached directly (NOPROXY exclusion, or a per-request empty proxy) can therefore setdata->state.proxydigestfrom its own 407, and so can an origin reached through a CONNECT tunnel, sincehttp_proxy.peerstays set for tunnels.The next request to the real proxy then sends a preemptive
Proxy-Authorization: Digestusing that host's realm and nonce. For the tunneled case curl retries immediately and puts the header on the CONNECT.Gate on
bits.origin_is_proxy, which is whatCurl_http_output_auth()already uses to decide whether to emit proxy auth headers, so the input and output sides agree. Proxy challenges for tunnels arrive in the CONNECT response and are handled by the proxy filters, so they are unaffected. This also covers the NTLM/Negotiate/Basic proxy state andCURLINFO_PROXYAUTH_AVAIL, whichCurl_http_input_auth()sets on the same path.digest_flush_stale()is additionally made to fail closed: withdigest->origin == NULLboth guards were false, so the state survived a peer change.Test 1616 covers both vectors: a proxied request, a NOPROXY-excluded host answering 407, the proxy again, then a tunneled origin answering 407, then the proxy again. It fails with either vector unfixed.