先说结论
如果你的项目里有 com.fasterxml.jackson.core:jackson-core(几乎一定有,jackson-databind 会把它带进来), 而版本落在下面任一区间,你中了一条 high,而 Dependabot 不会告诉你:
| 坐标 | 受影响 | 升到 |
|---|---|---|
com.fasterxml.jackson.core:jackson-core |
>= 2.16.0, <= 2.18.9 |
2.18.10 |
| 同上 | >= 2.19.0, <= 2.21.5 |
2.21.6 |
| 同上 | >= 2.22.0, <= 2.22.1 |
2.22.2 |
tools.jackson.core:jackson-core(Jackson 3) |
>= 3.0.0, <= 3.1.5 |
3.1.6 |
| 同上 | >= 3.2.0, <= 3.2.1 |
3.2.2 |
编号是 CVE-2026-68498(GHSA-649p-m576-vr99,high 7.5),FasterXML 2026-09-12 发在自己仓库的 Security 页上。 截至 2026-09-21 ,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() 才跑。
那时候内存已经分配完了。
官方公告里贴了实测输出,两条路径的差别一眼可见:
scss
[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 条公告是系统性失明的 ,而且不会报任何错 ------ 它只是安静地跳过所有 jackson-core-*.jar。「没扫到」和「你很安全」在报告里长得一模一样。
这一版(v0.3.0)把判定粒度从「advisory × groupId × 区间」改成 「advisory × groupId × artifactId × 区间」,判定、求交集、「未扫到这个坐标」 全部以完整坐标为键。顺带把 jackson-core 那 7 条公告都收了进来。
⚠️ 上一版给 jackson-databind 的答案(2.18.10 / 2.21.6 / 2.22.2 / 3.1.6 / 3.2.2)没有错, 错的是维度 ------ 它只回答了一个坐标的问题。
工具
bash
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 和文件名。
下面是 09-21 的真实输出 ------ databind 已经升到 2.21.6,core 还停在 2.21.5:
arduino
【一】扫到的 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)
【三】判定结果
你的版本落在受影响区间内的:1 条
其中 Dependabot 会报的:0 条(GitHub 全局漏洞库已收录)
🔴 其中 Dependabot 看不见的:1 条(GitHub 全局漏洞库还没收录,按 GHSA 号查 404)
CVE-2026-68498 high 7.5 Delayed maxNameLength enforcement for char-backed input ...
坐标 com.fasterxml.jackson.core:jackson-core · 你的版本 2.21.5 · 受影响 2.19.0 <= 版本 <= 2.21.5
条件 仅当从 String / Reader / char[] 解析不可信 JSON;从 byte[] / InputStream 解析不受影响
未找到 CharInputParse
说明 未在你的源码里找到触发条件(CharInputParse) ------ 🔴 这不等于安全
【四】该升到哪个版本(逐条求交集,不是照抄某一条 advisory)
com.fasterxml.jackson.core:jackson-core
现在 2.21.5 → 升到 2.21.6
盖住 1 条;把目标顶到这么高的是 CVE-2026-68498
退出码:0 版本没中 · 2 版本中但源码里没找到触发条件 · 3 触发条件也成立 · 4 有文件读不动。
最后那个 4 值得单说。ZipInputStream 遇到不是 zip 的文件不抛异常,只给零条目 ------ 扫描会正常走完、输出「没找到」、退出码 0。「我读不动它」于是变成了「你是安全的」。 所以这里单独占一个退出码。
🔴 工具做不到的那一半
它判得了 jar 版本,判不了你的调用方式。
readValue(body, X.class) 里的 body 是 String 还是 byte[],文本扫描看不出来 ------ 那是个变量。工具只认得出显式写法(比如 new StringReader(...)), 所以报告里那句「未在你的源码里找到触发条件」后面永远跟着一句 「🔴 这不等于安全」。
真要确认,只有两条路:看一眼你那几处反序列化入口的实参类型;或者直接升版本。 升版本更便宜。
这篇能证明什么、不能证明什么
能 :CVE-2026-68498 在 FasterXML 仓库公开可查;截至 09-21 全局库按编号查仍 404; 五个修复版在 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 全瞎 ------ 那 7 条里其余 6 条都已收录、正常告警,只有这一条没有; 也不是说 GitHub 永远不会收录它,AsyncHttpClient 那批就是晚了 39 天才收的。
工具、判定表生成脚本、发文前复核脚本都在仓库里(Apache-2.0): github.com/xiaoqiMikko... ------ 可直接下载的 jar 在 Release v0.3.0。