一个虚假 GitHub 账号提交了54个伪造 SQLite CVE 警报,CISA 和 NVD 均采信,红帽给了 9.8 分;假警报已通过 MITRE→NVD→GHSA 链路进入企业扫描管道。
2026 年 7 月 30 日,JFrog 安全团队公布了一个值得所有构建流水线从业者警惕的问题。一个新创建的 GitHub 账号批量提交了一批 SQLite 漏洞公告。NVD 迅速将其标记为高危。CISA 的 ADP enrichment 程序也表示认同。Red Hat 最初为其中一条 CVE-2026-51302 打出了满分 10.0 的 CVSS 评分。
JFrog 的调查发现,公告中引用的函数在公告所声称针对的 SQLite 版本中根本不存在。引用的行号指向了文件末尾之外。"已在 3.51.3 中修复"的声明是幽灵修复——3.51.2 到 3.51.3 的 diff 显示,公告中提及的文件零改动。在这同一个账号发布的 55 条公告中,有 54 条完全是机器生成的伪造文本,设计成看起来像安全研究的样子。当 JFrog 将这些公告合并成一个文件时,AI 生成内容检测器立即亮起了红灯。
Red Hat 在遭到反驳后将那个 10.0 悄悄降到了 7.6。但此时这些伪造公告已经通过标准流程流动了起来:MITRE 表格 → NVD → GHSA,进而进入每一个同步这些数据源的企业扫描器。
如果你的 CI 配置会在发现 Critical CVE 时自动让构建失败,或者会自动根据 Dependabot 或 Snyk 告警创建 Jira 工单,那这个故事说的就是你。以下是事件始末、系统为何让它通过,以及我现在在自己的 Java 流水线上运行的三线分级工作流程——目的就是让一个幻觉出来的 CVE 不会浪费团队一周的时间。
细节至关重要,因为这就是你接下来会再次看到的模式。
不存在的函数。 CVE-2026-51302(9.8 高危)声称在 exprComputeOperands() 中存在 use-after-free。但该函数在 SQLite 3.41.0(公告指定的版本)中根本不存在,它是在 2025 年中期才被加入的。公告还声称 sqlite3ReleaseTempReg() 会留下一个悬空指针,但该函数只是将寄存器索引回收到一个数组中。从设计上就不可能产生 use-after-free。
超出文件范围的行号。 CVE-2026-51296(7.5 高危)引用了 json.c 的第 3555 和 3575 行。在 SQLite 3.41.0 中,整个文件只有 2706 行。被引用的行根本不存在。
幽灵补丁。 CVE-2026-51303(9.8 高危)声称修复已于 3.51.3 版本落地。但 3.51.2 到 3.51.3 的 diff 中对 src/expr.c 没有任何更改。
从未能执行的 PoC。 JFrog 在隔离的 Docker 容器中构建了 SQLite,并在 AddressSanitizer 下运行了每一个 PoC。其中一个 PoC 是无效 SQL,在解析阶段就失败了,根本没有到达它所声称被利用的代码。其他 PoC 则干净地运行完成,零内存错误。
分析了六个 CVE,六个全是伪造。更大范围的审计发现该账号发布的 55 条公告中有 54 条是垃圾,剩下那一条虽然包含一个真实漏洞,但其元数据未经核实。Hacker News 上的讨论达到了 727 热度值和 373 条评论,实践者们最集中的担忧如出一辙:大多数组织对此毫无防御能力。
理解失败模式能告诉你自己的防御应该部署在哪里。
无身份验证。 MITRE 公开的 CVE 提交表单不验证你是谁。任何人都可以提交一份漏洞描述并给出一个 CVSS 评分建议。
安全网在 2024 年断裂了。 NVD 以前会在 CVE 进入系统前进行人工分析和富化。NIST 在 2024 年 2 月因报告激增而有效暂停了这种深度分析,工作负载被推给了 CISA 和其他授权数据发布者。结果就是一条碎片化的流水线加上大量积压。
无 PoC 要求。 当前系统中没有任何步骤要求提供概念验证(PoC)或复现步骤。一条听起来 plausible 的伪造公告可以从提交一路滑到 NVD、GHSA,再到你的扫描器,全程没有一个人真正运行过这个漏洞利用。
最后这一点才是关键。系统信任文本。LLM 能生成流畅的文本。这不会是最后一波。
你可能没有直接嵌入 SQLite,但 org.xerial:sqlite-jdbc 是 Java 生态中使用最广泛的 JDBC 驱动之一,被打包进测试工具、桌面应用和嵌入式服务。当一条带有 "sqlite" 的 CPE 的 Critical CVE 进入 NVD 时,漏洞扫描器会将其与你的依赖树中每一个匹配该模式的 jar 进行匹配,然后你就会收到告警。
真正的成本取决于你的组织:
这种情况在其他地方已经大规模发生了。curl 项目在 2019 年启动了漏洞赏金计划,产生了 81 个真实安全修复,支付了超过 90,000 美元的奖励。Daniel Stenberg 在 2026 年 2 月 1 日关闭了该项目,因为 AI 生成的垃圾报告埋没了维护者。激励机制现在已经反转了:生成伪造公告几乎零成本,而证伪它们却要耗费真实的工程师工时。
我在每次构建时都运行依赖扫描,并将每条 Critical 告警视为未经证实的,直到被证明为止。以下是整个序列,适用于基于 Maven 的 Spring Boot 流水线,但其逻辑同样适用于 Gradle 或其他任何构建工具。
OWASP Dependency-Check 在 Maven 构建中提供基础扫描:
<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>12.1.0</version>
<configuration>
<nvdApiKey>${env.NVD_API_KEY}</nvdApiKey>
<failBuildOnCVSS>11</failBuildOnCVSS>
</configuration>
</plugin>
注意 failBuildOnCVSS 设置为 11。这实际上禁用了按评分让构建失败的功能,因为 CVSS 单独作为一个门控条件是很糟糕的——它衡量的是理论严重性,而不是漏洞代码路径是否在你的使用中存在,更不关心这个 CVE 是否真实存在。扫描输出仍然会给你完整的清单,而这才是你真正想要的。
NVD 和 GHSA 经常互相镜像,所以第二次意见意味着要更接近源头。Google 运营的 OSV.dev 数据库可以通过 API 查询:
curl -s "https://api.osv.dev/v1/vulns/CVE-2026-51302" | jq '.summary, .modified, .affected[].package.name'
对于一条垃圾 CVE,你经常会发现:上游项目没有公告、受影响的版本范围与现实不匹配、或者一条只是回声原始提交内容的条目。上游未确认不等于被证明是伪造,但它提高了你投入工程时间的门槛。
这是杠杆最高的习惯,直接来自 JFrog 的红旗指标:
对于一个 Java 服务,检查被标记的依赖是否在你的运行时路径中,以及具体是哪个版本:
mvn dependency:tree -Dincludes=org.xerial:sqlite-jdbc
一个只出现在 test scope 中、或者通过你并未发布的工具间接带来的 jar,会完全改变优先级。在 Java 流水线中,大多数扫描噪音首先是作用域噪音,其次才是其他。
无论 CVE 是真实的还是伪造的,写下你检查了什么并附上证据链接:公告、源检查结果、决定。当合规审计来临时,"我们验证了公告中引用的函数在指定版本中不存在,这是链接"是一份可辩护的例外记录。"我们忽略它了"则不是。一份只追加的三线分级日志,每条 CVE 一行,耗时几分钟,但当下周同一条告警再次触发时,可以节省重复调查的成本。
既然我写了很多关于构建 AI 代理的文章,这里再多说一句警告。如果你已经将 LLM 接入告警流水线来做摘要或自动三线分级,伪造公告几乎是一种最糟糕的输入。模型会读到描述一个 plausible 的 use-after-free 的流畅、技术细节丰富的文本,然后会很乐意为此起草一份补救方案。失败是隐形的,因为输出看起来完全像一个正确的三线分级结果。
防御是结构性的,不是提示词层面的:永远不要让代理在 Critical 严重性等级上单独闭环。将可机器检验的证据作为输入——函数是否存在、行号是否可解析、是否有厂商公告——并让代理在其输出中引用这些证据。如果证据步骤目前还无法自动化,代理的工作是为人类准备检查清单,而不是做决定。
如果你是 Java 服务的负责人,现在正在设置依赖扫描:
以上并不意味着放弃 CVE 监控。它意味着将漏洞数据源视为不可信输入——而从这个月开始,它们事实上就是。
你在自己的流水线中遇到过伪造的或完全不适用的 CVE 吗?你的团队是如何处理的?你的流程在与之接触后还能存续吗?我真心想知道,因为这里的集体 playbook 仍在书写中。
我每周都会写关于 Java、Spring Boot 和 AI 工程的文章,通常来自正中间那些恰恰如这一篇的问题。欢迎订阅,免费的,这是看到下一篇最好的方式——我计划将这个检查清单接入一个自动化的 CI 门控。