HexBrain

curl · Report #4041053

CVE-2026-94266: password leak in CURLINFO_EFFECTIVE_URL

Validstatus
1upvotes
14 Oct 2026disclosed

How it was found

A .netrc-sourced password, injected into the live URL handle at login time, survives an ordinary same-host relative Location: redirect and ends up verbatim in data->state.url, so it is exposed via CURLINFO_EFFECTIVE_URL, curl -w '%{url_effective}', and verbose (-v) output.

Affected code

https://github.com/curl/curl/blob/d1823ebc17e5778c30f8a6b2221a057ec607a9b7/lib/url.c#L1325-L1332

      result = Curl_creds_merge(ncreds_out->user, ncreds_out->passwd,
                                *pcreds, CREDS_NETRC, pcreds);
      if(result)
        goto out;
      /* for updated strings, we update them in the URL */
      uc = curl_url_set(data->state.uh, CURLUPART_USER,
                        Curl_creds_user(*pcreds), CURLU_URLENCODE);
      if(!uc)
        uc = curl_url_set(data->state.uh, CURLUPART_PASSWORD,
                          Curl_creds_passwd(*pcreds),
                          CURLU_URLENCODE);

https://github.com/curl/curl/blob/d1823ebc17e5778c30f8a6b2221a057ec607a9b7/lib/http.c#L1244

https://github.com/curl/curl/blob/d1823ebc17e5778c30f8a6b2221a057ec607a9b7/lib/http.c#L1298-L1306

https://github.com/curl/curl/blob/d1823ebc17e5778c30f8a6b2221a057ec607a9b7/lib/urlapi.c#L1334-L1401

https://github.com/curl/curl/blob/d1823ebc17e5778c30f8a6b2221a057ec607a9b7/lib/getinfo.c#L83-L86

Details

  1. url_set_data_creds_netrc() (lib/url.c:1325-1332) writes the .netrc user/password directly into data->state.uh, the handle later reused to compute the effective URL. It is never cleared.
  2. On a redirect, Curl_http_follow() calls curl_url_set(data->state.uh, CURLUPART_URL, newurl, ...) (http.c:1244), reparsing the same, already-dirty handle with the Location: value.
  3. For a relative Location: /path, redirect_url() (urlapi.c:1334) computes cutoff = strchr(protsep, '/') and copies base[0..cutoff), i.e. scheme://user:pass@host:port, verbatim into the new URL before appending the new path (urlapi.c:1355-1362, 1391-1397). CURLU_URLENCODE only percent-escapes non-unreserved bytes, so a plain alphanumeric password passes through unchanged.
  4. The result is read back and stored: Curl_bufref_set(&data->state.url, follow_url, ...) (http.c:1298) and infof(data, "Issue another request to this URL: '%s'", follow_url) (http.c:1306).
  5. CURLINFO_EFFECTIVE_URL returns Curl_bufref_ptr(&data->state.url) unsanitized (getinfo.c:84).

An absolute Location: does not leak: set_url() fully resets the handle before parsing, so no stale userinfo carries forward. Only the relative-reference path is affected. The first-hop effective URL is also clean, since data->state.url is populated (url.c) before the netrc injection runs; the leak appears starting from the first redirect.

Reproducer

.netrc:

machine 127.0.0.1
login netrcuser
password netrcSECRET123

Server: answers /first with 302 Found + Location: /newpath.

curl -v -L --netrc-file netrc_test --netrc-optional \
  -w '\nEFFECTIVE_URL=%{url_effective}\n' http://127.0.0.1:25036/first

Captured output (built from clean upstream commit d1823ebc17):

* Issue another request to this URL: 'http://netrcuser:[email protected]:25036/newpath'
...
EFFECTIVE_URL=http://netrcuser:[email protected]:25036/newpath

Confirmed identically via direct libcurl API (CURLOPT_NETRC=CURL_NETRC_OPTIONAL, CURLOPT_FOLLOWLOCATION=1, then curl_easy_getinfo(CURLINFO_EFFECTIVE_URL)):

CURLINFO_EFFECTIVE_URL = http://netrcuser:[email protected]:25036/newpath
RESULT: netrc password LEAKED into CURLINFO_EFFECTIVE_URL

Suggested fix

Strip userinfo from data->state.uh before it is used to compute the redirect follow-URL / effective URL, the same way the Referer builder already does (curl_url_set(u, CURLUPART_USER/PASSWORD, NULL, 0), http.c:1219-1221) and the non-tunnelling proxy request-target builder does (http.c:2161-2173). This needs to happen without disturbing the credentials curl still needs to send the actual Authorization header on the next hop.

Impact

The impact is disclosure of .netrc usernames and passwords into places that applications commonly treat as safe URL metadata:

  • CURLINFO_EFFECTIVE_URL
  • CURLINFO_REDIRECT_URL, even without following the redirect
  • %{url_effective} and %{redirect_url}
  • verbose/debug output

A server can trigger this by returning a relative Location:. If the application records, displays, returns, or forwards these values to logs, monitoring systems, users, or another service, the netrc password can escape its intended credential store.

The server does not directly receive the password, and absolute cross-origin redirects do not carry it. Exploitation therefore needs a secondary observer of the URL metadata or logs. That makes it a real confidentiality flaw, but likely low severity rather than direct remote credential theft.

This report was disclosed publicly on HackerOne and belongs to its author and the program. See the original