Bug 2536939 (CVE-2026-93560)

Summary: CVE-2026-93560 io.netty/netty-codec-stomp: Netty: STOMP codec content-length long-to-int truncation causes infinite decode loop DoS
Product: [Other] Security Response Reporter: OSIDB Bzimport <bzimport>
Component: vulnerabilityAssignee: Product Security <prodsec-ir-bot>
Status: NEW --- QA Contact:
Severity: high Docs Contact:
Priority: high    
Version: unspecifiedCC: anujha, aschwart, asoldano, aszczucz, bbaranow, bmaxwell, boliveir, bstansbe, dlofthou, drichtar, fmariani, gmalinko, istudens, ivassile, iweiss, janstey, jwon, mcarlett, mosmerov, mposolda, msvehla, nwallace, pberan, pdelbell, pesilva, pjindal, pmackay, rmartinc, rstancel, rstepani, ssilvert, sthorger, tcunning, thjenkin, vdosoudi, vmuzikar, yfang
Target Milestone: ---Keywords: Security
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: ---
Doc Text:
A flaw was found in the Netty STOMP codec. A remote attacker could send a specially crafted STOMP frame with a content-length header exceeding the maximum integer value. This integer truncation vulnerability could lead to an infinite decode loop, causing a Denial of Service (DoS) by exhausting memory and CPU resources.
Story Points: ---
Clone Of: Environment:
Last Closed: Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description OSIDB Bzimport 2026-09-18 09:45:05 UTC
STOMP codec content-length long-to-int truncation causes infinite decode loop DoS

A public GitHub Security Advisory (GHSA-hmf3-49g9-g7qq) describes the following issue:

## Vulnerability

In `StompSubframeDecoder.java`, the `contentLength` field is `long` (line 80) but `alreadyReadChunkSize` is `int` (line 78). At line 149, the remaining length is computed with a truncating cast:

```java
private long contentLength = -1;       // long
private int alreadyReadChunkSize;      // int

// Line 149
int remainingLength = (int) (contentLength - alreadyReadChunkSize);
```

At line 233-238, `getContentLength()` accepts any non-negative long with no upper bound:

```java
private static long getContentLength(StompHeaders headers) {
    long contentLength = headers.getLong(StompHeaders.CONTENT_LENGTH, 0L);
    if (contentLength < 0) {
        throw new DecoderException(...);
    }
    return contentLength;  // No upper bound! Can be Long.MAX_VALUE
}
```

## Attack Scenario

A STOMP frame with `content-length: 2147483648` (Integer.MAX_VALUE + 1):

1. `contentLength = 2147483648L`, `alreadyReadChunkSize = 0`
2. `remainingLength = (int)(2147483648L) = -2147483648` (int truncation wraps negative)
3. `toRead > remainingLength` → any positive > -2147483648 → true → toRead not capped
4. `(alreadyReadChunkSize += toRead) >= contentLength` → small int vs huge long → false (never terminates)
5. `alreadyReadChunkSize` is int → eventually overflows, making termination impossible
6. Decoder produces chunks infinitely

## Impact

- **Infinite loop DoS**: Decoder never finishes the frame, blocking all subsequent STOMP frames
- **Memory exhaustion**: Chunk objects accumulate unbounded
- **CPU exhaustion**: Endless decode iterations
- **Default configuration**: No configuration changes needed

## Affected Code

- `codec-stomp/.../StompSubframeDecoder.java:78,80,149,233-238`

## Suggested Fix

Add upper bound in `getContentLength()`:
```java
if (contentLength > Integer.MAX_VALUE) {
    throw new DecoderException("content-length exceeds maximum");
}
```
Or change `alreadyReadChunkSize` to `long`.

Affected:
- maven:io.netty:netty-codec-stomp affected >= 4.2.0.Final, <= 4.2.17.Final; fixed unknown
- maven:io.netty:netty-codec-stomp affected <= 4.1.137.Final; fixed unknown

Fixed versions: see advisory

Advisory: https://github.com/netty/netty/security/advisories/GHSA-hmf3-49g9-g7qq