七条 advisory 各给了一个修复版,而一次修完的那个数字一条都没写

一、先给结论:七条的修复版,和那个没人写的交集

io.netty:netty-codec-http2 在 2025-08 至 2026-07 之间累计 7 条 CVE。 每一条的 GitHub advisory 都规规矩矩给了 first_patched_version ------ 问题是七个都不一样:

CVE 评级 4.1 线修复版 4.2 线修复版
CVE-2025-55163(MadeYouReset) high 7.5 4.1.124.Final 4.2.4.Final
CVE-2026-33871(CONTINUATION 洪水) high 4.1.132.Final 4.2.11.Final
CVE-2026-47244(MAX_CONCURRENT_STREAMS 不生效) medium 5.3 4.1.135.Final 4.2.15.Final
CVE-2026-48043(Decompressor 引用计数泄漏) medium 5.3 4.1.135.Final 4.2.15.Final
CVE-2026-50560(Reset 攻击换了个签名) medium 5.3 4.1.135.Final 4.2.15.Final
CVE-2026-56819(解压泄漏 → OOM) high 7.5 4.1.136.Final 4.2.16.Final
CVE-2026-59900(Host 头去重缺失 → 路由绕过) medium 4.1.136.Final 4.2.16.Final

取最大值:

sql 复制代码
4.1 线 → 4.1.136.Final
4.2 线 → 4.2.16.Final

这两个数字不写在任何一条 advisory 上。 它们是七条各自修复版的交集,得自己算。 照着其中任何一条升,都还落在其余几条的受影响区间里 ------ 比如升到 4.1.124 修好了 MadeYouReset, 剩下六条一条没动。

说清楚一件事,免得误会:这七条 Dependabot 都会正常告警 。 它们全是 reviewed、包信息齐全、修复版有值。 告警会来,而且会给你一个版本号 ------ 但那是这一条 的版本号,不是这七条的。

二、为什么你的 pom.xml 里搜不到 netty-codec-http2

这是最容易得出错误结论的地方。如果你用 Spring WebFlux,依赖链是这样的:

lua 复制代码
spring-boot-starter-webflux
  └─ spring-boot-starter-reactor-netty
       └─ reactor-netty-http
            └─ io.netty:netty-codec-http2   ← 在这儿

三个 POM 都在 repo1.maven.org 上,可以逐个点开核。结论是: netty-codec-http2 这个 artifactId 从头到尾不会出现在你自己的 pom.xml 里。

所以:

  • 在源码目录里 grep netty-codec-http2 → 没有 → 不代表你没用它;
  • 想知道实际装的是哪个版本,得看构建产物 :target/*.jar、容器镜像里的 /app、 或者 mvn dependency:tree | grep netty-codec-http2

三、4.1 和 4.2 是两条要分开算的线

七条每一条都同时影响两条线,而两条线的修复版编号完全不同(见第一节的表)。

这里有个容易踩的心理陷阱:4.2 是新线,用它的人容易觉得自己"在新版本上" 。 实际上停在 4.2.15.Final 的人:

  • 已经修好五条;
  • 还中着 CVE-2026-56819CVE-2026-59900 两条,其中前者是 high 7.5。

四、有一个版本掉在官方口径的缝里:4.2.10

CVE-2026-33871 在 4.2 线上的两个字段是这么写的:

sql 复制代码
vulnerable_version_range :  >= 4.2.0.Alpha1, < 4.2.10.Final
first_patched_version    :  4.2.11.Final

4.2.10.Final 掉在中间 ------ 按区间它不受影响(区间是"小于 4.2.10"), 按修复版它又没到(修复版是 4.2.11)。

这不是我的推断,是这条 advisory 上两个字段的原文。我不知道哪个字段是笔误, 所以工具的处理是:把它显式报出来,而不是让它落进默认分支 ------ 因为默认分支是"安全",而一个判不了的情况被判成安全,是最糟的那种错。

如果你正好在 4.2.10.Final 上:直接升过 4.2.11 就行,别在这条上纠结。

五、MadeYouReset 在 Netty 上有自己的编号

2025 年 8 月那批 HTTP/2 重置流放大攻击,公开讨论用的编号是协议级的 CVE-2025-8671 。 Netty 自己的那条是 CVE-2025-55163

拿 8671 去查你的 Netty 版本,查不出结论。 这两个编号不是一回事: 前者说的是协议层面的问题面,后者才是"你的 netty-codec-http2 中不中"。

顺带一提:CVE-2025-55163 的 advisory 还单列了 io.grpc:grpc-netty-shaded(< 1.75.0)。 用 gRPC 的人换个坐标也在里面 ------ 但只有这一条 advisory 列了这个坐标, 另外六条没列。「advisory 没列」不等于「不受影响」,只等于官方没给这个坐标下过结论。

六、怎么自查

手动:

bash 复制代码
# 1) 看构建产物里实际装的版本(不是 pom)
mvn dependency:tree | grep netty-codec-http2

# 2) 或者直接翻 jar
unzip -p target/myapp.jar 'BOOT-INF/lib/netty-codec-http2-*.jar' > /dev/null 2>&1
ls target/*/BOOT-INF/lib/ | grep netty-codec-http2

拿到版本号后,对照第一节的表逐条比。

或者用工具(开源,单 jar,零运行时依赖,完全离线):

bash 复制代码
java -jar netty-http2-check.jar target/                  # 扫构建产物,支持 fat-jar / war 嵌套
java -jar netty-http2-check.jar --version 4.1.100.Final  # 直接判一个版本
java -jar netty-http2-check.jar --table                  # 打印完整规则表

输出长这样:

rust 复制代码
netty-codec-http2 4.1.135.Final
  证据: META-INF/io.netty.versions.properties

中了 2 条:
  CVE-2026-56819   high     CVSS 7.5      解压泄漏 -> OOM
  CVE-2026-59900   medium   官方未给分     Host 头与 :authority 去重缺失 -> 路由绕过

-> 一次修完这几条,升到:4.1.136.Final

仓库:github.com/xiaoqiMikko...

几个刻意的设计:

  • 不扫 pom.xml ------ 理由就是第二节;
  • 判不了就说判不了 ------ 认不出的版本号、没覆盖的版本线(4.0 / 5.0)、读不动的压缩包, 一律报"判不了",绝不报"安全";
  • 规则表是生成的,不是手抄的 ------ tools/gen_rules.py 直接读 GitHub advisory, 五条断言不过就拒绝出表(包括"算出来的交集必须真的是 4.1.136 / 4.2.16")。

七、附:我是怎么确认补丁真的在 4.1.136 里的

只比版本号是不够的 ------ advisory 说修了,得自己看一眼。 于是下了 4.1.1354.1.136 两个 jar 做字节码对比。这里有个坑,值得单独说。

第一次我比的是每个条目的 SHA-256:40 个条目全变了 (其中 35 个是 .class,另外 5 个是 META-INF 里的元数据),连 DefaultHttp2PingFrameAbstractHttp2StreamFrame 这种和本次修复八竿子打不着的类都在里面。

原因很简单:整包重编译 。常量池顺序、时间戳都会变,hash 自然全不一样。 "hash 变了 = 这个类改过"是个会骗人的判据。

换成比 class 的字节大小,噪音从 35 个降到 15 个 ;再用 javap -c 做反编译差分, 才拿到能说话的证据:

CVE 4.1.136 里新增的东西
CVE-2026-56819 DelegatingDecompressorFrameListener$Http2Decompressor 多了 EmbeddedChannel.isOpen() 判断和 new ClosedChannelException ------ 向已关闭的 decompressor 写数据时抛异常,而不是继续吃内存
CVE-2026-59900 HttpConversionUtil$Http2ToHttpHeaderTranslator 多了字段 hostHeaderFound 和错误消息 Conflicting ':authority' and 'host' headers found ------ 开始比对 Host 与 :authority 是否一致

第二个坑更隐蔽。我一开始的判据是"136 的那个类里出现了 HOST 这个符号", 结果 135 里也有 (HttpHeaderNames.HOST 本来就在常量池里)。 换成那句只在 136 出现的错误消息,判据才立得住。

教训是通用的:验"新版本有某个东西",必须同时验"旧版本没有"。 只验一半,和没验长得一模一样。

相关推荐
vHelios1 小时前
【电商项目】短信测试遇到的问题与解决方案:InaccessibleObjectException报错、单元测试通过但未接收到验证码
java·微服务
气泡水好喝1 小时前
Java魔法探秘:从Java代码到CPU指令,一个方法调用的完整生命周期
java
气泡水好喝1 小时前
读《阿里巴巴Java开发手册》五年,这7条规约救了我太多次
java
凯哥Java1 小时前
System.setProperty 的正确姿势:Spring Boot 启动类里的“缺省值“魔法
java·spring boot·后端
lhldsg1 小时前
智慧场馆解决方案小程序系统:从架构设计到落地实践
java·小程序·需求分析
hfywmsj2 小时前
广州餐饮铺位招租的选址架构:流量入口与成本函数分析
java·大数据·jvm·广州餐饮铺位招租
爪哇岛国人2 小时前
原来我一直理解错了:实现接口真的必须实现所有方法吗?
java
万年咸鱼2 小时前
Java BufferedOutputStream 详解:原理、用法与性能优化
java·开发语言·性能优化
万年咸鱼2 小时前
Java BufferedInputStream 详解:原理、用法与实战
java·开发语言·python