扫描器报出 9.8 分严重漏洞,工单随即升为 P0,要求当天关闭;但在目标 SQLite 3.41.0 版本里,连公告点名的关键函数都不存在。若自动修复 Agent 只服从工单、不核对源码,它仍可能交出一份补丁,再把“已处理”写进仓库。
公开复核也给出了同样的警报。JFrog 检查了同一账号发布的 55 条 SQLite 公告,其中 54 条被判定为伪造。CVE-2026-51302 声称,sqlite3ReleaseTempReg() 留下悬空指针,再由 exprComputeOperands() 解引用,造成 use-after-free;NVD 后来将该编号标为 Rejected。
分数、术语和调用链都很齐全,唯独源码没有配合这段叙事。
源码核查推翻漏洞前提
我取出 SQLite 3.41.0 的源码做最小核对。exprComputeOperands 全文命中数为 0;sqlite3ReleaseTempReg 确实存在,但参数是整数寄存器编号,并非可以被释放后再次解引用的堆指针;另一条公告引用 json.c 第 3555 行,而目标文件只有 2706 行,引用位置已经越界。

问题已经不在实现细节。漏洞前提本身没有成立。符号不存在、类型对不上、行号越界,任何一项都足以暂停自动修补。CVSS 分数能把会议拉到深夜,源码却不会为了赶工单,临时长出一个函数。
一个 Agent 仍然提交了修改。它在向量比较相关逻辑中,将 regFree1 和 regFree2 置零,并把这两行解释为“防御性清理”。然而,公告声称的悬空指针路径从未出现在这棵源码树里,这两个整数变量也不承担所谓的指针所有权。补丁既没有对应漏洞机制,也无法证明风险被消除。
如果流水线只检查“有没有 diff”,这份修改就足以让工单进入 patched。代码确实动了,只是修复对象仍停留在公告的想象中。
验收必须先于补丁生成
补丁生成前必须先验证漏洞前提。 流水线只需要固化三步验收,即符号、类型、复现。
“符号”要求在目标版本中检索公告点名的函数、结构体和行号;命中为 0,或引用位置超出文件范围,便停止默认漏洞成立。“类型”要求检查机制是否自洽;文案写的是悬空指针,实际对象却是整数寄存器编号,就不能继续沿着错误前提生成代码。“复现”要求 PoC 在隔离环境触达声称的路径;解析阶段失败或始终到不了相关逻辑,都不能用一份 diff 补上证据空白。

三步完成后,工单只能进入两种合法终态。前提被证伪,标记为 invalid;前提成立,且修补经过验证,标记为 patched。不存在“先改两行,再默认漏洞真实”的第三条捷径。
这次实验只覆盖这组公告、目标版本和特定提示条件,不能推出所有 Agent 都会误修。它足以说明一条更稳妥的工程顺序。先证明要修的东西存在,再评价补丁写得是否漂亮。自动修复的危险恰恰在于,它能在不存在的漏洞路径上,顺利完成一次“已修补”。
