🔴 2026-10-05 更新(下面结论表里的版本号已改)
10-01 FasterXML 又在
jackson-core发了 2 条 high(CVE-2026-89425、CVE-2026-89407,都是拒绝服务)。只升到本文原来写的 2.18.10 / 2.21.6 / 2.22.2 / 3.1.6 / 3.2.2 已经不够,现在要 2.18.11 / 2.21.7 / 2.22.3 / 3.1.7 / 3.2.3。jackson-databind09-30 也新发了 2 条,到位版本同号。这两条新的发布当天就进了 GitHub 全局漏洞库,Dependabot 会报 —— 和本文的主角不一样。
本文的核心结论没变:
CVE-2026-68498截至 2026-10-05 在全局库按编号查仍是 404(仓库发布已 23 天),Dependabot 仍然不报。
先说结论
如果你的项目里有 com.fasterxml.jackson.core:jackson-core(几乎一定有,jackson-databind 会把它带进来),
而版本落在下面任一区间,你中了一条 high,而 Dependabot 不会告诉你:
| 坐标 | 68498 的受影响区间 | 修掉 68498 的版本 | 现在该升到(10-05) |
|---|---|---|---|
com.fasterxml.jackson.core:jackson-core | >= 2.16.0, <= 2.18.9 | 2.18.10 | 2.18.11 |
| 同上 | >= 2.19.0, <= 2.21.5 | 2.21.6 | 2.21.7 |
| 同上 | >= 2.22.0, <= 2.22.1 | 2.22.2 | 2.22.3 |
tools.jackson.core:jackson-core(Jackson 3) | >= 3.0.0, <= 3.1.5 | 3.1.6 | 3.1.7 |
| 同上 | >= 3.2.0, <= 3.2.1 | 3.2.2 | 3.2.3 |
最后一列比第三列高一格,是因为 10-01 新发的那 2 条(见文首)。
编号是 CVE-2026-68498(GHSA-649p-m576-vr99,high 7.5),FasterXML 2026-09-12 发在自己仓库的 Security 页上。
截至 2026-10-05,GitHub 全局漏洞库按这个编号查仍是 404 —— Dependabot 和 OSV 读的就是那个库。
有一件事要先说清楚:这不是「Jackson 又出了个 RCE」。它是内存耗尽型 DoS, 而且只有从字符输入解析时才中。下面每一节都会把边界写死。
为什么升了 databind 还会中
jackson-databind 和 jackson-core 是两个独立发版的坐标,只是通常一起升。
jackson-core 在 Maven 生态里的被依赖数甚至比 databind 还高 —— 很多项目会直接声明它,
也有不少项目用 dependencyManagement 单独钉住过它的版本。
于是有一种很常见的状态:jackson-databind 已经是 2.21.6,jackson-core 还停在 2.21.5。
你的 SCA 面板全绿,因为它按 jackson-databind 查,而这条洞不挂在那个坐标上。
这和「同一个 Netty 版本号、不同模块的『修完』版本不一样」是同一类问题: 你脑子里的单位是「Jackson」,而 advisory 的单位是「坐标」。
洞本身:一道校验跑得太晚
StreamReadConstraints 里有两个独立的上限:
maxStringLength 默认 100,000,000 —— 管字符串「值」
maxNameLength 默认 50,000 —— 管对象属性「名」
差了约 2000 倍。maxNameLength 的存在意义就是:哪怕你允许很大的字符串值,
也别让一个属性名吃掉那么多内存。
字节输入路径做对了。UTF8StreamJsonParser 扫属性名时,每次扩缓冲都会调
ParserBase._growNameDecodeBuffer(),里面就有一次 validateNameLength() ——
所以超长的名字在分配了几十 KB 之后就被拒掉了。
字符输入路径没有。ReaderBasedJsonParser._parseName2() 把名字累积进 TextBuffer,
而 TextBuffer.finishCurrentSegment() 调的是 validateStringLength() ——
字符串上限,不是名字上限。真正的 validateNameLength() 要等整个名字扫到闭引号、
进了 CharsToNameCanonicalizer.findSymbol() 才跑。
那时候内存已经分配完了。
官方公告里贴了实测输出,两条路径的差别一眼可见:
[bytes] Name length (65536) exceeds the maximum allowed (50000, ...)
[reader] Name length (5000000) exceeds the maximum allowed (50000, ...)
字节路径在缓冲涨到 65,536 时就抛了;字符路径把整个 5,000,000 字符的名字读完了才抛 ——
异常信息里那个数字本身就是证据。不设人为上限的话,这条路径能一直缓冲到 maxStringLength,
也就是约 1 亿字符(约 200MB),而且 maxDocumentLength 默认是关的(-1),没有别的东西兜底。
一个请求几百 MB,几个并发就够把堆打爆。不需要任何误配置。
你到底中不中:一句话判据
- 从
String/Reader/char[]解析不可信 JSON → 中 - 从
byte[]/InputStream解析,或用非阻塞(async)解析器 → 不中
坏消息是,第一种恰好是最常见的写法之一 —— HTTP 请求体先读成 String 再
objectMapper.readValue(body, X.class),这行代码到处都是。
我自己的工具也漏了这一维
9 月 14 日我发过一个 jackson-check,扫 jar 判「你中哪几条、哪几条 Dependabot 看不见」。
它的判定表整张只有一个 artifactId:jackson-databind。
所以它对 jackson-core 的公告(当时 7 条,10-01 起 9 条)是系统性失明的,而且不会报任何错 ——
它只是安静地跳过所有 jackson-core-*.jar。「没扫到」和「你很安全」在报告里长得一模一样。
这一版(v0.3.0)把判定粒度从「advisory × groupId × 区间」改成
「advisory × groupId × artifactId × 区间」,判定、求交集、「未扫到这个坐标」
全部以完整坐标为键。顺带把 jackson-core 那 7 条公告都收了进来。
10-05 的 v0.4.0 又并入了 09-30 / 10-01 新发的 4 条(databind 2 条 + core 2 条),两个坐标共 26 条。
⚠️ 上一版给 jackson-databind 的答案(2.18.10 / 2.21.6 / 2.22.2 / 3.1.6 / 3.2.2)在当时没有错,
错的是维度 —— 它只回答了一个坐标的问题。(10-05:那组答案现在也被新公告顶高了一格,见文首。)
工具
java -jar jackson-check.jar ./target ./src
零依赖单 jar,不联网,判定表内置。扫普通 jar、Spring Boot fat jar(BOOT-INF/lib/)、
传统 WAR(WEB-INF/lib/),坐标从 META-INF/maven/**/pom.properties 读,读不到才退回 MANIFEST 和文件名。
下面是 10-05 用 v0.4.0 扫的真实输出 —— databind 已经升到 2.21.6,core 还停在 2.21.5(本次没传源码目录):
【一】扫到的 jackson 构件(databind / core)
com.fasterxml.jackson.core:jackson-core 2.21.5 (版本来源:pom.properties)
com.fasterxml.jackson.core:jackson-databind 2.21.6 (版本来源:pom.properties)
【三】判定结果
你的版本落在受影响区间内的:5 条
其中 Dependabot 会报的:4 条(GitHub 全局漏洞库已收录)
🔴 其中 Dependabot 看不见的:1 条(GitHub 全局漏洞库还没收录,按 GHSA 号查 404)
CVE-2026-68498 high 7.5 Delayed maxNameLength enforcement for char-backed input ...
🔴 GitHub 全局漏洞库还没收录这条 —— Dependabot 不会报
坐标 com.fasterxml.jackson.core:jackson-core · 你的版本 2.21.5 · 受影响 2.19.0 <= 版本 <= 2.21.5
条件 仅当从 String / Reader / char[] 解析不可信 JSON;从 byte[] / InputStream 解析不受影响
【四】该升到哪个版本(逐条求交集,不是照抄某一条 advisory)
com.fasterxml.jackson.core:jackson-databind
现在 2.21.6 → 升到 2.21.7
盖住 2 条;把目标顶到这么高的是 CVE-2026-91776
com.fasterxml.jackson.core:jackson-core
现在 2.21.5 → 升到 2.21.7
盖住 3 条;把目标顶到这么高的是 CVE-2026-89425
同一对 jar,09-21 用 v0.3.0 扫是「1 条,core 升到 2.21.6」。多出来的 4 条就是 09-30 / 10-01 新发的, Dependabot 都会报;看不见的仍然只有 68498 这 1 条。
退出码:0 版本没中 · 2 版本中但源码里没找到触发条件 · 3 触发条件也成立 · 4 有文件读不动。
最后那个 4 值得单说。ZipInputStream 遇到不是 zip 的文件不抛异常,只给零条目 ——
扫描会正常走完、输出「没找到」、退出码 0。「我读不动它」于是变成了「你是安全的」。
所以这里单独占一个退出码。
🔴 工具做不到的那一半
它判得了 jar 版本,判不了你的调用方式。
readValue(body, X.class) 里的 body 是 String 还是 byte[],文本扫描看不出来 ——
那是个变量。工具只认得出显式写法(比如 new StringReader(...)),
所以报告里那句「未在你的源码里找到触发条件」后面永远跟着一句 「🔴 这不等于安全」。
真要确认,只有两条路:看一眼你那几处反序列化入口的实参类型;或者直接升版本。 升版本更便宜。
这篇能证明什么、不能证明什么
能:CVE-2026-68498 在 FasterXML 仓库公开可查;截至 10-05 全局库按编号查仍 404;
修掉它的五个版本、以及现在该升到的五个版本(2.18.11 / 2.21.7 / 2.22.3 / 3.1.7 / 3.2.3)在 Maven Central 上都拿得到;字节码实测 validateNameLength 的调用
只在修复版的 ReaderBasedJsonParser 里有、中招版里没有(2.18.9→2.18.10、
2.21.5→2.21.6、3.1.5→3.1.6 三条线都复现了)。
不能:不能证明你一定会被打 —— 得看你是不是从字符输入解析不可信 JSON; 不是说 Dependabot 对 jackson-core 全瞎 —— 截至 10-05 的 9 条里其余 8 条都已收录、正常告警,只有这一条没有; 也不是说 GitHub 永远不会收录它,AsyncHttpClient 那批就是晚了 39 天才收的。
工具、判定表生成脚本、发文前复核脚本都在仓库里(Apache-2.0): github.com/xiaoqiMikko… —— 可直接下载的 jar 在 Release v0.4.0(v0.3.0 印的升级目标已不够,别再用)。