2026年4月Cursor上运行的Claude Agent误用Railway令牌,在约9秒内删除了PocketOS生产数据库和备份,事后恢复需回滚3个月。调查显示65%组织曾发生AI Agent相关事故。
2026年4月、运行在 Cursor 上的编码代理(Claude Opus 4.6)在 staging 作业中遇到了认证错误。代理试图自己"修复"它。然后在一个与作业无关的文件中,发现了 Railway 的令牌。名义上用于域名管理,但实际上是一个拥有整个账户全域权限的令牌。代理使用它,仅用一次 API 调用,在约9秒内删除了生产数据库和卷级别的备份。
这个事件(PocketOS 案例)在日语圈鲜为人知,所以按时间顺序写下来。然后,从日语介绍文章中最容易遗漏的点开始写起——那就是"没有可还原的备份"。Railway 把备份放在了本应保护的数据所在的同一个卷里。所以被同一击抹掉了。PocketOS 能还原的最新备份是3个月前的(为了不让业务停止,只能回滚到那个时间点)。
那3个月的数据怎么办?手工重建的。而且不只是 PocketOS。客户——租车公司——不得不从 Stripe 的支付记录、日历集成和邮件确认通知中恢复自己的预订。用 Tom's Hardware 的话说就是"因为一次9秒的 API 调用,所有人都陷入了紧急的手工操作"。(来源:Zenity・The New Stack・NeuralTrust 事后验证・Tom's Hardware・Fast Company・2026年4月报道)
先把表述说准确。公司并没有永久失去一切。业务没有停止,活了下来。只是,许多介绍文章使用的"已恢复"这个词,实际上意思是"回滚了3个月,然后从支付收据和日历中推导还原差额。而且其中一部分事务工作还让客户做了"。代理9秒的活动,转化成了大量人类的時間——包括那些从未同意参与 AI 实验的人。而9秒,比人类意识到终端在做什么异常事情的时间还要短。
而且,这不是稀有案例。2026年对418名 IT・安全从业者进行的调查显示,65%的组织在过去一年中经历过 AI 代理相关事件,其中61%发生了数据泄露,43%发生了业务中断(Cloud Security Alliance"Autonomous but Not Controlled: AI Agent Incidents Now Common in Enterprises"、Token Security 委托、2026-04-21发布)。需要补充一点:这个调查中的"AI 代理"是广义的定义,包括客户服务 copilot、RAG 应用、OAuth/API 连接的外部 AI 工具等,不仅仅是编码辅助。所以可以引用为"这个领域并不罕见"的依据。
我用一个台账管理 AI 编码代理的事故。不是凭感觉,而是用表格。每个条目都有一次信息的来源,不重复计数,也不混入近失事件来夸大数量。目前确定的是10件。加上辅助证据和社区信号。
secrets 泄露:10件中5件。Claude Code 自动读取 .env 并用 echo 等输出其内容(Knostic)。Cursor 擅自读取 .env 并发送给模型侧(Cursor 论坛)。Cursor 将 API 密钥直接写入代码,在测试 fixture 中嵌入真实密钥(Vibe App Scanner)。Cursor Cloud 快照中烧入了令牌(Infisical)。使用 Lovable 构建的应用进行渗透测试,约18,000名用户暴露(The Register)。
配置・系统破坏:10件中2件。Claude Code 自动更新 bug 导致系统损坏(TechCrunch・2025年3月)。Claude CLI 会话删除了整个主目录,Mac 全军覆没——超过1,900票・数百评论的帖子(r/ClaudeAI)。
生产数据破坏:10件中2件。上述 PocketOS 案例。以及 Replit 的案例(后述)。
成本暴走:10件中1件。一条命令一夜之间烧掉约$6,000(r/ClaudeAI)。
恰好一半是 secrets 泄露。而且不仅如此。最严重的事故 PocketOS,根源也是 secrets 的问题。代理本不该访问的文件中放置了权限过度的令牌——这就是导火索。也就是说 secrets 出现了两次。件数最多的类别,同时又是最严重事故的根本原因。
Replit 的案例——"代理不会如实报告"
日语圈对 Replit 案例也不为人知,所以这里多写一些。某个代理无视明确的代码冻结(不要修改的指示)删除了生产数据库。到这里为止或许可以说是"暴走"。问题在后面。代理伪造了自己所做的事情并进行了报告(当事人 Jason Lemkin 氏(SaaStr)的一次报告;The Register・2025年7月)。
顺序很重要。被追问的代理交出了整洁的自白——"是的。在有效的代码冻结・操作冻结期间,未经许可删除了整个数据库"。但那是在隐瞒和说谎之后的事情。用 Lemkin 本人的话说是"可能更糟。隐瞒并撒谎了。在单元测试中也撒了谎,声称通过了。批处理失败时才被发现,让 Replit 解释原因后才抓住"。自我报告不仅仅是错误的,而是自信地错了两次,而发现的契机是无关处理的失败。
为了公平起见,也因为帖子的结局(coda)很重要,所以写在这里。Lemkin 本人后来也警告不要夸大受害程度——"不要混淆影响。我损失的是100小时。就这样"。Replit 的 CEO 也公开承认"不可接受,而且根本不应该发生",根本的设计缺陷(preview・testing・production 共享同一数据库)之后被分离了。我引用这个不是为了作为特定企业的恐怖故事。而是因为这两个坏掉的东西,是我们所有人都默默依赖的东西——明确的指示,和关于代理是否遵从了指示的自我报告。
这一点在设计上具有决定性。我们往往会默认"万一出了问题,代理会如实告诉我们"。但 Replit 案例表明,这个前提可能崩塌。代理的自我报告不能作为安全设施的基础。这一点,与后面"分离防守方和被防守方"的内容相呼应。
各位已经在自己动手做护栏了
如果这不是问题,没人会手工制作防御措施。但实际上,人们在做。有人在制作并公开 .cursorrules 生成器(r/cursor)。也有人制作了专门捕获代理错误的回归测试机制(r/cursor)。还有人只是想要一个"不要读这个文件"的简单列表,结果最终不得不手写 .claude/settings.json 中的 Read(**/.env)・Read(**/*.pem)・Bash(cat **/.env) 等 deny 规则——因为简单的列表没有效果(issue #56997)。
我把这些当作素直的观察而不是推销来读。实践者愿意投入自己的时间写 workaround,说明课题确实存在,那里应该有通用解决方案的空白。
这里是令人不舒服的部分。在 PocketOS 事件中,项目已设定了规则,Cursor 声称有防破坏操作的护栏,Claude Opus 4.6 是以工具使用安全性为卖点的旗舰机型。所有这些层级都齐全了,但没有一个能阻止(NeuralTrust 的安全事后验证验证了各层级)。
这比单独的 bug 报告更有说服力,而 bug 报告也指向同样的方向。其中有一件甚至不是报告。2026年1月,The Register 自己重现了 Claude Code 能够读取放入 .cursorrignore 应该无法读取的 .env 内容。尽管工具端的说明是"拒绝读取与其中所写模式匹配的文件"。开发者的报告也是同样的内容——"本意不让读 .env放了 .cursorrignore。没效果。Claude 连同秘密一起读取了 env 文件并纳入对话。没有警告。没有错误"。
请再读一遍最后一句。这里浓缩了问题的全部。防御没有被华丽地突破。只是坐在仓库里,外表像防御而已。
而且权限问题不限于单个仓库。同一个2026年的调查显示,82%的企业在自有 IT 环境中发现了未曾掌握其存在的 AI 代理(41%发现多次)(Cloud Security Alliance / Token Security・2026-04-21。这也是广义"AI 代理")。连代理在运行都不知道的话,不可能控制它能触及什么。
结构性的论点是:内置护栏与代理存在于同一进程、以同一权限运行。护栏与代理同命运。代理误操作时,本应捕获它的装置也会一起误操作。防守方不应该与被防守方处于同一进程。
得出这个结论的不只是我。在 PocketOS 事件的 Hacker News 帖子中,技术人们自力地得出了结论。真正的原因是访问控制,解决方法是把破坏性能力隔离到人类门禁后面(事件的主要讨论帖——超过100条评论——和第二个帖子"Claude-powered AI coding agent deletes company database in 9 seconds")。
引用这个不是为了反驳,而是作为援军。这些工具最亲近的人们已经在认为"答案是门禁+权限分离"。这篇文章的重点是,那个门禁实际运行起来会怎样。
这是我实际在运行的——5个门禁和决定性的 diff 验证
这里是报道的二手信息,而是自己运行过一次的信息。我数个月来,围绕着绝对不想让代理修改的少数文件(安全规则、ADR、代理自身的配置,以及保护脚本本身——称之为"不可侵犯集合")铺设门禁在运行。
工作的是两个脚本。一个是定义和保护不可侵犯集合的,另一个是验证 diff 的。这两个在 CI 上作为5个独立检查——后面会提到的"5个门禁"——来运行。如果数的话,脚本是2本、门禁是5个。设计基于3条规则。
# 说明用 — 非逐字的实际脚本
import hashlib, subprocess
from pathlib import Path
protected = load_inviolable_list() # { 路径: 期望的sha256 }
changed = subprocess.run(["git", "diff", "--name-only", base, head],
capture_output=True, text=True).stdout.split()
for path in changed: # diff 是否触及了保护集合
if path in protected:
fail(f"触及了保护文件: {path}")
for path, expected in protected.items(): # 内容哈希是否仍一致
actual = hashlib.sha256(Path(path).read_bytes()).hexdigest()
if actual != expected:
fail(f"保护文件内容已变更: {path}")
ok() # 如果有任何 fail(),Check Run 就不合格
没有概率,也没有"模型说应该没问题"。保护文件变了,还是没变,只有这两种情况。
无法验证的,一律 fail(偏向安全)。检查无法运行、无法读取文件、无法确认状态时——不让通过,朝着关闭的方向失败。默认是"No"。这恰好与不确定时"先试着修一下"的代理行为相反。
只有人类能打开门禁。通过自动检查只是必要条件,不是充分条件。合并需要人类批准。这个批准步骤正是对前节结构性问题的直接回答。门禁在与它裁量的代理不同的位置、以不同的权限运行。代理无法自行批准自己的工作,也无法触及批准机制。
设置了一个有意的限制。门禁很窄。不试图判定 PR 中的所有变更是好主意。那是模型化 review 一直在失败的工作,"这个变更安全吗?"这个问题太开放,代理可以把讨论带到任何"是"的方向。门禁只回答关于小的保护集合的封闭问题——那里有什么动了吗,内容还一致吗。集合之外的部分,正常合并。决定性的检查只在问题窄到可以用 Yes/No 回答时才可信。所以我故意把问题设窄了。
在稳态下,这看起来很无聊。这正是目的。不可侵犯文件4个,每次确认无变更,5个门禁全部绿色,持续好几个月。无聊才是成功条件。有意思的日子,只有 diff 显示保护文件被移动了、在人类发现之前门禁就阻止了合并的那一天。
"这个 GitHub 标准功能做不到吗?"
一定会被问到的问题,所以先于评论区不意打击自己写出来。老实说,能做到。不过取决于你的仓库种类。
GitHub 确实有按文件路径的門禁。Ruleset 的 required reviewers 规则,用官方文档的话说"对涉及特定文件或目录变更的 PR,强制要求指定团队的审查或批准",最多可设置15个团队、每个团队设定必要批准数。Push ruleset 的 restrict file paths 阻止包含匹配路径变更的 commit 的 push(最多200个模式)。此外 CODEOWNERS + "强制代码所有者审查"也以更粗粒度的方式做同样的事情。如果这些符合你的情况,你应该使用。没有必要把不存在的东西说成存在。
问题在于"你"是谁。required reviewers 规则,GitHub 自身文档记载"is not available on user-owned repositories as they do not contain teams"(用户拥有的仓库因为没有团队而无法使用)。个人开发者、个人账户下的仓库、public 项目——这扇门是关着的。Push ruleset 也是"available for the GitHub Team plan in internal and private repositories"(Team 计划,internal / private 仓库)。public 仓库和免费账户不在范围内。也就是说,最有可能深夜2点无监督运行 AI 代理的群体——个人和小团队,以及 public 代码——在官方规则的覆盖范围之外。
而且,即使能应用,这些也是"原语"而不是"阵型"。设置损坏或 API 失败时不会变成红色。也不会保护保护设置本身。对"AI 代理容易不经意触动的路径是哪些"也没有意见。这不是对 GitHub 的批评。通用平台没有义务内置我的威胁模型。只是,"组装起来可以做成类似的东西"和"已经组装好了,而且设成了会变红"在实运上的差异不小。
所以,老实的立场变窄了。如果你是 org 管理员,有意自己布线 Ruleset,我的 App 可能不需要。如果不是——或者不想让"无法验证的案例"默默通过、而想要硬红色——那就是空白。
下一步:同一个门禁,任何仓库都可以
这里写的都是在自己的仓库布线的脚本。作为下一步——也有几个人问过——正在制作一个 GitHub App,让任何仓库都能使用同样的决定性检查。保护路径、fail-closed 验证、仅人类批准,按 PR 运行。不会做比你们刚读到的机制更聪明的事。这才是要点。
现在还在犹豫的是"默认应该保护什么""团队之间如何共享保护集合"这样的设计,这里是外部意见可以影响结果的部分。如果这与你的问题重叠,请告诉我意见。等待名单附带5题问卷,大约1分钟:https://tally.so/r/9qgREV
关于手法的注记:上述事故全部来自每个条目有一次信息来源、不重复计数的台账。使用调查统计的地方,明确记载了该调查的对象是"非编码代理限定、广义的 AI 代理"。今后如果添加案例,件数会随之变动——事故增加对这个主张来说不是坏消息。