一条 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_version 是 null。

再看同一条 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 以下的版本下判断。
相关推荐
Han.miracle几秒前
MySQL InnoDB:MVCC、记录锁、间隙锁、二级索引MVCC底层原理
java·开发语言
不停喝水26 分钟前
【前端转全栈java速通课】 项目实战④7-11节 操作数据库-登录-注册-修改密码-注销-mubatis-plus简化crud-
java·前端·数据库
y1su32 分钟前
Leetcode 二分模板
java·数据结构·算法·leetcode·排序算法
飞跨浏览器41 分钟前
亚马逊 Passkey 怎么配置?在飞跨浏览器内完成设置
安全
霸道流氓气质1 小时前
多Agent通信机制与协议设计完全指南:从FIPA-ACL到A2A/MCP的Java生产级实战
java·开发语言
007张三丰1 小时前
C/C++ 内存管理详解:从内存分布到 new/delete 底层原理
java·c语言·c++·内存管理
骇客野人1 小时前
Java BIO / NIO / AIO 完整详解 + 编程技巧
java·开发语言·nio
霸道流氓气质1 小时前
OpenTelemetry 入门与实战:Java Agent、Spring Boot Starter与LLM调用追踪示例
java·开发语言·spring boot
m0_587383001 小时前
24 小时自助健身房系统软件开发实战指南与案例解析
java·spring boot·spring·系统架构·需求分析