CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-21452
7.50.02%

CVE-2026-21452: Remote DoS via Allocation-Before-Validation in msgpack-java

Amit Schendel
Amit Schendel
Senior Security Researcher

Feb 28, 2026·6 min read·9 visits

PoC Available

Executive Summary (TL;DR)

MessagePack for Java versions before 0.9.11 contain a denial-of-service vulnerability. Attackers can trigger an immediate JVM crash by sending a tiny packet that declares a massive payload size, causing the library to attempt an impossible memory allocation.

A critical resource exhaustion vulnerability exists in the MessagePack for Java (msgpack-java) library, specifically within its deserialization logic for binary and extended data types. The flaw stems from an uncontrolled memory allocation pattern where the library attempts to allocate heap memory based on a declared length field in the input stream before verifying if sufficient data exists. This allows remote attackers to trigger an `OutOfMemoryError` (OOM) and crash the Java Virtual Machine (JVM) by sending a specially crafted 'MessagePack Bomb'—a payload as small as 6 bytes that declares a 2GB size.

Vulnerability Overview

MessagePack is a binary serialization format designed for efficiency and speed, often used as a replacement for JSON in high-performance microservices and data pipelines. The vulnerability, CVE-2026-21452, impacts the msgpack-java library's handling of large binary data types (BIN32) and extension types (EXT32). These formats include a 4-byte length header indicating the size of the subsequent payload.

The core issue lies in the library's eager allocation strategy. When the deserializer encounters a header declaring a large payload (e.g., 2 GB), it immediately allocates a byte array of that size on the JVM heap. This allocation occurs before the library attempts to read the actual payload bytes from the network stream. Consequently, an attacker does not need to send 2 GB of traffic to consume 2 GB of memory on the target server. They simply need to send the header declaring that size.

This creates an asymmetric denial-of-service condition. A packet smaller than 10 bytes can force the server to allocate gigabytes of memory. If the allocation request exceeds the available heap space, the JVM throws a java.lang.OutOfMemoryError, typically causing the application container or the entire service process to terminate abruptly.

Root Cause Analysis

The vulnerability is a classic instance of CWE-789: Memory Allocation with Excessive Size Value. It resides in the MessageUnpacker class, specifically in the methods responsible for reading payload bodies, such as readPayload(int length). In vulnerable versions, the logic blindly trusts the length integer extracted from the MessagePack header.

The Vulnerable Logic

When unpackValue() or readPayload() is called for a BIN32 or EXT32 type, the code performs the following sequence:

  1. Read Header: Reads the format byte (e.g., 0xC6 for BIN32) and the subsequent 4-byte length integer.
  2. Allocate: Immediately executes new byte[length]. If length is Integer.MAX_VALUE (approx. 2.14 GB), the JVM attempts to find a contiguous block of heap memory of that size.
  3. Read Body: Only after allocation does the code attempt to fill the array from the input stream.

This sequence is flawed because it lacks a "check-then-act" mechanism. It acts (allocates) based on untrusted input before verifying that the input stream actually contains the claimed amount of data. This violates the principle that resources should only be allocated proportional to the data actually received or validated.

The flaw is particularly dangerous because msgpack-java is often used in public-facing APIs and high-throughput data ingestion services where untrusted input is common. The lack of an upper bound check or a stream-availability check makes this trivial to exploit.

Code Analysis

The remediation involves shifting from an eager allocation strategy to a gradual allocation strategy for large payloads. The fix was implemented in commit daa2ea6b2f11f500e22c70a22f689f7a9debdeae.

Vulnerable Code Pattern (Before)

The original implementation optimized for speed by allocating the buffer in one operation. This is efficient for trusted data but catastrophic for untrusted input.

// org.msgpack.core.MessageUnpacker
public byte[] readPayload(int length) throws IOException {
    // DANGER: Unconditional allocation based on untrusted 'length'
    byte[] newArray = new byte[length];
    readPayload(newArray);
    return newArray;
}

Patched Code Pattern (After)

The fix introduces a threshold (GRADUAL_ALLOCATION_THRESHOLD, set to 64 MB). Payloads smaller than this threshold are still allocated eagerly to maintain performance. Payloads larger than the threshold are allocated gradually as data is read from the stream.

// org.msgpack.core.MessageUnpacker
private static final int GRADUAL_ALLOCATION_THRESHOLD = 64 * 1024 * 1024; // 64MB
 
public byte[] readPayload(int length) throws IOException {
    if (length < 0) {
        throw new MessageSizeException("Invalid payload size: " + length, length);
    }
 
    // FIX: If length is massive, use gradual allocation to prevent OOM bombs
    if (length > GRADUAL_ALLOCATION_THRESHOLD) {
        return readPayloadGradually(length);
    }
    
    // Fast path for small payloads
    byte[] newArray = new byte[length];
    readPayload(newArray);
    return newArray;
}
 
private byte[] readPayloadGradually(int length) throws IOException {
    byte[] buffer = new byte[length];
    int totalRead = 0;
    while (totalRead < length) {
        // Read in chunks (e.g., 8KB or available bytes)
        // If EOF is reached before 'length' is met, throw exception
        // preventing the full allocation if data is missing.
        // ... implementation details ...
    }
    return buffer;
}

By reading gradually, the system ensures that memory is only consumed if the attacker actually transmits the data. This neutralizes the "MessagePack Bomb" because sending 2 GB of actual data is a network bandwidth attack, not a protocol logic exploit, and is handled by standard timeouts and rate limits.

Exploitation Methodology

Exploiting CVE-2026-21452 requires sending a malformed MessagePack structure to a vulnerable endpoint. The attack does not require authentication or complex chaining. The attacker simply acts as a client submitting data.

The "MessagePack Bomb"

The payload relies on the BIN32 (Binary 32-bit) format code 0xC6 or EXT32 (Extension 32-bit) format code 0xC9.

  1. Construct Header: The attacker creates a byte sequence starting with 0xC6.
  2. Define Length: The next 4 bytes define the length. The attacker sets this to 0x7F 0xFF 0xFF 0xFF (Maximum signed 32-bit integer, ~2.14 GB).
  3. Final Payload: The total payload is just 5 bytes: C6 7F FF FF FF.

Attack Flow

If the server has a large heap (e.g., 8 GB) and does not crash immediately, the attack still degrades performance significantly. The thread handling the request holds a 2 GB array alive, triggering massive Garbage Collection (GC) pauses. Multiple concurrent requests of this type will quickly exhaust even the largest heaps.

Impact Assessment

The primary impact of this vulnerability is Denial of Service (DoS). The severity is High (CVSS 7.5) because it can be exploited remotely by an unauthenticated attacker with minimal resources.

Operational Impact

  • Service Instability: The OutOfMemoryError is an Error type in Java, not an Exception. It is often unrecoverable at the request level and frequently causes the JVM to terminate or enter a zombie state where it cannot process new requests.
  • Resource Starvation: Even if the process does not crash, the sudden allocation of gigabytes of memory forces the Garbage Collector into a "Stop-the-World" pause, freezing the application for all users.
  • Scaling Failure: In auto-scaling environments (like Kubernetes), this exploit can cause a crash loop. As new pods start up, the attacker can crash them immediately, preventing the service from ever stabilizing.

Scope of Compromise

This vulnerability does not lead to:

  • Remote Code Execution (RCE)
  • Information Disclosure (Memory Leak)
  • Data Corruption (beyond the interrupted transaction)

The scope is strictly limited to availability, but for critical infrastructure or high-availability APIs, the loss of availability is a catastrophic failure mode.

Official Patches

MessagePackMessagePack for Java 0.9.11 Release Notes

Fix Analysis (1)

Technical Appendix

CVSS Score
7.5/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
EPSS Probability
0.02%
Top 94% most exploited

Affected Systems

MessagePack for Java (msgpack-java)Systems using Jackson-dataformat-msgpack (transitive dependency)RPC frameworks utilizing MessagePack serialization

Affected Versions Detail

Product
Affected Versions
Fixed Version
msgpack-java
MessagePack
< 0.9.110.9.11
AttributeDetail
CWE IDCWE-789
CVSS v3.17.5 (High)
Attack VectorNetwork
ImpactAvailability (DoS)
Exploit StatusPoC Available
Fix Version0.9.11

MITRE ATT&CK Mapping

T1499Endpoint Denial of Service
Impact
T1499.003Application Exhaustion Flood
Impact
CWE-789
Memory Allocation with Excessive Size Value

The product allocates memory based on an untrusted size value, but it does not verify that the size is within expected limits or that the data is actually available, allowing an attacker to cause resource exhaustion.

Known Exploits & Detection

GitHubPayloadSizeLimitTest.scala included in the patch demonstrates the OOM condition

Vulnerability Timeline

Vulnerability Published
2026-01-02
Patch Released (v0.9.11)
2026-01-02
Noted in CISA Weekly Bulletin
2026-02-26

References & Sources

  • [1]GHSA-cw39-r4h6-8j3x
  • [2]NVD CVE-2026-21452

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.