2026-10-06,Netty 同时放出 4.2.19.Final 与 4.1.139.Final。官博与 GitHub Release 都写成缺陷修复加安全发布;4.2 线列出 16 项安全修复,4.1 线列出 13 项。对依赖扫描习惯按 CVE 编号告警的团队,更关键的一句在正文中间:因 CVE 基础设施压力过大,这批报告发布时一个编号都没拿到,公告会不带 CVE 编号发出,扫描器可能漏报。

本稿只按官博、Release 与 Maven Central 可核验内容写作(核对时间 2026-10-07)。不编 CVE、不编严重级别;本批若尚未挂出对应 GHSA,就标明「尚未挂出」,不把更早周期的 advisory 硬套到本次版本上。

官方列出了什么

两份公告的安全列表格式一致:左侧是 CVE-2026-XXXXX 占位,右侧是问题类型加 io.netty: 模块坐标。把条目数点清楚:4.1.139.Final 共 13 条;4.2.19.Final 在相同 13 条之外多写了 HTTP/3 与两处 io_uring,合计 16 条。

共有部分按官方用词归纳如下(模块名保持原文坐标)。数字单位也按原文:这是「条目数」,不是「CVE 数」,因为编号尚未分配。

HTTP 与走私相关主要落在 netty-codec-http:improper CRLF neutralization(request/response smuggling)、另有一条 request/response smuggling、origin validation error,以及 unbounded resource consumption。也就是说,公告把 CRLF 注入与请求响应走私、源校验错误和 HTTP 侧资源耗尽都点到了同一模块上,但分成了多条独立条目,不要自行合并成「一个洞」或「一个 CVE」。做影响面评估时,可以按模块收敛排查范围,但计数仍应与官方列表对齐:4.1 为 13,4.2 为 16。

协议与路由方面:netty-codec-http2 是 unbounded resource consumption;netty-handler 列出 SNI routing bypass 与 improper access control;netty-handler-ssl-ocsp 是 time-of-check/time-of-use error(TOCTOU)。DNS、XML、以及 codec 基座上的资源耗尽分别写在 netty-codec-dns、netty-codec-xml、netty-codec-base。另外还有 netty-codec-haproxy 的 parser desync,以及 netty-codec-socks 的 input misinterpretation。

4.2.19 多出来的三项只在 4.2 公告与 4.2 Release 里出现:netty-codec-http3 的 unbounded resource consumption;netty-transport-classes-io_uring 的 use-after-free;netty-transport-native-io_uring 的 memory leak。走 HTTP/3 或启用了 io_uring transport 的部署,不能只看 4.1 线的 13 项清单;纯 4.1 用户则不必把这三项当成自己线路上的必选项,但 EOL 时间表仍适用。

原文没有在这两篇发布说明里给出真实 CVE 编号,也没有写 CVSS。阅读时按「模块 + 官方类型描述」对齐即可,不要把占位符 CVE-2026-XXXXX 当成已分配编号。

为什么说「暂无 CVE」是读者增量

官方原句如下(两篇公告措辞一致):

Note that due to overwhelming strain on the CVE infrastructure, we have not gotten a single CVE number assigned to these reports in time for our release. The advisories will be published without.

漏洞已经写进发版说明,只是公共 CVE 编号流程没赶上报发布节奏。发版说明里已经把问题类型和模块写清楚了,只是公共 CVE ID 还空着。实际后果通常是:发版当天(甚至之后一段时间)NVD / 各类 CVE 库里搜不到对应条目;只认 CVE 字段的 SCA、镜像扫描、软件成分清单对账,仍可能显示通过;内部变更单若写成「无 CVE 不给升」,会被流程本身挡住。更稳妥的门禁是版本比较:4.1 线升到 4.1.139.Final,4.2 线升到 4.2.19.Final。本稿用 Maven Central 交叉核对过,io.netty 相关构件已能解析到这两个版本。

安全公告有时晚于版本说明,这是发稿前要默认接受的节奏。本稿核对时(2026-10-07),打开 netty/netty Security Advisories 并检索与 4.2.19 / 4.1.139 相关的公开材料,尚未看到与上述 16/13 项一一对应、并标明 patched versions 为 4.2.19.Final / 4.1.139.Final 的新 GHSA。仓库里能看到的较早 GHSA 属于此前发布周期,修复版本也更早,不能当作本批的编号表,本文也不转抄那些 id,以免读者误以为「本批已经有编号」。后续若挂出 GHSA,应以 advisory 原文中的 GHSA id、影响模块与修复版本为准;在那之前,不要断言「永远没有编号」,也不要凭猜测填 CVE。

对排障同事可以多说一句:若扫描报告仍显示旧版 Netty 的历史 CVE 已修复、却对本次条目沉默,优先核对依赖树里的版本号,而不是等 CVE 库补齐后再动手。

FileUpload.setContentType 与 4.1 EOL

两份公告都单独点出行为变化:以前 FileUpload.setContentType 不校验入参;现在若给定字符串不像合理的 MIME content type,会抛出 IllegalArgumentException(官博拼成 IllegaalArgumentException,Java 标准异常类名是 IllegalArgumentException)。这不是安全列表里的占位 CVE 条目,但是升级后可见的 API 行为变化。multipart 上传、自定义 Content-Type、测试里故意塞奇怪 MIME 的路径,都值得跑一遍;原先「写进去就算了」的代码,升级后可能直接失败。

同一段还写明:Netty 4.1 将于 2027-07-01 End-of-Life。日期来自官博原文(July 1st, 2027)。仍在 4.1 的项目,短期至少应到 4.1.139.Final;中期要规划迁 4.2,否则 EOL 之后连同类安全修复通道都会收窄。

排查命令与升级目标

先确认 classpath 上实际解析到的 io.netty 版本。

Maven:

mvn dependency:tree -Dincludes=io.netty

Gradle(把构件名换成你最关心的那一个,例如 netty-handler):

./gradlew dependencyInsight --dependency io.netty:netty-codec-http --configuration runtimeClasspath

判定规则简单:当前是 4.1.x 且低于 4.1.139.Final,升到 4.1.139.Final;当前是 4.2.x 且低于 4.2.19.Final,升到 4.2.19.Final。不要跨大版本「顺手」从 4.1 跳到 4.2,除非你已经评估过 4.2 的 API 与 transport 差异;安全修复在两条线上是分别发布的。

间接依赖很常见:WebFlux / Reactor Netty、部分 gRPC 与网关栈都会带入 io.netty。只改业务模块里显式声明的版本不够时,要用依赖树把 netty-codec-http、netty-handler、netty-codec-http2 等关键模块的解析结果看全。若树里同时出现 4.1 与 4.2,先查是谁引入了另一条线,再决定对齐策略,避免「升了一半」。

Spring Boot:netty.version 属性与本稿核对到的默认值

Spring Boot 参考文档「Version Properties」写明,覆盖 Netty 管理版本的属性名是 netty.version。属性名可以确认;默认落到哪一个 Netty,则取决于你用的 Boot BOM,不能写死成某一个想象中的 Boot 版本。

本稿从 Maven Central 已发布的 spring-boot-dependencies POM 读取(2026-10-07):

Spring Boot BOM 中 netty.version
3.5.16 4.1.135.Final
4.0.8 4.2.17.Final
4.1.1 4.2.17.Final

对照本次修复版本可以看到:3.5.16 仍停在 4.1.135.Final,低于 4.1.139.Final;4.0.8 / 4.1.1 停在 4.2.17.Final,低于 4.2.19.Final。Boot 发版节奏与 Netty 安全发版并不总是同一天对齐,出现「Boot 稳定版默认 Netty 仍低于本次安全版」是常态,不必等 Boot 小版本再动手。若你的 Boot 版本不在上表,请打开对应 BOM 看 <netty.version>,或直接用 dependency:tree / dependencyInsight 看解析结果,以你项目所用 Boot BOM 为准。

继承 spring-boot-starter-parent 时,Maven 可临时覆盖:

<properties>
  <netty.version>4.1.139.Final</netty.version>
</properties>

4.2 线写成 4.2.19.Final。Gradle 在使用 Spring dependency-management 插件的前提下,设置 ext['netty.version'] 或 extra["netty.version"]。覆盖后务必再跑依赖树,确认 netty-codec-http、netty-handler、netty-codec-http2 等模块版本一致,避免只抬了一个 artifact。

等 Boot 后续小版本把默认 netty.version 抬上来之后,可以去掉覆盖。在此之前,版本属性是官方文档支持的做法。回归重点除了安全相关协议路径外,还有上文的 FileUpload.setContentType;若生产启用了 io_uring 或 HTTP/3,优先对照 4.2.19 的三项额外修复做验证。

参考链接

— 感谢阅读 —

一起交流

分享你的思考,让讨论更进一步。