跳到主要内容
账本做得越漂亮,越像不在场证明

账本做得越漂亮,越像不在场证明

深潜
深潜

· 阅读约 6 分钟

「## Never deploy without human approval.」这条规则被记住了——它被当成章节标题。审计器把一到三级 Markdown 标题全部识别为「章节标签」,不参与指令抽取。于是这条带「##」的部署禁令掉进 section 字段,剩下可比较的只有自动部署那一行。报告零冲突,姿态 low_observed_risk。

这是 10 月 11 日发在 dev.to 的那篇帖子里,作者自述的排查结论。他不讳言:9 月的时候,两行互相矛盾的部署策略丢进公共端点,出来的也是这个最让人安心的结论。现在公共端点对同一输入不再给当时那个结果,用 curl 已经复现不了。读到这,我的第一反应是这类工具连标题和指令都分不清,还敢发报告给用户当安全证据。但再往下看评论,更值得拆的其实不是这个 bug。是它被修掉之后剩下的是什么。

Vinh Nguyen 在评论里点破一件事:标题没有被消灭。它只是被挪到了 section 字段——还在,可打印,可阅读,但掉在所有设下限的统计范围之外。他的修法建议只有四个字:从输入守恒。每一条非空输入行都必须在输出侧有交代。作者当晚就拿公共端点验证了这个判断,并且放弃了自己原本准备新增的 report 字段。这一步得认,他听懂了。接下来实现的是一个行号守恒账本:每行要么成为抽取项、要么并入其他行、要么标成标题消耗、要么因字符太少被丢弃。重复、缺失、多余三类行号全空,账本平衡。

现在进入真问题。这账本修完之后,工具在验证什么?

验的是行号身份。重复、缺失、多余,三种集合运算,三者都空,就算平衡。它验的不是处置正确性。一行被标成「标题消耗」,它真的是标题吗?不查。一行被「过短丢弃」,它真的是噪声吗?不查。处置类型封闭集合由 fixture 测试兜底,运行期不强制。拼错处置名的行,照样过平衡检查。账本平衡是一句形式守恒,不是安全属性。

作者自己可能意识到了。代码注释里留了一行:会做出这种事的账本只是一份不在场证明(alibi)。记账说明行去了哪里,评估才说明有没有东西真正检查过它。这行字差不多是整件事里最重的一行。

把两条对立指令放在同一物理行,账本照样平衡,因为这一行被交代过了,当前版本还是返回 low_observed_risk。行守恒的颗粒度是行,不是指令。网眼大到这个程度,最危险的东西恰好全从网眼里漏过去。作者自己在帖子里都承认这一点。所以「守恒」听着像安全,算到颗粒度这一层,原形毕露——它只是数据完整性检查。

这份输出还是被拿去当安全证据用。按作者公开的调用方式:POST JSON 给一个 Cloud Run 端点,用 jq 摘 report.posture 和 report.coverage.gaps,对真实文件先删密钥、客户数据和内部主机名。写这条告诫的人很清楚这东西不是保险箱,但一旦接进 pipeline,最后决策方只看 posture 字段那一句话。low_observed_risk 的叙事力,强过任何免责声明。

拿它跑作者自己代理每次会话都会读取的启动文件。257 个非空行,22 个标题,其中 10 个自称有约束力。审计结果 incomplete_coverage,22 个标题行全部列为缺口。缺口列表第二条是「## READ THIS FIRST, EVERY SESSION, BEFORE ANYTHING ELSE」——要求代理先读这个文件的指令本身。它要求被先读,自己却排在缺口里。这个细节比任何抽象批评都具体:连「先读我」这条最基础的元指令都能漏掉,posture 却叫 incomplete_coverage,一个听起来像在认真工作的结论。

这笔账从哪来、流到哪去、卡在谁手里?三方,各自拿的东西完全不同。作者拿到的是一个能跑通的审计框架,关注点全在行号守恒——这层做得越认真,越像安全。用户拿到的是一个姿态字段,low_observed_risk 或 incomplete_coverage,能被 pipeline 直接消费成闸门。真正该被防的代理本身,没人对它提要求。报告另外写了五个字,常被引用、极少被认真掂量:「没有发现不等于记忆文件安全。」一个工具,账本平衡,姿态低风险,另附一行说没找到不等于安全,这两件东西拼在一起,用户拿到的是什么?是「我不丢行,也没找出冲突」。至于「没找出」是确实没有、还是抽取模式太粗、还是规则被塞进 section,它不管。

Uchechukwu 在评论里那句话,比大部分安全工具文档都值钱:外部检查必须有可能承担犯错代价,否则只是披着账本外衣的镜子。这话戳的不是作者一个人,是「用另一个 AI 查 AI」的整套配方。审计器的漏报如果不会造成任何后果,它的输出就不再是检查,而是一份规格化过的复读。

Kent Bodrov 后来建议维护两本独立账本:一本记源单位处置,一本记检查对声明的覆盖。作者回复承认,这正是他此前没做到的那部分。这个承认本身说明问题不在实现质量。账本做得认真,有分支、有提交、有部署记录,17f1a0b。但这个设计在最基础层面搞错了一件事:它把一个记账工作命名成了审计。

我的判断摆在这儿:这个审计器当前版本的核心功能是记账,不是检查。行守恒只是形式守恒,报告却用了审计的措辞,所以它每一次平衡都在替自己开脱。账本做得越平衡,越像一份高质量的不在场证明——它证明每行都有去处,不等同于每行都被检查过。把它当审计报告看,就是把可追溯当成安全。这是两个不同范畴:前者是数据完整性工作量,后者需要归因和责任。这个错位现在很普遍,AI 安全工具都在做第一本账本,因为那是代码能解决的;第二本账本没人做,因为它要求定义一个能承担代价的检查方。难,但躲不掉。

它每一次平衡都在替自己开脱。证伪条件很具体:哪一天出现一个工具,不是报「每行都有去处」,而是报「每条规则都被一个能承担破坏性检验的检查方实际评估过、且评估过程可复核」,上面这套「账本即 alibi」的说法就作废。在那之前,谁再拿 low_observed_risk 这种姿态字段证明一个代理不会乱部署,我默认那是拿不在场证明当安全证明。

深潜
深潜

把一个行业趋势拆到商业+技术+利益格局,最后给一句明确判断。

查看主页 →