Severity by source
CVSS:4.0/AV:L/AC:L/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
Primary rating from NVD · only source for this CVE.
CVSS VectorNVD
CVSS:4.0/AV:L/AC:L/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
Lifecycle Timeline
4DescriptionCVE.org
Interpretation Conflict vulnerability in benoitc hackney allows Server Side Request Forgery. hackney_url:normalize/2 URL-decodes the host component after the URL has been parsed into a #hackney_url{} record. OTP's uri_string:parse/1 and inet:parse_address/1 do not decode percent-escapes in the host, so a URL such as http://%31%32%37%2E%30%2E%30%2E%31/ is seen by a caller's allowlist validator with host %31%32%37%2E%30%2E%30%2E%31 (not an IP address), which passes the allowlist check. hackney's normalizer then decodes the host to 127.0.0.1 and opens a TCP connection to loopback. Because hackney:request/5 always calls hackney_url:normalize/2 with no opt-out, every request that takes a binary or list URL is affected. The same technique reaches cloud instance metadata services (169.254.169.254), RFC1918 networks, and any admin interface listening on localhost.
This issue affects hackney: from 0.13.0 before 4.0.1.
AnalysisAI
SSRF allowlist bypass in hackney (Erlang HTTP client) versions 0.13.0 through before 4.0.1 allows attackers who control URL input to circumvent application-level SSRF protections by supplying percent-encoded IP addresses as hostnames. The parser differential lies in hackney_url:normalize/2 decoding the host component post-parse: OTP's uri_string:parse/1 and inet:parse_address/1 see %31%36%39%2E%32%35%34%2E%31%36%39%2E%32%35%34 as a non-IP string (allowlist passes), while hackney then decodes it to 169.254.169.254 and establishes the TCP connection. A proof-of-concept exists per SSVC assessment; no active exploitation is confirmed in CISA KEV, and EPSS is very low at 0.01% (2nd percentile).
Technical ContextAI
CWE-436 (Interpretation Conflict) describes vulnerabilities where two components interpret the same data differently, creating an exploitable gap. Here, hackney_url:normalize/2 applies percent-decoding to the URL host field after OTP has already parsed the URL into a #hackney_url{} record - a deliberate normalization step with no caller opt-out. OTP's uri_string:parse/1 and inet:parse_address/1, which applications use to validate hosts against SSRF allowlists, intentionally do not decode percent-escapes in hostnames (RFC 3986 does not require IP literals to be percent-encoded). The result is that any caller performing allowlist validation on the pre-normalized URL operates on a fundamentally different value than hackney uses for connection. The affected CPE is cpe:2.3:a:benoitc:hackney:*:*:*:*:*:*:*:* across all Erlang/OTP platforms. Because hackney:request/5 unconditionally invokes normalize/2 with no bypass mechanism, every code path accepting binary or list URLs is vulnerable. Specially crafted targets include 127.0.0.1 (loopback admin interfaces), 169.254.169.254 (cloud instance metadata services), and arbitrary RFC1918 networks.
RemediationAI
Upgrade hackney to version 4.0.1 or later, which is the vendor-released patch per the advisory at https://github.com/benoitc/hackney/security/advisories/GHSA-pj7v-xfvx-wmjq. The fix (commit 452620a92ec1da2e6b4862a049a2a4f04b42068f at https://github.com/benoitc/hackney/commit/452620a92ec1da2e6b4862a049a2a4f04b42068f) adds a post-decode check inside normalize/2: if the percent-decoded host parses as an IP address via inet_parse:address/1 but the original pre-decoded form did not, the call raises {invalid_url_host, Host0} - rejecting the differential entirely while preserving IDN and percent-encoded UTF-8 hostnames. If immediate upgrade is not feasible, a compensating control is to move SSRF allowlist validation to execute after calling hackney_url:normalize/2 explicitly, so validation inspects the already-decoded host - this requires application-level refactoring and care to avoid race conditions between normalize and request dispatch. Defense-in-depth via network-layer blocking of 169.254.169.254 and RFC1918 ranges reduces blast radius but does not address all internal targets (e.g., loopback admin interfaces on non-standard ports) and should not be treated as a sufficient substitute for patching.
Denial of service in benoitc hackney (Erlang HTTP client) versions 2.0.0 through 4.0.0 allows a malicious WebSocket serv
Denial of service in benoitc hackney (Erlang HTTP client) 2.0.0 through 4.0.0 allows remote unauthenticated attackers to
Denial-of-service in benoitc's hackney Erlang HTTP client (versions 2.0.0-beta.1 through 4.0.0) allows any HTTP origin s
Allocation of Resources Without Limits or Throttling vulnerability in benoitc hackney allows Flooding. hackney_h3:await_
Denial of service in benoitc hackney (Erlang HTTP client) versions 0.10.0 through 4.0.0 lets a hostile SOCKS5 or HTTP CO
CRLF injection in hackney (Erlang HTTP client, versions 2.0.0-4.0.1) enables header injection into outbound WebSocket up
HTTP Request Splitting via CRLF injection in hackney, the Erlang/Elixir HTTP client library, allows an attacker who cont
Credential leakage in the hackney Erlang HTTP client library (versions 3.1.1 through before 4.0.1) allows a malicious or
CRLF injection in the hackney Erlang HTTP client library's hackney_cookie:setcookie/3 function enables HTTP response spl
Same weakness CWE-436 – Interpretation Conflict
View allShare
External POC / Exploit Code
Leaving vuln.today
EUVD-2026-31689
GHSA-pj7v-xfvx-wmjq