CVE-2026-47066: Infinite loop in Alt-Svc header parser in hackney
Summary
CVE-2026-47066 is an infinite loop (CWE-835) in hackney's Alt-Svc response header parser (src/hackneyaltsvc.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.
Details
1. Parser dispatch
parseandcache/3 is called inside the hackney connection process on each HTTP response. It collects all Alt-Svc header values via collectaltsvcheaders/1, concatenates them, and passes the result to parse/1, which calls parseentries(Header, []).
2. Failed token consumption
parseentries/2 → parseentry/1 → parseprotocol/1 → parsetoken(Data, <<>>). The function parsetoken/2 pattern-matches leading bytes: alphanumeric, -, , whitespace, and comma all have explicit clauses. Any other byte (e.g. !) falls through to the catch-all:
erlang parsetoken(Rest, <<>>) -> {undefined, Rest}.
This returns the input unchanged — no byte is consumed.
3. No-progress loop
parseentry propagates {undefined, Rest} back to parseentries/2, which calls skipcomma(Rest). Because the first byte is not ,, skipcomma also returns Rest unchanged. parseentries then recurses with the identical buffer:
erlang parseentries(Data, Acc) % Data identical to previous iteration
Erlang tail recursion never preempts on a pure CPU loop, so the scheduler is pinned and the process never yields or returns.
4. Root cause
parseentries/2 has no guard that detects zero-byte progress after a failed parseentry call and no fallback to advance past the offending byte.
PoC
1. Start an HTTP server that responds with the header Alt-Svc: ! (any single non-token byte suffices). 2. Issue any HTTP GET request via hackney to that server: erlang hackney:request(get, "http://attacker.example/", [], <<>>, []) 3. Observe that the call never returns; the Erlang scheduler hosting the connection process is pinned at 100% CPU indefinitely.
Alternatively, call the parser directly: hackneyaltsvc:parse(<<"!">>) — the process hangs immediately.
Impact
Denial 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).
Resources
Introduction commit: https://github.com/benoitc/hackney/commit/408e5fe20302226ea8c74dde2bcbd452d712b5b2 Patch commit: https://github.com/benoitc/hackney/commit/e548aba1f97ffa3f4750da7b772998fb78c01894
Other sources
Loop with Unreachable Exit Condition ('Infinite Loop') vulnerability in benoitc hackney allows Excessive Allocation. The Alt-Svc response header parser in src/hackneyaltsvc.erl does not guarantee forward progress. When parsetoken/2 receives a non-token, non-whitespace, non-comma byte (e.g. !, @, =, ;), it returns the input unchanged. skipcomma/1 also returns the buffer unchanged when the first byte is not a comma. parseentries/2 then recurses with identical data, creating a tight infinite tail-recursive loop that pins a scheduler at 100% CPU. The calling process never returns.
The entry point parseandcache/3 is called synchronously in the connection process on every HTTP response. A single-byte Alt-Svc: ! response header is sufficient to trigger the hang; the header is fully controlled by any HTTP origin the client connects to.
This issue affects hackney: from 2.0.0-beta.1 before 4.0.1.
— NVD
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
erlang/hackneyto a version that resolves this vulnerability.Fixed in 4.0.1 - Upgrade
Upgrade
hackneyto a version that resolves this vulnerability.Fixed in 4.0.1 - Compensating control
Prevent untrusted HTTP origins from being able to return attacker-controlled Alt-Svc header values (e.g., restrict outbound connections from clients using hackney to trusted destinations, or use network controls/allowlists to block attacker-controlled endpoints).
Event History
Frequently Asked Questions
Which deployments are exposed to this issue?
Deployments using hackney to make HTTP requests to an attacker-controlled origin are exposed. The affected parser is invoked synchronously for every HTTP response that contains Alt-Svc headers.
What must an attacker control to trigger the condition?
An attacker needs to operate or control an HTTP origin that can return an Alt-Svc response header. A header value beginning with a non-token byte, such as !, @, =, or ;, can trigger the loop; no authentication or user interaction is required.
What symptoms indicate that a process may have been affected?
The Erlang scheduler can be pinned at 100% CPU, and the hackney connection process handling the response can remain permanently hung. This can occur after receiving a crafted Alt-Svc header from a remote server.