Skip to main content
Vulnerability Database/CVE-2026-73276

CVE-2026-73276: Erlang/OTP inets SSRF Vulnerability

CVE-2026-73276 is a Server-Side Request Forgery flaw in Erlang/OTP inets that enables HTTP Request Smuggling attacks. This article covers the technical details, affected OTP versions, security impact, and mitigation steps.

Published:

CVE-2026-73276 Overview

CVE-2026-73276 is an HTTP Request Smuggling vulnerability [CWE-444] in the Erlang/OTP inets httpd server. The gracefulness code in the HTTP header parser silently ignored malformed headers, including headers with whitespace before the colon, instead of rejecting them per RFC 7230 section 3.2.4. When inets is deployed behind a reverse proxy or load balancer that interprets the same headers differently, the desync allows attackers to smuggle requests across connection boundaries.

Critical Impact

A remote, unauthenticated attacker can smuggle HTTP requests through front-end proxies, bypassing access controls, poisoning caches, and hijacking sessions of other users behind the same connection.

Affected Products

  • Erlang/OTP 22.2 through versions before 27.3.4.17
  • Erlang/OTP 28.0 through versions before 28.5.0.6
  • Erlang/OTP 29.0 through versions before 29.0.6 (inets 7.1.2 to 9.3.2.7, 9.4 to 9.6.2.3, and 9.7 to 9.7.2)

Discovery Timeline

  • 2026-09-01 - CVE-2026-73276 published to NVD
  • 2026-09-01 - CVE record last modified in NVD database

Technical Details for CVE-2026-73276

Vulnerability Analysis

The flaw lives in the key_value/1 function in lib/inets/src/http_lib/http_request.erl. The parser splits each header line on the first colon, then verifies that the key does not have trailing whitespace. RFC 7230 requires that any whitespace between the field-name and the colon force rejection of the request. The pre-patch implementation instead returned undefined, which the caller in httpd_request.erl treated as an invalid line to skip. The header was silently dropped and request processing continued with the remaining headers.

Root Cause

The root cause is permissive error handling in the HTTP/1.1 header state machine. Skipping malformed headers rather than rejecting the message creates parsing disagreement between inets and any upstream proxy. A front-end that treats Content-Length : 10 (note the space before the colon) as a valid Content-Length will forward one framing, while inets will discard that header and fall back to a different framing (for example, Transfer-Encoding: chunked), producing a classic CL.TE or TE.CL desynchronization.

Attack Vector

Exploitation requires network access to a proxy fronting an inets httpd instance. The attacker sends a crafted request containing an ambiguous framing header with whitespace before the colon. Because the flaw is network-reachable and requires no authentication, it exposes any HTTP application served by inets behind a shared proxy.

erlang
%% Vulnerable pattern in lib/inets/src/http_lib/http_request.erl (pre-patch)
key_value(KeyValueStr) ->
    case lists:splitwith(fun($:) -> false; (_) -> true end, KeyValueStr) of
        {Key, [$: | Value]} when Key =/= [] ->
            %% RFC 7230 - 3.2.4 ... No whitespace is allowed between the header field-name and colon.
            case string:strip(Key, right) of
                Key ->
                    {http_util:to_lower(string:strip(Key, left)),  string:strip(Value)};
                _ ->
                    %% Ignore invalid header  <-- silently dropped instead of rejected
                    undefined
            end;
        {_, []} -> undefined;
        _ -> undefined
    end.

Source: GitHub OTP Commit 60add5a1

Detection Methods for CVE-2026-73276

Indicators of Compromise

  • HTTP requests reaching inets httpd with whitespace characters (space or tab) between a header field name and its colon, especially in Content-Length or Transfer-Encoding.
  • Requests containing both Transfer-Encoding and Content-Length headers where one of the two is malformed.
  • Unexpected 400 responses from patched instances after upgrade, indicating that a client or intermediary was previously relying on the silent-skip behavior.

Detection Strategies

  • Deploy a Web Application Firewall or reverse-proxy rule that rejects requests with whitespace before any header colon before they reach the Erlang backend.
  • Baseline the outbound inets request logs and alert on paired requests where the second request appears to originate from the same TCP connection but targets a privileged path.
  • Inspect access logs for prefixes of one request appearing inside the body or URI of the next, a classic smuggling signature.

Monitoring Recommendations

  • Enable verbose httpd access logging and forward events to a central analytics platform for correlation across proxy and application tiers.
  • Track version telemetry for the inets and OTP releases running on production hosts to confirm patch coverage.
  • Monitor for anomalous session use, such as a single connection producing responses that mix authenticated and unauthenticated identities.

How to Mitigate CVE-2026-73276

Immediate Actions Required

  • Upgrade Erlang/OTP to 27.3.4.17, 28.5.0.6, or 29.0.6, corresponding to inets 9.3.2.7, 9.6.2.3, or 9.7.2.
  • Inventory all services that embed inets httpd, including administrative endpoints of Erlang and Elixir applications, and confirm the fixed version is loaded.
  • Restrict direct network access to inets listeners so that only hardened proxies can reach them.

Patch Information

The fix changes key_value/1 to return {error, whitespace_before_colon} and updates httpd_request.erl to emit HTTP/1.1 400 Bad Request with the reason "whitespace before colon in header". Details are in the Erlang Ecosystem Foundation CNA advisory, the GitHub Security Advisory GHSA-6v7q-jwgh-cx8p, and commits 60add5a1, 6cd995e3, and c285240c.

Workarounds

  • Configure the fronting proxy (nginx, HAProxy, Apache) to strictly reject any header line containing whitespace before the colon and to normalize framing headers.
  • Disable HTTP/1.1 connection reuse (keep-alive) between the proxy and inets so that smuggled request fragments cannot span requests.
  • Prefer HTTP/2 or HTTP/3 between the proxy and origin where the deployment supports it, as request framing is length-prefixed rather than delimiter-based.
bash
# Example nginx hardening: drop requests with whitespace before header colons
# Place in the http {} block of nginx.conf
if ($http_transfer_encoding ~* "^\s") { return 400; }
if ($http_content_length ~* "^\s") { return 400; }
proxy_http_version 1.1;
proxy_set_header Connection "close";

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.