CVE-2026-48856
Description
Erlang OTP's httpc client leaks Authorization and Proxy-Authorization headers on cross-origin redirects, enabling credential theft.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Erlang OTP's httpc client leaks Authorization and Proxy-Authorization headers on cross-origin redirects, enabling credential theft.
Vulnerability
The httpc client in Erlang OTP's inets module, specifically in httpc_response.erl, forwards Authorization and Proxy-Authorization request headers to redirect targets without verifying if the redirect crosses an origin boundary. The httpc_response:redirect/2 function updates only the host field of the header record, copying all other fields verbatim, including sensitive authorization headers. This affects OTP versions from 17.0 before 29.0.2, 28.5.0.2, and 27.3.4.13, corresponding to inets versions from 5.10 before 9.7.1, 9.6.2.2, and 9.3.2.6 [2].
Exploitation
An attacker can control a server that a victim's httpc client contacts. The attacker's server can then issue a cross-origin 3xx redirect (e.g., 301, 302) to another server also controlled by the attacker. If the httpc client has autoredirect enabled (which is the default), it will follow the redirect, forwarding the Authorization and Proxy-Authorization headers to the attacker's controlled server, thereby exposing credentials [2, 4].
Impact
Successful exploitation allows an attacker to steal sensitive credentials, including Basic authentication credentials derived from URL userinfo, that are transmitted via the Authorization and Proxy-Authorization headers. This can lead to unauthorized access to resources or services that the victim is authenticated to [2, 4].
Mitigation
Patched versions include OTP 29.0.2, 28.5.0.2, and 27.3.4.13, and corresponding inets versions 9.7.1, 9.6.2.2, and 9.3.2.6 [2]. As a workaround, set {autoredirect, false} in httpc:request/4 options and manually handle redirects, stripping sensitive headers when crossing an origin boundary. Alternatively, ensure httpc is only used with trusted servers that do not issue cross-origin redirects [4]. Versions prior to OTP 17.0 are also affected [4].
AI Insight generated on Jun 10, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
3Patches
1688d748d6f7ainets/httpc: strip sensitive headers on cross-origin redirect
2 files changed · +73 −1
lib/inets/src/http_client/httpc_response.erl+21 −1 modified@@ -411,8 +411,28 @@ redirect(Response = {_, Headers, _}, Request) -> NewURI = uri_string:normalize( uri_string:recompose(URIMap)), HostPort = http_request:normalize_host(TScheme, THost, TPort), - NewHeaders = + NewHeaders0 = (Request#request.headers)#http_request_h{host = HostPort}, + %% RFC 9110 §15.4: strip Authorization, Proxy-Authorization, + %% Cookie, Origin, and Referer on cross-origin redirects + %% (different host or port). + NewHeaders = + case Request#request.address of + {THost, TPort} -> + NewHeaders0; + _ -> + CrossOriginOther = ["cookie", "origin"], + OtherStripped = lists:filter( + fun({K, _}) -> + not lists:member(string:lowercase(K), CrossOriginOther) + end, + NewHeaders0#http_request_h.other), + NewHeaders0#http_request_h{ + authorization = undefined, + 'proxy-authorization' = undefined, + referer = undefined, + other = OtherStripped} + end, NewRequest = Request#request{redircount = Request#request.redircount+1,
lib/inets/test/httpc_SUITE.erl+52 −0 modified@@ -193,6 +193,7 @@ only_simulated() -> redirect_temporary_redirect, redirect_permanent_redirect, redirect_relative_uri, + redirect_strips_sensitive_headers, port_in_host_header, redirect_port_in_host_header, relaxed, @@ -887,6 +888,40 @@ redirect_relative_different_port(Config) when is_list(Config) -> = httpc:request(post, {URL301, Headers, "text/plain", "foobar"}, [], RequestOpts, Profile). %%------------------------------------------------------------------------- +redirect_strips_sensitive_headers() -> + [{doc, "RFC 9110 §15.4: Authorization, Proxy-Authorization, Cookie, " + "Referer, and Origin headers MUST NOT be forwarded on cross-origin " + "(different host/port) redirects (CVE / GHSA-m75x-4vwg-ggjh)."}]. +redirect_strips_sensitive_headers(Config) when is_list(Config) -> + %% Origin server issues a 301 to a second sim_http server (different port + %% = cross-origin). The target echoes which sensitive headers it received + %% back as x-received-* response headers so the test can inspect them. + OriginUrl = url(group_name(Config), "/301_custom_url.html", Config), + RequestOpts = proplists:get_value(request_opts, Config, []), + Profile = ?profile(Config), + + TargetPort = server_start(sim_http, []), + {ok, Host} = inet:gethostname(), + TargetUrl = ?URL_START ++ Host ++ ":" ++ integer_to_list(TargetPort) ++ + "/capture_sensitive_redirect_target.html", + + RedirectHeaders = [{"x-test-301-url", TargetUrl}, + {"authorization", "Basic dXNlcjpzM2NyM3Q="}, + {"proxy-authorization", "Basic dXNlcjpzM2NyM3Q="}, + {"cookie", "session=secret"}, + {"referer", "http://example.com/secret"}, + {"origin", "http://example.com"}], + + {ok, {{_, 200, _}, RespHeaders, _}} = + httpc:request(get, {OriginUrl, RedirectHeaders}, [?SSL_NO_VERIFY], RequestOpts, Profile), + + ?assertEqual("false", proplists:get_value("x-received-authorization", RespHeaders)), + ?assertEqual("false", proplists:get_value("x-received-proxy-authorization", RespHeaders)), + ?assertEqual("false", proplists:get_value("x-received-cookie", RespHeaders)), + ?assertEqual("false", proplists:get_value("x-received-referer", RespHeaders)), + ?assertEqual("false", proplists:get_value("x-received-origin", RespHeaders)). + +%%------------------------------------------------------------------------- cookie() -> [{doc, "Test cookies on the default profile."}]. cookie(Config) when is_list(Config) -> @@ -3024,6 +3059,23 @@ handle_uri(_,"/delete_no_body.html", _,Headers,_, DefaultResponse) -> not_found -> DefaultResponse end; +%% Capture endpoint for redirect_strips_sensitive_headers. +%% Echoes presence of each sensitive header as an x-received-* response header. +handle_uri(_,"/capture_sensitive_redirect_target.html",_,Headers,_,_) -> + Present = fun(Name) -> + case proplists:is_defined(Name, Headers) of + true -> "true"; + false -> "false" + end + end, + "HTTP/1.1 200 OK\r\n" ++ + "Content-Length:0\r\n" ++ + "X-Received-Authorization:" ++ Present("authorization") ++ "\r\n" ++ + "X-Received-Proxy-Authorization:" ++ Present("proxy-authorization") ++ "\r\n" ++ + "X-Received-Cookie:" ++ Present("cookie") ++ "\r\n" ++ + "X-Received-Referer:" ++ Present("referer") ++ "\r\n" ++ + "X-Received-Origin:" ++ Present("origin") ++ "\r\n" ++ + "\r\n"; handle_uri(_,_,_,_,_,DefaultResponse) -> DefaultResponse.
Vulnerability mechanics
Root cause
"The httpc client forwards sensitive headers like Authorization and Proxy-Authorization to redirect targets without checking if the redirect crosses an origin boundary."
Attack vector
An attacker controls a server that a victim contacts using httpc. The attacker's server issues a 3xx redirect to another server also controlled by the attacker. The httpc client automatically follows this redirect, forwarding the Authorization and Proxy-Authorization headers to the attacker's second server, enabling credential theft [ref_id=1]. This occurs when automatic redirects are enabled, which is the default behavior.
Affected code
The vulnerability resides in the httpc_response:redirect/2 function within the lib/inets/src/http_client/httpc_response.erl file. The commit modifies this function to implement the stripping of sensitive headers on cross-origin redirects, as indicated by the added test case `redirect_strips_sensitive_headers/0` [patch_id=5502039].
What the fix does
The patch modifies the httpc_response:redirect/2 function to strip sensitive headers, including Authorization and Proxy-Authorization, when a redirect crosses an origin boundary (different host or port) [patch_id=5502039]. This aligns with RFC 9110, which mandates that these headers must not be forwarded on cross-origin redirects, thus preventing credential leakage.
Preconditions
- configAutomatic redirects must be enabled in httpc (this is the default).
- networkThe attacker must control at least two servers: one that the victim initially connects to, and another to which the redirect occurs.
Generated on Jun 10, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5News mentions
1- Erlang OTP: Seven Vulnerabilities Disclosed, Including High-Severity FlawsVypr Intelligence · Jun 10, 2026