CVE-2026-70399 Overview
CVE-2026-70399 is a denial-of-service vulnerability in the Erlang/OTP inetshttpd web server. The flaw stems from Allocation of Resources Without Limits or Throttling [CWE-770] in the connection accept path. When operators do not explicitly set max_clients, the server accepts an unlimited number of simultaneous TCP connections instead of enforcing the documented default of 150. An unauthenticated remote attacker can open and hold connections until the Erlang node exhausts processes, memory, and file descriptors. No valid HTTP request and no authentication are required to trigger the condition.
Critical Impact
Unauthenticated remote attackers can exhaust Erlang node resources and take inetshttpd servers offline simply by opening and holding TCP connections.
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 before OTP 28.5.0.6 (inets 9.4 before 9.6.2.3)
- Erlang/OTP 29.0 before OTP 29.0.6 (inets 9.7 before 9.7.2)
Discovery Timeline
- 2026-09-01 - CVE-2026-70399 published to NVD
- 2026-09-01 - Last updated in NVD database
Technical Details for CVE-2026-70399
Vulnerability Analysis
The inets hardening guide documents max_clients as the primary denial-of-service defense, with a default value of 150. The implementation, however, does not apply that default when the option is unset. Instead, the accept gate in httpd_manager:handle_new_connection/4 reads the option with httpd_util:lookup/2, which returns the atom undefined when the key is absent. The neighbouring get_ustate/2 uses the three-argument lookup form that carries the 150 default, but the accept path does not.
The consequence surfaces in the connection count guard Count =< Max. Because Erlang term ordering places every integer before every atom, the comparison holds for any integer against undefined, and the server never returns {reject, busy}. Each accepted socket consumes a worker process and a file descriptor for as long as the client holds the connection.
Root Cause
The defect is a mismatched API call. httpd_util:lookup/2 cannot return the documented default, while httpd_util:lookup/3 can. The reliance on Erlang term ordering hides the bug at runtime because integer-versus-atom comparisons do not raise errors. Servers that explicitly configure max_clients are unaffected.
Attack Vector
An attacker opens TCP connections to the httpd listener and keeps them open. Each connection allocates an Erlang worker process and a socket. Once the accumulated connections exceed available processes, memory, or file descriptors, the node fails to serve legitimate traffic or crashes.
// Patch: lib/inets/src/http_lib/http_internal.hrl
-define(HTTP_MAX_VERSION_STRING, 8).
-define(HTTP_MAX_METHOD_STRING, 20).
-define(HTTP_MAX_CONTENT_LENGTH, 100000000).
+-define(HTTP_MAX_CLIENTS, 150).
// Patch: lib/inets/src/http_server/httpd_manager.erl
-moduledoc false.
-include("httpd.hrl").
+-include("../http_lib/http_internal.hrl").
-behaviour(gen_server).
Source: Erlang OTP commit 6746dc4. The fix introduces the HTTP_MAX_CLIENTS macro and includes it in httpd_manager, ensuring the 150-client default applies when no value is configured.
Detection Methods for CVE-2026-70399
Indicators of Compromise
- Sudden growth in Erlang node process counts and open file descriptors on hosts running inetshttpd.
- Repeated inbound TCP connections from the same source addresses that remain established without issuing HTTP requests.
- Rising socket counts on the httpd listen port with no corresponding request logs.
- Erlang node crash dumps referencing system_limit on processes or ports.
Detection Strategies
- Monitor erlang:system_info(process_count) and erlang:system_info(port_count) against configured limits.
- Compare active TCP connections on the httpd port with recent HTTP request volume; large divergence indicates connection holding.
- Alert on httpd configurations where max_clients is not explicitly set on affected inets versions.
Monitoring Recommendations
- Ingest network flow data and Erlang VM telemetry to correlate connection state with worker process allocation.
- Track file descriptor utilization per Erlang node and alert before ulimit is reached.
- Retain HTTP access logs alongside TCP accept counters to identify accept-without-request patterns.
How to Mitigate CVE-2026-70399
Immediate Actions Required
- Upgrade Erlang/OTP to 27.3.4.17, 28.5.0.6, or 29.0.6, matching your release train.
- Explicitly set max_clients in every httpd configuration until patched builds are deployed.
- Place inetshttpd listeners behind a reverse proxy or load balancer that enforces per-source connection limits.
Patch Information
The issue is fixed by adding a HTTP_MAX_CLIENTS macro and including it in httpd_manager. Fixes are available in the GitHub Security Advisory GHSA-pwvh-c689-f8q5, the CNA advisory, and commits 6746dc4, d94a94c, and e0050fc.
Workarounds
- Set max_clients explicitly in the httpd service configuration; a configured value is honored on all affected versions.
- Enforce connection rate limits and per-IP concurrent connection caps at the network edge.
- Reduce the operating system ulimit for the Erlang runtime to bound blast radius while patching is in progress.
# Example inets httpd configuration snippet enforcing max_clients
{max_clients, 150},
{server_name, "example"},
{port, 8080},
{server_root, "/var/inets"},
{document_root, "/var/inets/htdocs"}
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

