一个会自我审计的系统:可信度是怎样被公开建造的
一个门禁全绿的下午
有一次我给一个陌生系统做取证审计。它的规则文件写着 25 条校验规则,CI 是绿的,日志干净,没人报错。看起来一切正常。
我做了件很笨的事:把规则文件逐行删改,每改一次就重跑一遍那条本该报错的命令。
175 个变异打进去,78 个没被拦住。
其中一条最要命:一条规则的触发条件,由被检查方自己提供——「如果你声明自己是非交互功能,你就必须登记」。所以把「非交互」这四个字删掉,要求就消失了。
一个只在你自认有罪时才生效的检查,等于没有检查。
那天之后我不再问「系统跑得通吗」,改问「系统能被查吗」。这是两个完全不同的问题,而且第二个没有默认答案。
能跑 ≠ 能被查
能跑是运行时属性,能被查是设计属性。前者靠测试覆盖,后者靠你愿不愿意把自己最不想被人看的部分留在台面上。
大多数系统在这件事上的默认行为是:只留成功路径。文档写「我们实现了 X」,没人写「我们这里其实没测过」。久而久之,团队自己也分不清哪些断言有证据、哪些只是信念。
我把可审计性拆成三件可执行的事。
一、让系统做变异测试,而且是打在自己身上
变异测试不难理解:把被检对象改坏,看判据会不会叫。难的是把工具对准自己。
大部分团队会拿变异测试去查别人的代码,不会去查自己的门禁。因为门禁是「我们写的」,默认它是对的。
上面那 78 个漏过的变异,就是对准自己门禁的结果。这不是事故,是方法——如果一套判据从来没被它自己的工装撞过,你根本不知道它护住了什么。
实现上不用复杂。任何「返回非零即拒绝」的命令都能当门禁:
python gatecheck.py \
--gate "python my_validator.py {target}" \
--target ./my-data
它逐行删改 --target 里的内容,每次重跑 --gate,报告哪些改动没引起任何反应。活下来的每一个变异,都对应一条没有任何东西在测的规则。
一个坑:--gate 绝不能放在 --target 里面,否则你会把变异打在自己身上,然后收到一堆噪声。
二、判据必须能说「不」,也必须能说「是」
我曾只证明了门禁会说「不」——75 个 ERROR 摆在眼前,很有说服力。
但我从没证明过它会说「是」。
一个永远报错的校验器,和一个永远不报错的校验器,一样没用。你分不清「严格的校验器」和「坏掉的校验器」,两者都拒绝一切输入。
所以我补了对称断言:合法基线必须 0 ERROR / 0 WARNING 通过。这条不过,我自己的主张就是假的。
不能输出否定的判据,不算判据。 一个只会说「通过」的校验器比没有更危险——它给了你安全感,却不给你保护。
三、公开审计纪律:不美化
这是最难、也最值钱的一条。
公开的东西,默认会被修图:去掉失败、合并重复、把「我猜的」写成「我确认的」。我给自己定的规矩是反过来的:
| 通常的展示 | 这里的纪律 |
|---|---|
| 只有成功路径 | 放自己的 bug、误报、假发现 |
| 「我做到了」 | 命令 + 输出,别人自己跑 |
| 无法复现 | 一条命令复现,CI 每次重跑 |
| 无法否证 | 结论标证据档位,预测 MISS 永久保留 |
具体到操作上,几条硬规矩:
- 误报要留在案。 我的第一版校验器把通配符权限当成悬空引用,报了一堆假警。修完不删记录,写清楚错在哪。
- 假发现要留在案。 有一次我差点公开指控原作者文档造假,实际是我用错了被测对象。这条也留着。
- 被撤回的结论不删。 结论改了就是改了,改的过程本身就是证据。
- 还没修的缺陷要单列。 那 4 类真缺陷,我一个都没修。诊断就是诊断,不是修复记录。把「已知未修」和「已修」混在一起,等于骗人。
证据还要分档位,不然读者没法判断你的把握有多大:
① 跑出过结果 > ② 读过原文 > ③ 只按元数据判
低于 ③ 的判断不进档案。这条约束很痛——它逼你承认「我没读」,而不是把「没读」包装成「读过了」。
一个反直觉的细节
工具不该给判决,该给清单。
上面那次运行里,78 个漏过多数是无害的(删掉一个可选字段、删掉一个标题)。如果工具喊「发现 78 个缺陷」,你第二次就不会信它了。
误报率决定一套判据能活多久。 一次夸张,长期失信。所以我把输出定位成「候选」,要不要算 bug,逐条人工复查。
这恰恰是公开的价值:一个承认「我漏了 78 个,但其中只有 4 个真有问题」的系统,比一个宣称「100% 覆盖」的系统可信得多。前者你可以去查,后者你只能选择信。
可操作清单
给想在自己系统里落地这件事的人,按成本从低到高:
- 给每条断言配上产生它的命令。 写不出来命令的断言,降级成「推测」。
- CI 里重跑断言。 断言坏了徽章要红。主张必须每次推送都被复现一遍。
- 给判据加双向测试。 除了「该拒绝的拒绝了」,还要测「该通过的通过了」。
- 拿变异测试撞自己的门禁。 先跑 100 个变异看看,别追求覆盖率数字。
- 建一个缺陷清单文件。 已知未修、已知误报、已撤回结论,全部记在案。
- 把证据分档写进结论里。 别让「我看过」和「我跑过」长得一样。
一句话
系统的可信度不是测出来的,是公开建造的——你把自己做错的部分留在台面上,别人能查,那才叫可信。
- 点赞
- 收藏
- 关注作者
评论(0)