一条你修不掉的告警
依赖扫描报出来:org.eclipse.jetty:jetty-http,CVE-2026-2332,high。你照例去查官方安全公告,它给了升级建议。你按那个版本号去 Maven Central 下 —— 404。
这不是你手滑打错版本号。这篇要讲的就是:对 Jetty 的 9.4 / 10 / 11 三条老线,官方公告叫你升的那个修复版本,在公开仓库里根本不存在,而这件事扫描工具不会告诉你。
先把 2026 年这五条摆出来,它们散在四个模块上:
| CVE | 模块 | 严重度 | 一句话 |
|---|---|---|---|
| CVE-2026-2332 | jetty-http | high / CVSS v3 7.4 | ⭐ 主打:chunked 编码里 quoted-string 内的 \r\n 被当成分块头结束 → 请求走私(CWE-444) |
| CVE-2026-5795 | jetty-jaspi | high / v3 7.4 | JASPI 的 ThreadLocal 未清理 → 越权 |
| CVE-2026-6790 | jetty-server | medium / v3 5.3 | HTTP/2·3 的 Host 与 :authority 混淆 |
| CVE-2026-10050 | jetty-security | high / v4 8.7 | Digest 认证的 ISO-8859-1 处理 |
| CVE-2025-11143 | jetty-http | low / v3 3.7 | URI 解析差异 |
注意评级:6790 是 medium、11143 是 low。别被「五条 CVE」这个数字唬住统称高危。 而且五条里真正受影响面站得住的只有主打的 2332 —— 后面会说为什么。
主打这条为什么是真的:走私落在默认解析路径上
CVE-2026-2332 是 “Funky Chunks” 请求走私的一个新变种:Jetty 的 HTTP/1.1 解析器在遇到 chunk 扩展的 quoted-string 里的 \r\n 时,把它当成了分块头的结束,而不是报错。
我担心的是它会不会像有些漏洞那样,要开某个特定功能才触发 —— 那样受影响面就很小。于是用修复 commit 和真 jar 做了构件级核对:
gh api ...compare/jetty-12.0.32...jetty-12.0.33:改动集中在jetty-http/.../HttpParser.java(+346/−156),外加新增测试ChunkSizeExtensionTest。12.1.6→12.1.7 是同款。HttpParser是 Jetty 的 HTTP/1.1 解析主状态机,不是任何可选 handler。HttpParser.class在 9.4.58 / 11.0.26 / 12.0.32 的 jar 里全都在。javap -p HttpParser:_chunkLength/isChunking()/MAX_CHUNK_LENGTH这些成员由parseNext()无条件驱动,没有任何开关。advisory 自带的 PoC 也只是一个普通的POST / HTTP/1.1带Transfer-Encoding: chunked。
结论:这条走私落在 HTTP/1.1 解析主路径上,不需要开任何特定功能,受影响面就是 ServerConnector 本身。
但危害有前提,这里必须说清楚: 请求走私要害的前提是你的 Jetty 前面还有一个前端代理 / 负载均衡,而两者对同一个请求的解读不一致。裸跑一个 Jetty、前面什么都没有,讲不出攻击故事。这也是官方给它 7.4 而不是满分的原因。本文证明的是「这段代码在你的构件里、走的是默认路径」,不是「你一定会被打穿」。
核心:9.4 / 10 / 11 老线的公开修复版不存在
这是本文最硬的一条。
官方安全页 https://jetty.org/security.html 对 CVE-2026-2332 那一行写的是:
修复版:
12.0.33, 12.1.7(9.4.60, 10.0.28, 11.0.29see details for availability)
那句 “see details for availability” 是一个超链接,指向商业支持。也就是说:12 线给了公开版本号,而 9.4 / 10 / 11 老线的版本号被放进了「看详情谈可用性」里。
我把这些版本号逐个拿到 Maven Central 上 HEAD 探测:
| 版本 | Maven Central |
|---|---|
jetty-http 12.0.33(12.0 线修复版) | 200 —— 在 |
jetty-http 12.1.7(12.1 线修复版) | 200 —— 在 |
jetty-http 9.4.60 | 404 |
jetty-http 10.0.28 | 404 |
jetty-http 11.0.29 | 404 |
jetty-http 9.4.58.v20250814(老线最后一个公开版) | 200 —— 在 |
最后一行很关键:老线的最后一个版本仍然在 Central 上,404 的只是那个「修复版」本身 —— 不是整个坐标下架了,是那个补丁版本没往公开仓库发。
而且修复版可得性其实有三种情况,不是非黑即白:
- 有公开修复版:12.0 / 12.1 线,升就是了;
- 官方点名了但 Central 404:9.4/10/11 的 2332、5795、10050 —— 就是 “see details for availability”;
- 官方连版本号都没给:9.4/10/11 的 6790 和 11143,advisory 的
first_patched_version直接是空。
⚠️ 到此为止都是可复现的事实。至于官方为什么这么做,我不替它说 —— 12 线仍在正常更新,这不是「Jetty 不发版了」;而「把补丁藏起来卖钱」是动机推断,一手源没这么写。事实就是:照公告去升老线,你会升到一个公开渠道拿不到的版本号。
被困在老线上的,主要是这几个 Spring Boot 版本
Jetty 在国内是少数派(大多数 Spring Boot 用的是 Tomcat)。但如果你当年选了 spring-boot-starter-jetty,你带进来的默认 Jetty 版本是这样的(从每个 spring-boot-dependencies-<版本>.pom 的 <jetty.version> 实读):
| Spring Boot | 默认 Jetty | 落在哪条线 | 有没有公开修复版 |
|---|---|---|---|
| 2.7.18 | 9.4.53.v20231009 | 9.4 老线 | ❌ 老线,see details |
| 3.0.13 | 11.0.18 | 11 老线 | ❌ 老线,see details |
| 3.1.12 | 11.0.21 | 11 老线 | ❌ 老线,see details |
| 3.2.x – 3.4.x | 12.0.9 – 12.0.15 | 12.0 线 | ✅ 升到 12.0.33+ 即可(公开有) |
也就是说:还在 Boot 2.7 / 3.0 / 3.1 且用 Jetty 的项目,默认落在无公开修复版的老线上;要拿到公开修复版,得跨大版本升到 Boot 3.2+(12 线)—— 那是迁移,不是打补丁。3.2 以上的项目在 12 线内升个小版本就行。
(如果你在 pom 里自己覆盖过 jetty.version,以你覆盖的为准 —— 这也正是工具直接扫构件、不看 Boot 版本号的原因。)
判据为什么不能靠「jar 里有没有某个类」
姊妹项目 tomcat-line-check 的判据是「jar 里有没有某个修复类」,因为 Tomcat 那次修复新增了一个类。
Jetty 这次不行。上面说过,2332 的修复改的是 HttpParser 的方法体,isChunking() 这些成员在修复前后都在,没有新增类可查。所以判据只能是:
你的完整坐标 + 版本线,命中哪几条 CVE;以及官方点名的修复版,在 Maven Central 上到底存不存在。
还有个坑:5795(jaspi)和 10050(security)在 12.x 里模块名会裂开成 jetty-ee10-jaspi / jetty-ee9-security 这种,9.4/10/11 才是光 jetty-jaspi / jetty-security。判定必须按完整坐标,短名一刀切会漏。
一个把这些做完的小工具
jetty-line-check:扫目录 / jar / war / Spring Boot fat jar(读的是实际打进去的构件,不是 pom),读出每个 Jetty 模块的完整坐标和版本,对照判定表给出「命中哪几条 CVE、每条的修复版是公开有 / Central 404 / 官方没给」。
https://github.com/xiaoqiMikko/jetty-line-check
单 jar、零运行时依赖、完全离线、Java 17+。
java -jar jetty-line-check-0.1.0.jar /path/to/jetty # 解压部署的 Jetty(扫 lib/*.jar)
java -jar jetty-line-check-0.1.0.jar app.war # war
java -jar jetty-line-check-0.1.0.jar app.jar # Spring Boot fat jar
java -jar jetty-line-check-0.1.0.jar --table # 只看五条 CVE × 模块 × 版本线的判定表
java -jar jetty-line-check-0.1.0.jar --utf8 ... # Windows 控制台中文乱码时加
判定表不是手抄的:tools/gen_table.py 从五条 advisory 加 Maven Central 真 jar 探测生成,七组断言(阳性对照 / 核心主张 / 老线终版 / 哨兵 / 主打结构 / 裂模块 / 评级)不过就拒绝出表。发文前的 tools/recheck_before_publish.py 会把上面这些主张重跑一遍。
退出码:0 = 每个文件都真读进去了 · 2 = 用法错误 · 4 = 有文件读不动。4 故意不是 0 —— 一个损坏 / 下载不全的 jar,不能在 CI 里安静地变成「没发现问题」。
这篇能证明什么、不能证明什么
- ❌ 不是「扫描工具报不出来」。 五条都是 reviewed 的 advisory,报是报得出来的。本文讲的是报出来之后,叫你升的那个老线版本号在公开仓库里不存在。
- ❌ 不是「Jetty 不发版了」。 12.0 / 12.1 线仍在更新,公开修复版都在 Central 上。
- ❌ 不是「任何 Jetty 应用都会被打穿」。 主打那条是请求走私,危害要前置代理与解析分歧,见上文。
- ❌ 不替官方说动机。 “see details for availability” 是官方页面的原话,到此为止。
- ✅ 是:9.4 / 10 / 11 这三条 EOL 老线,官方点名的多条 CVE 修复版在 Maven Central 上是 404;主打的 CVE-2026-2332 走私落在默认解析路径上,受影响面是 server 本身;工具帮你按实际构件判到「中哪几条、能不能公开升」这一步。
如果你发现哪里错了,欢迎直接开 issue —— 这类文章的价值全在准确性上。
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/P191117/article/details/165121289



