Automated Threat Modeling

Brief Summary: Netty SNI Handler Pre-Allocation DoS (CVE-2026-45416) Turns Nine Bytes Into 16 MiB of Memory Pressure

A short review of CVE-2026-45416, a high-severity denial-of-service vulnerability in Netty's SNI handler. A crafted TLS ClientHello of as few as nine bytes triggers a 16 MiB memory allocation because the default length guards are disabled.

CVE Analysis

8 min read

ZeroPath CVE Analysis
ZeroPath CVE Analysis

2026-06-12

Brief Summary: Netty SNI Handler Pre-Allocation DoS (CVE-2026-45416) Turns Nine Bytes Into 16 MiB of Memory Pressure
Experimental AI-Generated Content

This CVE analysis is an experimental publication that is completely AI-generated. The content may contain errors or inaccuracies and is subject to change as more information becomes available. We are continuously refining our process.

If you have feedback, questions, or notice any errors, please reach out to us.

[email protected]

Introduction

As few as nine bytes sent over a TCP connection can force a Netty-based server to allocate 16 MiB of unpooled direct memory, and the default SNI handler configuration does nothing to stop it. CVE-2026-45416 is a denial-of-service condition in Netty's SslClientHelloHandler. A crafted TLS ClientHello message gets past a disabled length guard and triggers a large memory pre-allocation, which stays in place until the attacker's connection closes.

Netty is the asynchronous network I/O framework underneath much of the Java ecosystem, including infrastructure components like Spring Boot, gRPC, Cassandra drivers, and Elasticsearch clients. It has roughly 35,000 GitHub stars and adopters including Airbnb and Apple, so a vulnerability in its TLS handling reaches widely across the industry.

Technical Information

Root Cause

The vulnerability lives in SslClientHelloHandler.decode() within the io.netty:netty-handler package. When a TLS ClientHello message arrives, the method reads the 24-bit handshake length field from the TLS record header. If the ClientHello does not fit entirely within the first TLS record, the code at line 161 eagerly allocates a buffer sized to the declared handshake length:

ctx.alloc().buffer(handshakeLength)

The intended safety mechanism is a guard at line 140:

handshakeLength > maxClientHelloLength && maxClientHelloLength != 0

This guard is supposed to reject oversized ClientHello messages. But the three most commonly used constructors for SNI handling all pass maxClientHelloLength=0 and handshakeTimeoutMillis=0:

ConstructormaxClientHelloLengthhandshakeTimeoutMillis
SniHandler(Mapping)00
SniHandler(AsyncMapping)00
AbstractSniHandler()00

When maxClientHelloLength is 0, the condition maxClientHelloLength != 0 evaluates to false, so the whole guard short-circuits whatever the handshakeLength value is. The handshakeTimeoutMillis=0 setting also means no timeout is ever scheduled, so nothing reclaims the buffer if the handshake stalls.

This is a textbook case of CWE-770 (Allocation of Resources Without Limits or Throttling). An untrusted network input (the 24-bit handshake length field) is used directly as the allocation size with no effective upper bound.

Attack Flow

  1. The attacker opens a TCP connection to a Netty-based service that terminates TLS using one of the default SNI handler constructors.

  2. The attacker sends a TLS record containing a ClientHello with the 24-bit handshake length field set to 16,777,215 (0xFFFFFF), the maximum value. Only the TLS record header and the length field need to be present. The actual ClientHello payload can be minimal or absent, so the whole message can be as small as nine bytes.

  3. The decode() method reads the handshake length. The guard at line 140 evaluates 16777215 > 0 && 0 != 0, which reduces to true && false, or false. The guard does not trigger.

  4. The code proceeds to line 161 and calls ctx.alloc().buffer(16777215). Because 16 MiB exceeds Netty's default pooled chunk size, this becomes an unpooled (direct memory) allocation, performed immediately on the hot path.

  5. The handler holds on to the allocated buffer, waiting for the rest of the ClientHello data, which will never arrive. Because handshakeTimeoutMillis is 0, no timeout is scheduled to clean up the allocation.

  6. The attacker repeats this across many connections. Each connection consumes approximately 16 MiB of direct memory, an amplification factor of approximately 1.86 million to one (9 bytes in, 16 MiB allocated).

  7. The accumulated memory pressure leads to OutOfMemoryError, container OOM kills, or severe performance degradation, and the service goes down.

The CVSS v3.1 vector AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H (score 7.5) reflects network exploitability, low complexity, no authentication requirement, and high availability impact.

Why This Is Subtle

The first bytes of the attack look like a legitimate TLS ClientHello. Standard network monitoring tools that inspect TLS traffic at the protocol level may not flag the oversized length field as anomalous, since the TLS specification permits large handshake messages. The TLS protocol itself is not at fault. The bug is in Netty, which allocates the buffer before it validates the full message.

The memory consumed is also off-heap direct memory, not JVM heap memory, so standard JVM heap monitoring and garbage collection metrics will not show the growing pressure. Operators need to monitor direct memory usage specifically (e.g., via java.nio.BufferPoolMXBean) to detect this condition.

Affected Systems and Versions

The vulnerability affects the io.netty:netty-handler package in two version branches:

BranchVulnerable VersionsFixed Version
4.1.xAll versions prior to 4.1.135.Final4.1.135.Final
4.2.x4.2.0.Final through 4.2.14.Final4.2.15.Final

The vulnerable configuration requires one of the default SNI handler constructors: SniHandler(Mapping), SniHandler(AsyncMapping), or AbstractSniHandler(). These constructors pass maxClientHelloLength=0, which disables the length guard. Custom configurations that explicitly set a nonzero maxClientHelloLength may be partially protected, though upgrading is still the recommended action.

Netty often arrives as a transitive dependency, so organizations should audit their dependency trees with tools like Maven's dependency:tree or Gradle's dependencies task to find every path that resolves to a vulnerable version of io.netty:netty-handler.

Vendor Security History

Netty has had a concentrated run of security disclosures. The Cybersecurity Help security bulletin SB2026060813 cataloged 22 vulnerabilities published around the same time as CVE-2026-45416. Notable recent CVEs include:

CVETypeSeverity
CVE-2026-45416SNI handler memory pre-allocation DoSHigh (7.5)
CVE-2026-44248MQTT Decoder DoSReported
CVE-2026-42578DoS in netty-handlerReported
CVE-2026-33871DoS vulnerabilityReported
CVE-2025-25193DoS (up to 4.1.118.Final)Reported
GHSA-389x-839f-4rhxDoS via environment file on WindowsReported

The common thread across these disclosures is denial of service in protocol decoders, where Netty reads untrusted length fields from network input and allocates resources without effective bounds. Organizations that depend on Netty should plan to patch multiple CVEs in one batch rather than one at a time, and should consider auditing other resource allocation paths in the framework for the same flaw.

The Netty project publishes security advisories through the GitHub Security Advisory system and follows responsible disclosure practices. Maintainer chrisvest published the CVE-2026-45416 advisory on June 5, 2026.

References

Detect & fix
what others miss

Works with
  • GitHub
  • GitLab
  • Bitbucket
  • Azure DevOps Services
  • Gerrit
  • CVS
  • Jira
  • Linear
  • Slack
  • Security Compass
Explore integrations
Security magnifying glass visualization