审计自有 2 个 AI 项目发现的 13 个严重漏洞,核心问题是异常捕获无日志、静默崩溃和并发竞态条件。揭示了代码能用和能安全上线之间的差距。
两个项目、十三个严重 bug,以及一个反复出现在各处的模式。
大多数工程师都是在用户报告问题时,才发现自己的代码有问题。而我更早发现了这些问题——在其他人被迫面对它们之前,我主动回头对自己的两个项目进行了一次彻底审计。
这两个项目几乎处处不同。GitHub Autopilot 是一个 Flask 应用,通过 GitHub webhook 自动完成代码审查和 PR 管理。TokenMizer 则是一个代理,用于拦截 LLM API 调用,为其提供持久记忆。一个处理 webhook 流量,另一个处理模型请求。你可能会以为,它们的故障模式也截然不同。
事实并非如此。同一种故障模式反复出现在两个项目中,只是每次披着不同的外衣。下面是我的发现,以及它们让我认识到的:能运行的代码,与真正可以安全交付的代码之间,究竟有什么区别。
在 GitHub Autopilot 中,我发现了 27 处这样的代码:捕获异常后什么都不做——没有日志,没有告警,只是悄无声息地继续执行。在 TokenMizer 中,同类 bug 以静默崩溃模式散布在 12 个文件里。此外还有一个 async 竞态条件:并发请求可能乱序读取或写入记忆状态,而且在数据已经出错之前,没有任何人能够察觉。
这些 bug 都不是靠盯着代码就能发现的。要找出它们,你需要问一个不同于“它能运行吗?”的问题。正确的问题是:当它失败时——而它迟早会失败——这个故障会让任何人知道吗?
高调失败的代码令人厌烦,但至少诚实。静默失败的代码写起来很舒服,运行起来却很危险,因为它会让小问题在毫无线索的情况下不断累积,最终演变成大问题,而你连回溯的路径都没有。我在两个项目中所做的每一项修复,归根结底都是在把静默故障转变为可见故障。
GitHub Autopilot 的 auth 绕过:MCP 身份验证检查捕获了自身抛出的异常,却允许请求继续通过——也就是失败时放行,而不是失败时拒绝。于是,一项响应缓慢的 auth 服务意外变成了后门。
GitHub Autopilot 的 rate limiter:它按 IP 追踪请求数量,却从不清理过期条目。因此,这道本应阻止滥用的防线,反而变成了内存泄漏;在持续流量下,它甚至可能让应用崩溃。
TokenMizer 的安装程序 bug:MCP 安装程序中的一个边界情况,可能在安装时覆盖用户现有的记忆图谱,而不是与之合并——一个藏在看似常规的安装代码中的数据破坏 bug。
三个不同的子系统,造成了三种不同的后果——安全漏洞、可能导致服务中断的隐患,以及数据丢失 bug。但看看它们背后的共同习惯:在这三种情况下,代码都假设 happy path 会一直成立,却没有规划一旦事情偏离预期,该怎么办。auth 检查假设 auth 服务始终在线;rate limiter 假设流量始终有界;安装程序则假设没有任何已有数据可能被破坏。
优秀的防御性代码不会默认 happy path 必然成立。它会问:“当我不知道发生了什么时,最安全的默认行为是什么?”——而对于任何涉及安全或用户数据的操作,最安全的默认行为几乎总是:拒绝、不要继续、不要覆盖。
发现 bug 是一种能力。证明它们确实已经被修复,则是另一种能力,而这恰恰是在截止日期压力下最容易被跳过的部分。对于 GitHub Autopilot,这意味着编写有针对性的测试,重现每一种原始故障——伪造的请求 header、auth 服务超时、来自大量 IP 的持续流量。同时,整体测试覆盖率也从 62% 提升到了 76%;在包含 834 项测试的测试套件中,有 654 项测试全部通过。对于 TokenMizer,这意味着逐一验证全部九个问题,而不是想当然地认为一次大范围重构已经顺带解决了它们。
真正重要的数字并不是覆盖率百分比,而是你发现的每一种具体故障模式,是否都有一项能在它卷土重来时将其捕获的测试。没有针对性 regression test 的覆盖率,只是虚荣指标;只有针对性测试却不追踪覆盖率,则意味着你根本不知道还有哪些部分尚未检查。两者缺一不可。
我原本可以悄悄修复这些 bug,然后继续向前——没有人要求我进行审计,也没有用户提交问题报告。我之所以这样做,是因为真正有价值的其实并不是修复本身。真正有价值的是:我注意到了这个横跨两个无关 codebase 的共同模式,并把它记录下来,让它成为一条可以重复使用的经验,而不是一次性的清理工作。
这是我会推荐给每一位工程师的习惯。坦率地说,这也是为什么我像享受构建产品一样享受技术写作:一个 bug 修复只能帮助一个项目,而一个解释清楚的模式,可以帮助你此后接触的每一个项目。如果说从两次审计和十三个 bug 中只能带走一件事,那就是:真正能够发现问题的,并不是“它在 demo 里能运行吗?”,而是“当我所依赖的东西没有按预期运行时,会发生什么?”尽早提出这个问题,你就能在 bug 与用户产生关联之前将其修复。
GitHub Autopilot 和 TokenMizer 都是开源项目:github-autopilot · tokenmizer。
我在 TechNova World 构建开发者工具,并记录构建过程中发生的各种故障。如果你需要真正交付并审计过生产代码的人来编写文档,欢迎与我交流。
如需采取进一步措施,你可以考虑屏蔽此人和/或举报滥用行为。