Skip to content

fix(deps): update dependency io.netty:netty-codec-http2 to v4.1.133.final [security]#236

Merged
magisk317 merged 1 commit into
betafrom
renovate/maven-io.netty-netty-codec-http2-vulnerability
May 7, 2026
Merged

fix(deps): update dependency io.netty:netty-codec-http2 to v4.1.133.final [security]#236
magisk317 merged 1 commit into
betafrom
renovate/maven-io.netty-netty-codec-http2-vulnerability

Conversation

@magisk317
Copy link
Copy Markdown
Owner

@magisk317 magisk317 commented May 7, 2026

This PR contains the following updates:

Package Change Age Confidence
io.netty:netty-codec-http2 (source) 4.1.132.Final4.1.133.Final age confidence

Netty: HttpContentDecompressor maxAllocation bypass when Content-Encoding set to br/zstd/snappy leads to decompression bomb DoS

CVE-2026-42587 / GHSA-f6hv-jmp6-3vwv

More information

Details

Summary

HttpContentDecompressor accepts a maxAllocation parameter to limit decompression buffer size and prevent decompression bomb attacks. This limit is correctly enforced for gzip and deflate encodings via ZlibDecoder, but is silently ignored when the content encoding is br (Brotli), zstd, or snappy. An attacker can bypass the configured decompression limit by sending a compressed payload with Content-Encoding: br instead of Content-Encoding: gzip, causing unbounded memory allocation and out-of-memory denial of service.

The same vulnerability exists in DelegatingDecompressorFrameListener for HTTP/2 connections.

Details

HttpContentDecompressor stores the maxAllocation value at construction time (HttpContentDecompressor.java:89) and uses it in newContentDecoder() to create the appropriate decompression handler.

For gzip/deflate, maxAllocation is forwarded to ZlibCodecFactory.newZlibDecoder():

// HttpContentDecompressor.java:101 — maxAllocation IS enforced
.handlers(ZlibCodecFactory.newZlibDecoder(ZlibWrapper.GZIP, maxAllocation))

ZlibDecoder.prepareDecompressBuffer() enforces this as a hard cap by setting the buffer's maxCapacity and throwing DecompressionException when the limit is reached:

// ZlibDecoder.java:68 — hard limit on buffer capacity
return ctx.alloc().heapBuffer(Math.min(preferredSize, maxAllocation), maxAllocation);
// ZlibDecoder.java:80 — throws when exceeded
throw new DecompressionException("Decompression buffer has reached maximum size: " + buffer.maxCapacity());

For brotli, zstd, and snappy, the decoders are created without any size limit:

// HttpContentDecompressor.java:120 — maxAllocation IGNORED
.handlers(new BrotliDecoder())

// HttpContentDecompressor.java:129 — maxAllocation IGNORED
.handlers(new SnappyFrameDecoder())

// HttpContentDecompressor.java:138 — maxAllocation IGNORED
.handlers(new ZstdDecoder())

BrotliDecoder has no maxAllocation parameter at all — there is no way to constrain its output. It streams decompressed data in chunks via fireChannelRead with no total limit.

ZstdDecoder() defaults to a 4MB maximumAllocationSize, but this only constrains individual buffer allocations, not total output. The decode loop (ZstdDecoder.java:100-114) creates new buffers and fires channelRead repeatedly, so total decompressed output is unbounded.

The identical pattern exists in DelegatingDecompressorFrameListener.newContentDecompressor() at lines 188-210 for HTTP/2.

PoC
  1. Configure a Netty HTTP server with decompression bomb protection:
pipeline.addLast(new HttpContentDecompressor(1048576)); // 1MB max
pipeline.addLast(new HttpObjectAggregator(1048576));     // 1MB max
  1. Generate a brotli-compressed bomb (~1KB compressed → 1GB decompressed):
import brotli
bomb = b'\x00' * (1024 * 1024 * 1024)  # 1GB of zeros
compressed = brotli.compress(bomb, quality=11)
with open('bomb.br', 'wb') as f:
    f.write(compressed)

##### compressed size: ~1KB
  1. Send the bomb with gzip encoding (BLOCKED by maxAllocation):
##### This is caught — ZlibDecoder enforces the 1MB limit
curl -X POST http://target:8080/api \
  -H 'Content-Encoding: gzip' \
  --data-binary @​bomb.gz

##### Result: DecompressionException thrown at 1MB
  1. Send the same bomb with brotli encoding (BYPASSES maxAllocation):
##### This bypasses the limit — BrotliDecoder has no maxAllocation
curl -X POST http://target:8080/api \
  -H 'Content-Encoding: br' \
  --data-binary @​bomb.br

##### Result: Full 1GB decompressed into memory → OOM
  1. The same bypass works with Content-Encoding: zstd and Content-Encoding: snappy.
Impact
  • Denial of Service: An attacker can cause out-of-memory conditions on any Netty server that relies on maxAllocation for decompression bomb protection, by simply using a non-gzip content encoding.
  • False sense of security: Developers who explicitly configure maxAllocation to protect against decompression bombs are not actually protected for brotli, zstd, or snappy encodings. The API documentation implies all encodings are covered.
  • Trivial bypass: The attacker only needs to change one HTTP header (Content-Encoding: br instead of Content-Encoding: gzip) to circumvent the protection entirely.
  • Both HTTP/1.1 and HTTP/2: The vulnerability exists in both HttpContentDecompressor (HTTP/1.1) and DelegatingDecompressorFrameListener (HTTP/2).
Recommended Fix

Pass maxAllocation to all decoder constructors. For BrotliDecoder, which currently has no maxAllocation support, add the parameter:

HttpContentDecompressor.java — pass maxAllocation to all decoders:

// Line 120: BrotliDecoder — add maxAllocation support
.handlers(new BrotliDecoder(maxAllocation))

// Line 129: SnappyFrameDecoder — add maxAllocation support
.handlers(new SnappyFrameDecoder(maxAllocation))

// Line 138: ZstdDecoder — forward the configured maxAllocation
.handlers(new ZstdDecoder(maxAllocation))

DelegatingDecompressorFrameListener.java — same fix at lines 188-210.

BrotliDecoder — add maxAllocation parameter with the same semantics as ZlibDecoder.prepareDecompressBuffer(): set buffer maxCapacity and throw DecompressionException when the total decompressed output exceeds the limit.

SnappyFrameDecoder — add maxAllocation parameter with equivalent enforcement.

ZstdDecoder — ensure that when maxAllocation is set, total output across all buffers is bounded (not just per-buffer allocation size).

Severity

  • CVSS Score: 7.5 / 10 (High)
  • Vector String: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

References

This data is provided by OSV and the GitHub Advisory Database (CC-BY 4.0).


Configuration

📅 Schedule: (UTC)

  • Branch creation
    • ""
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Enabled.

Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR has been generated by Mend Renovate.

Summary by Sourcery

Build:

  • 将 Gradle 中的强制依赖约束里的 io.netty:netty-codec-http24.1.132.Final 升级到 4.1.133.Final
Original summary in English

Summary by Sourcery

Build:

  • Bump io.netty:netty-codec-http2 from 4.1.132.Final to 4.1.133.Final in Gradle forced dependency constraints.

@magisk317 magisk317 added dependencies Pull requests that update a dependency file java Pull requests that update java code security labels May 7, 2026
@magisk317 magisk317 merged commit 295842e into beta May 7, 2026
3 of 4 checks passed
@magisk317 magisk317 deleted the renovate/maven-io.netty-netty-codec-http2-vulnerability branch May 7, 2026 08:42
@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented May 7, 2026

审阅者指南(在小型 PR 上折叠显示)

审阅者指南

在 Gradle 构建配置中提升强制 Netty HTTP/2 codec 依赖版本,以引入上游针对 HttpContentDecompressor/DelegatingDecompressorFrameListener 解压炸弹防护的安全修复。

文件级变更

变更 详情 文件
在 Gradle 构建脚本中将强制依赖 io.netty:netty-codec-http2 的版本更新为 4.1.133.Final,以覆盖该安全补丁。
  • 修改顶层 buildscript 的 dependency constraints,将强制的 netty-codec-http2 版本从 4.1.132.Final 改为 4.1.133.Final
  • 修改子项目的 dependency constraints 块,将强制的 netty-codec-http2 版本从 4.1.132.Final 改为 4.1.133.Final
build.gradle.kts

技巧与命令

与 Sourcery 交互

  • 触发新的审阅: 在 pull request 中评论 @sourcery-ai review
  • 继续讨论: 直接回复 Sourcery 的审阅评论。
  • 从审阅评论生成 GitHub issue: 通过回复审阅评论让 Sourcery 从该评论创建一个 issue。你也可以在审阅评论下回复 @sourcery-ai issue 来从中创建 issue。
  • 生成 pull request 标题: 在 pull request 标题中任意位置写上 @sourcery-ai,即可随时生成标题。你也可以在 pull request 中评论 @sourcery-ai title 来(重新)生成标题。
  • 生成 pull request 摘要: 在 pull request 正文中任意位置写上 @sourcery-ai summary,即可在你想要的位置随时生成 PR 摘要。你也可以在 pull request 中评论 @sourcery-ai summary 来(重新)生成摘要。
  • 生成审阅者指南: 在 pull request 中评论 @sourcery-ai guide,可随时(重新)生成审阅者指南。
  • 解决所有 Sourcery 评论: 在 pull request 中评论 @sourcery-ai resolve,以解决所有 Sourcery 评论。如果你已经处理完所有评论且不想再看到它们,这会很有用。
  • 撤销所有 Sourcery 审阅: 在 pull request 中评论 @sourcery-ai dismiss,以撤销所有现有的 Sourcery 审阅。特别适合在你希望从头开始一次新审阅时使用——别忘了再评论 @sourcery-ai review 以触发新的审阅!

自定义你的体验

访问你的 控制面板 来:

  • 启用或禁用审阅功能,例如 Sourcery 生成的 pull request 摘要、审阅者指南等。
  • 更改审阅语言。
  • 添加、删除或编辑自定义审阅说明。
  • 调整其他审阅设置。

获取帮助

Original review guide in English
Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Bumps the forced Netty HTTP/2 codec dependency version in Gradle build configuration to pull in the upstream security fix for decompression bomb protection in HttpContentDecompressor/DelegatingDecompressorFrameListener.

File-Level Changes

Change Details Files
Update forced io.netty:netty-codec-http2 version in Gradle buildscript to 4.1.133.Final for security patch coverage.
  • Change top-level buildscript dependency constraints to force netty-codec-http2 version 4.1.133.Final instead of 4.1.132.Final.
  • Change subprojects dependency constraints block to force netty-codec-http2 version 4.1.133.Final instead of 4.1.132.Final.
build.gradle.kts

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

嗨——我已经审查了你的改动,一切看起来都很棒!


Sourcery 为开源项目提供免费服务——如果你觉得我们的评审有帮助,请考虑分享 ✨
帮我变得更有用!请在每条评论上点击 👍 或 👎,我会根据你的反馈来改进后续评审。
Original comment in English

Hey - I've reviewed your changes and they look great!


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file java Pull requests that update java code security

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant