一条 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 以下的版本下判断。
相关推荐
鹿角片ljp2 小时前
LeetCode 64:最小路径和复盘|二维 DP 与 ACM 模式完整写法
java·数据结构·算法
泡海椒3 小时前
PDF 表格样式优化:jquick-pdf 边框、圆角、背景色
java·开发语言·pdf
景熙55234 小时前
15.Java 8 Stream 流入门到实战
java·开发语言·数据结构
wno7045 小时前
Spring Security权限控制
java·python·spring
杨运交5 小时前
[071][验证码模块]基于Spring拦截器的验证码认证设计思想
java·后端·spring
Geek-Chow5 小时前
CountDownLatch in Java
java
SL_staff6 小时前
从RBAC到场景化授权:《无忧·企业文档》三级权限模型的技术实践解析
java·开源·产品
传奇开心果编程7 小时前
【springboot基础语法学与练】第 1 课:从零开始
java·spring boot·后端·学习
SL_staff7 小时前
财务系统慎用低代码?从数据模型闭环看合规落地的技术实践
java·低代码·全栈