CVE-2026-55951 Overview
CVE-2026-55951 is a resource exhaustion vulnerability [CWE-770] in the Erlang/OTP httpc HTTP client shipped with the inets application. The client does not enforce a limit on the total size of response headers received from a server. The max_header_size option defaults to nolimit, and httpc_response:parse_headers/6 accumulates every header into a list before the length check runs, which only fires after the terminating CRLF CRLF is received. A malicious or compromised HTTP server can send a very large number of headers, or headers with very large values, causing the client to allocate unbounded memory until the host runs out of memory or the BEAM VM crashes.
Critical Impact
A proof-of-concept server sending 100,000 headers of roughly 4,000 bytes each caused the client VM to allocate over 13 GB of memory in under 30 seconds, crashing the Erlang node.
Affected Products
- Erlang/OTP 17.0 through versions before OTP 27.3.4.17 (inets 5.10 before 9.3.2.7)
- Erlang/OTP 28.0 through versions before OTP 28.5.0.6 (inets 9.4 before 9.6.2.3)
- Erlang/OTP 29.0 through versions before OTP 29.0.6 (inets 9.7 before 9.7.2)
Discovery Timeline
- 2026-09-01 - CVE-2026-55951 published to NVD
- 2026-09-01 - Last updated in NVD database
Technical Details for CVE-2026-55951
Vulnerability Analysis
The vulnerability sits in the response parsing path of the Erlang httpc client. When a response arrives, httpc_response:parse_headers/6 accumulates each header line into an in-memory list. The size check against max_header_size runs only after the parser observes the header terminator (CRLF CRLF). A server that never sends the terminator, or sends it only after emitting a very large header block, can force the client to hold every byte in memory. Because max_header_size defaults to nolimit, out-of-the-box deployments have no ceiling on this allocation.
Any application calling httpc:request/4,5 against untrusted endpoints is exposed. No authentication is required. A redirect to an attacker-controlled host, or an on-path adversary intercepting the connection, is sufficient to trigger the condition. The impact is denial of service against the calling Erlang node, which may host unrelated workloads on the same BEAM VM.
Root Cause
The inets HTTP client did not propagate the max_header_size and max_body_size request options into the connection handler's state. As a result, the parser had no bound to enforce during header accumulation, and the check that did exist ran too late in the parsing flow to prevent memory growth.
Attack Vector
An attacker controls or intercepts an HTTP server that the target application contacts through httpc:request. The server streams a large number of header lines, or a small number of headers with very large values, without sending the CRLF CRLF terminator early. The client process allocates memory for each header, consuming heap until the operating system kills the process or the BEAM VM aborts.
%% Patch: propagate max_header_size and max_body_size into handler state
%% File: lib/inets/src/http_client/httpc_handler.erl
MaxHeaderSize = proplists:get_value(max_header_size, Request#request.request_options),
MaxBodySize = proplists:get_value(max_body_size, Request#request.request_options),
{ok, State} =
case {Address /= Request#request.address, Request#request.scheme} of
{true, https} ->
connect_and_send_upgrade_request(Address, Request,
#state{max_header_size = MaxHeaderSize,
max_body_size = MaxBodySize,
options = Options,
profile_name = ProfileName});
{_, _} ->
connect_and_send_first_request(Address, Request,
#state{max_header_size = MaxHeaderSize,
max_body_size = MaxBodySize,
options = Options,
profile_name = ProfileName})
end,
%% Source: https://github.com/erlang/otp/commit/aba0fe8c2d700bf4ac94607cf7f00e53bbe4042d
Detection Methods for CVE-2026-55951
Indicators of Compromise
- Sudden, sustained memory growth in Erlang BEAM processes that make outbound HTTP calls via httpc.
- Erlang crash dumps referencing httpc_handler or httpc_response:parse_headers/6 with large binary or list allocations.
- Outbound HTTP responses with abnormally large header blocks or missing CRLF CRLF terminators observed on the network.
Detection Strategies
- Inventory Erlang/OTP and inets versions across build pipelines and runtime hosts, and flag anything below the fixed releases listed in GHSA-f9fw-mg7q-4g3x.
- Instrument httpc callers to record response header count and total header size, alerting on outliers.
- Correlate BEAM out-of-memory kills with recent outbound HTTP activity, including HTTP redirects to unexpected hosts.
Monitoring Recommendations
- Monitor process memory (erlang:memory/0) and per-process heap size for handlers spawned by the inets HTTP client.
- Log and alert on HTTP redirects that steer httpc clients to hosts outside an approved allowlist.
- Capture and retain BEAM crash dumps so header-parsing stacks can be reviewed after an incident.
How to Mitigate CVE-2026-55951
Immediate Actions Required
- Upgrade to Erlang/OTP 27.3.4.17, 28.5.0.6, or 29.0.6 (or newer) as tracked in the Erlang Ecosystem Foundation advisory.
- Set an explicit max_header_size and max_body_size on every httpc:request/4,5 call, even after patching, to enforce a defense-in-depth ceiling.
- Review outbound HTTP destinations and restrict httpc clients to trusted hosts where feasible.
Patch Information
The fix is delivered in commits aba0fe8 and e3be1cf. The patches propagate max_header_size and max_body_size from request options into the httpc_handler state so the parser can enforce the limits during header accumulation rather than only after CRLF CRLF. Additional bounds are added to integer parsing paths in eldap to mitigate related DoS classes. Additional references: OSV entry and Erlang version ordering.
Workarounds
- Pass explicit {max_header_size, N} and {max_body_size, N} values in the HTTPOptions argument to every httpc:request call.
- Disable automatic redirect following ({autoredirect, false}) for clients that talk to untrusted servers, to prevent unexpected host pivots.
- Route outbound HTTP through a hardened forward proxy that caps response header size and rejects malformed responses.
# Erlang shell example: enforce header and body limits per request
erl -eval '
inets:start(),
httpc:request(get, {"https://example.com/", []},
[{timeout, 15000},
{connect_timeout, 5000},
{autoredirect, false}],
[{max_header_size, 65536},
{max_body_size, 10485760}]).
'
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

