一条 CVSS 9.0 的 RCE,advisory 里没写修复版是哪个 —— fastjson 16723 的字段考古

一个字段的差别,决定你的扫描器能不能告诉你升到哪

先看一条命令的输出。CVE-2026-16723 是 fastjson 1.x 上一条 CVSS 9.0 的 RCE:

bash 复制代码
# 注意:git bash 下 gh api 路径不要加前导斜杠
gh api advisories/GHSA-crf3-v9rr-v7hj \
  --jq '[.vulnerabilities[] | {range:.vulnerable_version_range, patched:.first_patched_version}]'
# [{"range":">= 1.2.68, <= 1.2.83","patched":null}]

受影响区间写得清清楚楚,first_patched_versionnull

再看同一条 advisory 在 OSV 侧的机器可读结构:

bash 复制代码
curl -s https://api.osv.dev/v1/vulns/GHSA-crf3-v9rr-v7hj | python -c "
import sys, json
d = json.load(sys.stdin)
print(d['affected'][0]['ranges'])
"
# [{'type': 'ECOSYSTEM', 'events': [{'introduced': '1.2.68'}, {'last_affected': '1.2.83'}]}]

字段名是 last_affected ,不是 fixed

这两个字段不是一回事

  • fixed: X ------ 升到 X 就安全了
  • last_affected: X ------ X 是最后一个中招的,至于该升到哪,没说

差别听起来很细,落到代码里是这样的:

python 复制代码
# 常见的区间判定写法
def hit(ver, intro, fixed):
    if intro and ver < intro:  return False
    if fixed and ver >= fixed: return False
    return True                      # ← fixed 是 None 时,永远走到这里

这段代码对 CVE-2026-16723 会把 1.2.84 判成中招 ------ 因为它只读 fixed, 而这条 advisory 的上界挂在 last_affected 上。

🔧 这不是我编的反例,是我自己的复核脚本。 写这篇文章之前我跑发文前复核,断言「1.2.84 不中 16723」当场 FAIL 。 查下去才发现字段读漏了。数据里答案是有的,只是不在我以为的那个字段上。

顺带,这条 advisory 的 versions 字段逐个列举了 21 个受影响版本 ,最高就是 1.2.83, 1.2.84 不在里面。判断依据是充分的,只是不在 fixed 那一栏。

NVD 侧是另一种缺法

bash 复制代码
curl -s "https://services.nvd.nist.gov/rest/json/cves/2.0?cveId=CVE-2026-16723" | python -c "
import sys, json
c = json.load(sys.stdin)['vulnerabilities'][0]['cve']
print(c['vulnStatus'], [m['cvssData']['baseScore'] for m in c['metrics']['cvssMetricV31']])
"
# Deferred [9.0]

有 9.0 的评分,没有 CPE 版本区间。 依赖 NVD 做版本匹配的工具,在这条上匹配不到东西。

⚠️ Deferred 是 NVD 近年积压的通用状态,不是针对这条 CVE ,我也只读到这一次 ------ 这里只陈述现象,不做因果推断。

佐证:把 fastjson 1.x 四条 advisory 摆在一条版本轴上

CVE 严重度 受影响区间 修复版
CVE-2017-18349 CRITICAL <= 1.2.24 1.2.31
CVE-2025-70974 CRITICAL < 1.2.48 1.2.48
CVE-2022-25845 HIGH 8.1 >= 1.2.25, < 1.2.83 1.2.83
CVE-2026-16723 CRITICAL 9.0 >= 1.2.68, <= 1.2.83 1.2.84(advisory 里没写)

⭐ 注意中间那两行:CVE-2022-25845 的修复版 1.2.83,正好是 CVE-2026-16723 区间的上界。

为修 2022 那条升到 1.2.83 的人,一脚踩进 2026 这条里。 同时躲开两条的只有 1.2.84

1.2.84 这个答案,恰恰是 first_patched_version 那一栏没写的那个

边界

  • 这四条里只有 16723 一条first_patched_version 是空的, 另外三条都有正常的 fixed,扫描器对它们工作正常 ------ 别读成「fastjson 的洞扫描器全看不见」。
  • 1.2.25 那条下界 GitHub 与 NVD 写法不同(NVD 没给下界),本文不对 1.2.25 以下的版本下判断。
相关推荐
程序员贺加贝18 分钟前
一次 SaaS ERP 主数据生命周期设计:Policy、PreCheck 与结构化阻断原因
java·后端·架构·saas
catino37 分钟前
spring-Bean
java·后端·spring
木卫四科技43 分钟前
当车机被“出租”:DoFun 更新器投毒链如何把 Android Head Unit 变成 BADBOX 代理节点
安全·汽车·木卫四
深入云栈1 小时前
Netty 4.2.x 源码深度解析 (十一):EventExecutor 业务线程池 —— 防止 IO 线程阻塞的并发模型
java·后端
吴声子夜歌1 小时前
Java——基本类型
java·开发语言
CoderYanger2 小时前
A.每日一题:输入单词需要的最少按键次数 Ⅰ+Ⅱ
java·数据结构·算法·leetcode·面试
Cosolar2 小时前
一文弄懂 Agent Harness 与 Agent Runtime 的区别
java·后端·github
吴声子夜歌3 小时前
Java——类、对象及方法(一)
java·开发语言
程序员夏洛3 小时前
Redis 的持久化机制有哪些?
java·数据库·redis