{"id":"GHSA-f9vr-g2g2-x9fg","summary":"Hackney has CRLF / header injection in WebSocket upgrade request","details":"### Summary\n\nCRLF injection in hackney's WebSocket upgrade request builder (`src/hackney_ws.erl`). `init/1` copies the `host`, `path`, `headers`, and `protocols` options from the caller-supplied opts map verbatim into `#ws_data{}`, and `do_handshake/1` splices them directly into the raw HTTP/1.1 upgrade request by binary concatenation with no `\\r\\n` or `\\0` stripping. A caller that passes any of these fields from untrusted input can inject arbitrary header lines into the outbound upgrade request.\n\n### Details\n\n`do_handshake/1` builds the upgrade request at several concatenation sites:\n\n- **Host header** (lines 583–590): the host binary is written straight into `Host: \u003chost\u003e:\u003cport\u003e\\r\\n`.\n- **Sec-WebSocket-Protocol** (lines 601–602): protocol tokens are joined with `, ` and appended as a header line.\n- **Extra headers** (line 606): caller-supplied `{Name, Value}` tuples are concatenated as `Name: Value\\r\\n` with no sanitization of either component.\n- **Request path** (line 611): the path is interpolated into the `GET \u003cpath\u003e HTTP/1.1\\r\\n` request line.\n\nNone of these sites reject `\\r`, `\\n`, or `\\0`. A header value like `\u003c\u003c\"benign\\r\\nAuthorization: Bearer token\"\u003e\u003e` produces two distinct header lines on the wire. A path with an embedded `\\r\\n` rewrites the request line itself.\n\n### PoC\n\n1. Call `:hackney_ws.start_link/1` with `headers: [{\"X-User\", \"v\\r\\nAuthorization: Bearer attacker\"}]`.\n2. Connect to a raw TCP listener and capture the bytes hackney writes.\n3. The request contains a standalone `Authorization: Bearer attacker` line that the upstream WebSocket server parses as a legitimate header.\n\n### Impact\n\nHeader injection / request smuggling in outbound WebSocket upgrades. Affects hackney 2.0.0 through 4.0.0 wherever `host`, `path`, `headers`, or `protocols` options are populated from network or user input. Consequences include forging authentication headers toward the upstream server, log and cache poisoning, and request smuggling through intermediary proxies. CVSS v4.0: **6.9 (MEDIUM)**.\n\n## Resources\n\n* Introduction commit: https://github.com/benoitc/hackney/commit/690cecaf236fba49526da404a5bc889a24367a3e\n* Patch commit: https://github.com/benoitc/hackney/commit/52310ca807e7b48441ba0e9129171f535313fdd1","aliases":["CVE-2026-47072","EEF-CVE-2026-47072"],"modified":"2026-06-26T22:15:08.704592159Z","published":"2026-06-26T21:59:44Z","database_specific":{"severity":"MODERATE","github_reviewed":true,"github_reviewed_at":"2026-06-26T21:59:44Z","nvd_published_at":"2026-05-25T15:16:22Z","cwe_ids":["CWE-93"]},"references":[{"type":"WEB","url":"https://github.com/benoitc/hackney/security/advisories/GHSA-f9vr-g2g2-x9fg"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-47072"},{"type":"WEB","url":"https://github.com/benoitc/hackney/commit/52310ca807e7b48441ba0e9129171f535313fdd1"},{"type":"WEB","url":"https://cna.erlef.org/cves/CVE-2026-47072.html"},{"type":"PACKAGE","url":"https://github.com/benoitc/hackney"},{"type":"WEB","url":"https://osv.dev/vulnerability/EEF-CVE-2026-47072"}],"affected":[{"package":{"name":"hackney","ecosystem":"Hex","purl":"pkg:hex/hackney"},"ranges":[{"type":"SEMVER","events":[{"introduced":"2.0.0"},{"fixed":"4.0.1"}]}],"versions":["2.0.0","2.0.1","3.0.0","3.0.1","3.0.2","3.0.3","3.1.0","3.1.1","3.1.2","3.2.0","3.2.1","4.0.0"],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/06/GHSA-f9vr-g2g2-x9fg/GHSA-f9vr-g2g2-x9fg.json"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V4","score":"CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:H/SA:N"}]}