CVE-2026-111551
Patch Available.
This Vulnerability has been fixed in the Never-Ending Support (NES) version offered by HeroDevs.
Overview
Apache Kafka is an open-source distributed event streaming platform used for high-throughput, fault-tolerant data pipelines and stream processing. It stores records in partitioned, replicated, append-only logs on a cluster of brokers, and exposes producer, consumer, admin, Streams, and Connect APIs for publishing, subscribing to, and processing those records. The Java client and server components are published as Maven artifacts under org.apache.kafka.
A denial-of-service vulnerability (CVE-2026-111551) has been identified in Apache Kafka, which allows attackers to crash a consumer or Kafka Streams thread with an OutOfMemoryError by supplying crafted serialized data. Several deserialization paths read a size or count field from the input and use it directly to allocate an array, collection, or byte buffer, so a small crafted input that declares a very large size can force a multi-gigabyte allocation.
Per OWASP: The Denial of Service (DoS) attack is focused on making a resource (site, application, server) unavailable for the purpose it was designed. There are many ways to make a service unavailable for legitimate users by manipulating network packets, programming, logical, or resources handling vulnerabilities, among others.
This issue affects multiple versions of Apache Kafka, in both the Kafka Streams and client deserializers.
Details
Module Info
- Product: Apache Kafka
- Affected packages: org.apache.kafka:kafka-clients, org.apache.kafka:kafka-streams
- Affected versions:
- org.apache.kafka:kafka-clients: >=0.10.0.0 <=4.1.2, >=4.2.0 <=4.2.1, >=4.3.0 <=4.3.1
- org.apache.kafka:kafka-streams: >=0.10.0.0 <=4.1.2, >=4.2.0 <=4.2.1, >=4.3.0 <=4.3.1
- GitHub repository: https://github.com/apache/kafka
- Published packages: https://central.sonatype.com/artifact/org.apache.kafka/kafka-clients
- Package manager: Maven
- Fixed in:
- OSS Apache Kafka 4.2.2, 4.3.2, 4.4.0
- NES for Apache Kafka
Vulnerability Info
This High-severity vulnerability is found in the kafka-clients and kafka-streams packages in multiple versions of Apache Kafka. Several deserialization paths read a length or count field from attacker-controllable input and allocate a collection, array, or byte buffer of that size without checking it against the number of bytes actually available. Because the allocation is driven by the declared size rather than by the input's length, the broker-side record size limit (max.message.bytes) does not bound it, and a small message can declare a size that triggers a multi-gigabyte allocation and an OutOfMemoryError.
In the clients library, ListDeserializer (used by ListSerde) reads the element count and each element length straight off the stream and uses them to size the backing list and per-element buffers:
final int size = dis.readInt();
List<Inner> deserializedList = createListInstance(size);
for (int i = 0; i < size; i++) {
int entrySize = serStrategy == SerializationStrategy.CONSTANT_SIZE ? primitiveSize : dis.readInt();
if (entrySize == ListSerde.NULL_ENTRY_VALUE || (nullIndexList != null && nullIndexList.contains(i))) {
deserializedList.add(null);
continue;
}
byte[] payload = new byte[entrySize];The same pattern appears in the Kafka Streams internal deserializers. ProcessorRecordContext reads a header count and, unless it is the legacy -1 marker, allocates an array of that length:
final int headerCount = buffer.getInt();
final Headers headers;
if (headerCount == -1) { // keep for backward compatibilty
headers = new RecordHeaders();
} else {
final Header[] headerArr = new Header[headerCount];CombinedKeySchema reads a foreign-key length and allocates a byte array of that size, where a negative value can also raise a NegativeArraySizeException:
final int foreignKeyLength = dataBuffer.getInt();
final byte[] foreignKeyRaw = new byte[foreignKeyLength];AssignmentInfo decodes group-assignment data by reading counts and dictionary sizes and pre-sizing the backing collections from them:
final int count = in.readInt();
assignmentInfo.activeTasks = new ArrayList<>(count);A consumer or Streams thread reaches these paths when it reads a crafted record from a topic consumed with ListSerde, from a Streams application's internal changelog or repartition topics, from crafted offset metadata committed to its consumer group, or from assignment data returned by a crafted group member elected leader. Because the crafted record stays in its topic, the error can recur after a restart.
Mitigation
Only recent versions of Apache Kafka are community-supported. Older lines are End-of-Life and will not receive public updates to address this issue. The Apache Kafka project does bugfix releases only for the last three minor releases; see the project's time-based release plan.
Users of the affected components should apply one of the following mitigations:
- Upgrade Apache Kafka to a currently supported release that contains the fix, such as 4.2.2.
- Leverage a commercial support partner like HeroDevs for post-EOL security support.
Credits
- Peyton Kennedy (finder)
- Bartlomiej Dmitruk (finder)
- Mike Read (finder)