{"id":"GHSA-6cp8-v795-jr2j","summary":"Hackney has an infinite loop on non-token byte at start of an Alt-Svc entry","details":"### Summary\n\n[CVE-2026-47066](https://nvd.nist.gov/vuln/detail/CVE-2026-47066) is an infinite loop (CWE-835) in hackney's Alt-Svc response header parser (`src/hackney_altsvc.erl`). When an HTTP server returns an `Alt-Svc` header whose value begins with a non-token byte (e.g. `!`, `@`, `=`, `;`), the parser enters a tight tail-recursive loop that pins an Erlang scheduler at 100% CPU and permanently hangs the calling connection process. Because the parser is invoked synchronously on every HTTP response, any attacker-controlled origin can trigger the hang with a single-byte header value.\n\n### Details\n\n**1. Parser dispatch**\n\n`parse_and_cache/3` is called inside the hackney connection process on each HTTP response. It collects all `Alt-Svc` header values via `collect_altsvc_headers/1`, concatenates them, and passes the result to `parse/1`, which calls `parse_entries(Header, [])`.\n\n**2. Failed token consumption**\n\n`parse_entries/2` → `parse_entry/1` → `parse_protocol/1` → `parse_token(Data, \u003c\u003c\u003e\u003e)`. The function `parse_token/2` pattern-matches leading bytes: alphanumeric, `-`, `_`, whitespace, and comma all have explicit clauses. Any other byte (e.g. `!`) falls through to the catch-all:\n\n```erlang\nparse_token(Rest, \u003c\u003c\u003e\u003e) -\u003e {undefined, Rest}.\n```\n\nThis returns the *input unchanged* — no byte is consumed.\n\n**3. No-progress loop**\n\n`parse_entry` propagates `{undefined, Rest}` back to `parse_entries/2`, which calls `skip_comma(Rest)`. Because the first byte is not `,`, `skip_comma` also returns `Rest` unchanged. `parse_entries` then recurses with the identical buffer:\n\n```erlang\nparse_entries(Data, Acc)  % Data identical to previous iteration\n```\n\nErlang tail recursion never preempts on a pure CPU loop, so the scheduler is pinned and the process never yields or returns.\n\n**4. Root cause**\n\n`parse_entries/2` has no guard that detects zero-byte progress after a failed `parse_entry` call and no fallback to advance past the offending byte.\n\n### PoC\n\n1. Start an HTTP server that responds with the header `Alt-Svc: !` (any single non-token byte suffices).\n2. Issue any HTTP GET request via hackney to that server:\n   ```erlang\n   hackney:request(get, \"http://attacker.example/\", [], \u003c\u003c\u003e\u003e, [])\n   ```\n3. Observe that the call never returns; the Erlang scheduler hosting the connection process is pinned at 100% CPU indefinitely.\n\nAlternatively, call the parser directly: `hackney_altsvc:parse(\u003c\u003c\"!\"\u003e\u003e)` — the process hangs immediately.\n\n### Impact\n\nDenial of service via unbounded CPU consumption. Any application using hackney 2.0.0-beta.1 through 4.0.0 that connects to attacker-controlled HTTP endpoints is affected. No authentication is required; a single response header byte is sufficient to hang the connection process. Fixed in hackney 4.0.1. CVSS v4.0 score: **8.7 (HIGH)**.\n\n## Resources\n\n* Introduction commit: https://github.com/benoitc/hackney/commit/408e5fe20302226ea8c74dde2bcbd452d712b5b2\n* Patch commit: https://github.com/benoitc/hackney/commit/e548aba1f97ffa3f4750da7b772998fb78c01894","aliases":["CVE-2026-47066","EEF-CVE-2026-47066"],"modified":"2026-06-26T22:00:09.483096663Z","published":"2026-06-26T21:53:07Z","database_specific":{"severity":"HIGH","github_reviewed":true,"github_reviewed_at":"2026-06-26T21:53:07Z","nvd_published_at":"2026-05-25T15:16:21Z","cwe_ids":["CWE-835"]},"references":[{"type":"WEB","url":"https://github.com/benoitc/hackney/security/advisories/GHSA-6cp8-v795-jr2j"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-47066"},{"type":"WEB","url":"https://github.com/benoitc/hackney/commit/e548aba1f97ffa3f4750da7b772998fb78c01894"},{"type":"WEB","url":"https://cna.erlef.org/cves/CVE-2026-47066.html"},{"type":"PACKAGE","url":"https://github.com/benoitc/hackney"},{"type":"WEB","url":"https://osv.dev/vulnerability/EEF-CVE-2026-47066"}],"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-6cp8-v795-jr2j/GHSA-6cp8-v795-jr2j.json"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V4","score":"CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N"}]}