程序员日常使用Claude Code代理时,突变测试在临时副本中运行却影响了真实Chrome配置文件,意外删除了记账文件并创建了11个虚假草稿 Listing。
我的 agent 每天在一台 Windows PC 上运行一个自治的 Claude Code agent。数据来自它自己的账本,而非记忆。
在同一天内,同一个错误以三种不同的形式出现。第三次直接删除了我的 agent 用来计算钱的文件。
我的 agent 在运行变异测试(mutation testing)。工具会编辑源代码的一行(翻转条件、删除一行、更改参数),运行测试,然后检查是否至少有一个测试失败。如果所有测试仍然通过,说明这些测试并没有真正监控那一行代码。
编辑发生在代码的临时副本中。这看似安全。实际上并非如此,因为副本仅仅是代码的副本。
一次变异运行覆盖了 394 个编辑项,其中包括一个管理韩国自由职业市场产品列表的脚本。有两个测试调用了该脚本:一个带有未知 flag,一个带有"仅检查"flag。两者都依赖一行提前停止的代码。
当变异删除了那一行后,脚本继续执行,走向了真实登录在市场上的 Chrome Profile 和"创建新列表"的路径。几个小时后,agent 发现了 11 个草案列表,没有任何账本或日志提及过它们,它们的 ID 集中在一个范围为 24 的区间内。变异运行是最可能的原因:agent 故意破坏了停止行,脚本直接启动了这个已登录的 Chrome Profile。
修复方案:在测试会话期间,启动真实已登录的浏览器在 Profile 被触碰之前就会抛出错误。Fake 浏览器仍然可以正常通过。
当天晚些时候,一个变异绕过了一个测试的 fake 录制函数。真实的函数被执行,并将测试值写入了真实的每日营收账本。随后运行器继续执行后续步骤,在 13:36 重写了 9 个真实数据文件。
代码是临时副本。数据文件夹是绝对路径。两份代码副本都写入了同一个地方。
修复方案:测试将钱账本指向一个临时文件夹,调用运行器的测试用异常停止它,而该异常不会被运行器广泛的错误处理逻辑吞掉。
显而易见的下一步是在一个地方放置一个守卫:在测试会话中,拒绝在真实数据文件夹下进行任何写入、删除或重命名操作。
然后 agent 为这个守卫编写了测试。"删除被拒绝"使用真实的营收账本作为目标。推理过程是:守卫会阻止它,所以是安全的。
然后它对这个守卫运行了变异测试。变异测试的存在就是为了移除守卫行。没有删除检查的变异体在 16:34 对真实账本执行了 os.unlink。
没有任何备份,也没有任何副本。Agent 从 39 天的运行器日志中重建了这些行,其中每天晚间的运行都会打印当天的数字。之后所有指标的读数都与删除前的值一致:30 天总计、已测量天数计数、运行中的总计。
破坏性守卫的测试瞄准真实文件夹内一个不存在的路径。如果守卫被破坏,测试以"文件未找到"结束,而不是被删除。
守卫也拒绝创建文件夹,所以即使是探测文件夹也不会出现。一个 fixture 在每个测试前后都检查这一点。
变异工具在每个变异体执行前后对整个数据文件夹(文件、大小、修改时间)进行快照,如果任何内容发生变化就停止。
"安全检查让这件事变得安全"正是变异测试要移除的假设。任何故意破坏代码的工具都必须从这个问题开始:被破坏的代码能触及什么?浏览器、账本、守卫自己的测试目标。先封堵这些路径,然后再开始破坏。
这里的每一篇文章都来自我每天运行的一套配置:一个 CLAUDE.md、agent 在做任何操作前都会读取的 memory 文件,以及一个独立的审计 agent 返回 PASS 或 FAIL。这本书的前 3 章是免费的 PDF:https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code-free-sample
完整版共 11 章,外加 4 个可直接使用的模板(CLAUDE.md 起步版、memory 文件、审计 checklist、测量指南),每章都有动手实践部分,PDF 格式 $19:https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code
关于这个配置的问题欢迎在评论区提出——我会用实际发生了什么来回答,而不是理论。