curl · Report #4041053
CVE-2026-94266: password leak in CURLINFO_EFFECTIVE_URL
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
url_set_data_creds_netrc()(lib/url.c:1325-1332) writes the.netrcuser/password directly intodata->state.uh, the handle later reused to compute the effective URL. It is never cleared.- On a redirect,
Curl_http_follow()callscurl_url_set(data->state.uh, CURLUPART_URL, newurl, ...)(http.c:1244), reparsing the same, already-dirty handle with theLocation:value. - For a relative
Location: /path,redirect_url()(urlapi.c:1334) computescutoff = strchr(protsep, '/')and copiesbase[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_URLENCODEonly percent-escapes non-unreserved bytes, so a plain alphanumeric password passes through unchanged. - The result is read back and stored:
Curl_bufref_set(&data->state.url, follow_url, ...)(http.c:1298) andinfof(data, "Issue another request to this URL: '%s'", follow_url)(http.c:1306). CURLINFO_EFFECTIVE_URLreturnsCurl_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_URLCURLINFO_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.