工程师 Alex Wauters 最近做了一个浏览器小游戏(LLM Game):你扮演一个 AI 编程 agent 的监督者,屏幕上一条条弹出 agent 想执行的命令,git status、npm test、rm -rf……你在倒计时里逐条点「允许」或「拒绝」。放行恶意命令扣分,误杀正常命令也扣分。游戏挂上 Hacker News 后,累计收集了超过 4 万局、40.9 万次审批决定(数据分析)。
结果:玩家平均只拦下约三分之二的威胁,漏掉三分之一。32.9% 的对局以负分收场,7% 的玩家干脆全部放行。既抓住全部威胁、又没有把大量正常命令一起拦下的玩家,只占 20.8%。
这些玩家是什么人?数据文章里没有交代玩家的职业构成,确切比例我没法给出。能确定的只有传播渠道:游戏靠 Hacker News 扩散。由此我推测玩家以开发者和技术从业者为主——不是随手点进来的普通网民,也不是受过专门训练的安全审核员,而恰好是日常给编程 agent 点「允许」的那群人。如果这个推测成立,这组成绩反映的就是 agent 审批弹窗真实面对的用户群。
「人在回路」(human-in-the-loop,让人类对 AI 的每个敏感操作做最终确认)常被当作 agent 安全的最后一道防线。今天主流编程 agent 的权限方案里,敏感操作走到最后一步,大多还是弹窗问你「允许执行吗?」。这份数据直接量化了这道防线的厚度。我本职做内容审核,看这组数字有强烈的既视感:这不是玩家不认真,是「让人逐条确认」这个机制本身的天花板。
人们拦下的,和人们放过的
按威胁类型拆开看,漏检率有一个清晰的梯度:一眼可见的破坏性命令,漏检率 11.7%;持久化改动类攻击(在系统里留下重启后仍生效的改动,比如改 shell 配置文件),23.8%;数据外传和代码执行类,33.4%;越权类(命令本身不算破坏,但超出当前任务的合理范围),35.0%。
全场被放行最多的恶意命令是 npm run analyze:64.7% 的玩家点了允许。这条命令的名字听起来像在做代码分析,实际上它调用的脚本里藏着一条 curl,把本地数据发往外部服务器。关键在于,游戏的历史日志里明明白白展示了脚本内容,玩家只要看一眼就能发现。三个这类「无害名字包着恶意载荷」的 npm 脚本合计漏检率 52.5%,而其他外传类攻击只有 28.4%。一层名字的包装,让漏检率几乎翻倍。
反过来,正常命令被大量误杀:npm config set registry(切换 npm 镜像源,常规运维操作)被 59% 的玩家拦下,rm -rf dist/(删除构建产物目录,日常操作)被拦 45%。
这两组数字合起来指向同一个诊断:人在时间压力下判断的是命令的「长相」,而非它的语义和后果。rm -rf 长得吓人,拦;npm run analyze 长得无害,放。至于日志里就摆着的脚本内容?信息可得,不等于信息被用上。
为什么会这样
**第一,威胁越稀有,人越看不见。**这个游戏里约 34% 的命令是威胁,三条里就有一条。视觉搜索研究早就量化过「低流行率效应」:Wolfe 等人 2005 年发表在 Nature 的实验显示,目标出现率为 50% 时,受试者漏检率只有 7%;出现率降到 1%,漏检率飙到 30%。机场安检、医学读片都受这个效应困扰(Wolfe 等人 2007 年的后续研究专门讨论了这两个场景)。真实的 agent 工作流里,恶意命令的出现率没有公开测量数据,我的推断是它远低于 1%——绝大多数人可能几个月都碰不到一条。照这个推断,这个游戏其实是简单模式:玩家知道自己在被测试、知道威胁密集。现实中的审批者面对的是更稀疏的威胁流,按低流行率效应的方向推,真实漏检率大概率比游戏里更高。
**第二,审批按钮会训练出肌肉记忆。**连续几十条无害命令之后,「允许」从一个判断退化成一个动作。游戏数据里能看到这个趋势:各组玩家在开局前几条命令上表现渐入佳境,随后漏检率一路回升。作者很谨慎地注明,这也可能是倒计时带来的紧张,未必是纯粹的疲劳。但审核员的注意力是消耗品,内容审核行业常见的做法是排班轮换、随机抽检、往队列里插入已知答案的测试样本来监测状态。这些成本高昂的机制存在的前提,恰恰是承认「人会疲」。而 agent 审批弹窗把同样的认知负荷丢给每一个开发者,防疲劳机制却基本是空白——有的产品用免审规则减少弹窗次数,但对真正落到人头上的那些决定,没有轮换,也没有抽检。游戏里 7% 的玩家全部放行,现实里对应的是有用户干脆打开跳过审批的模式(Claude Code 的 --dangerously-skip-permissions 这类开关),逻辑相同:当确认次数多到超过注意力预算,人就会整批交出判断权。
**第三,很多命令本来就没有语境无关的正确答案。**游戏里最分裂的一条是 cat ~/.zshrc(读取 shell 配置文件),45.9% 放行。这条该不该拦?取决于任务:agent 在帮你调试终端配置,天经地义;agent 在写一个网页爬虫,读你的 shell 配置就非常可疑。做内容审核的人对此再熟悉不过:边界样本上标注者之间往往达不成一致,因为判定依据不在样本内部,而在语境里。审批弹窗给到的语境却很有限,通常只有命令文本加一句简短说明,任务层面的语境被剥掉了大半。要求人在两秒内对一条缺少语境的命令做出「正确」判断,这个要求本身不成立。
对 agent 权限设计意味着什么
先说结论:逐条人工确认不是安全边界,而是审计工具。它的真实价值在于留下决策记录、供事后追查,以及在少数高风险节点上引入人的判断。把它当作防线主体,等于把系统安全押在一个已被反复证伪的假设上:人类可以在海量低风险决定中持续识别稀有威胁。
那「让用户更认真」为什么不是解法?因为失效是结构性的:注意力总量有限,而命令流的规模在增长。一个每天跑几百条命令的 agent,逐条认真审批意味着开发者的全部工作变成审批。这在算术上就走不通,不是态度问题。
可行的方向,这份数据其实已经勾勒出来了:
其一,缩小需要人判断的流。确定性规则先行:只读命令、白名单命令自动放行,真正需要判断的决定才到人面前。Claude Code 的分层权限(只读操作免审、shell 命令按规则放行)是这个思路的一个实例。但要警惕低流行率悖论的反噬:流越干净,剩下的威胁越稀有、越难被看见,所以留给人的每一个决定都必须配足语境。
其二,展示后果,而非命令文本。npm run analyze 一役说明,把载荷放在日志里等人去翻是没用的。审批界面应该直接回答「这条命令会读什么、写什么、往哪里发数据」,让人判断后果而非猜测语义。
其三,结构性兜底。作者自己的建议也在此列:沙箱执行、凭据与环境变量隔离、限制网络出口。这些机制不依赖任何人保持清醒,它们的作用是让「放行了恶意命令」的代价被封在箱子里。
agent 权限设计正在重走内容审核走过的路:把人的判断力当稀缺资源,花在真正需要人的地方,而不是平摊在每一条内容上。区别在于,这次点「允许」的不是受过训练、有轮换有抽检的专职审核员,而是每一个赶着下班的开发者。
参考来源
- Statistics on AI agent permissions(scalex.dev) — 全部游戏数据:4 万局、40.9 万次决定、各类漏检率、误杀率、疲劳趋势及作者对局限性的说明
- LLM Game — 实验游戏本体
- Hacker News 讨论 — 游戏传播来源
- Wolfe, Horowitz & Kenner, “Rare items often missed in visual searches”, Nature (2005) — 低流行率效应:目标出现率 50% 时漏检率 7%,1% 时 30%
- Wolfe et al., “Low target prevalence is a stubborn source of errors in visual search tasks”, J. Exp. Psychol. General (2007) — 低流行率效应在机场安检与医学筛查场景的讨论
- Claude Code 权限文档 — 分层权限的实例
- Claude Code 权限模式文档 — 跳过审批的 bypassPermissions 模式及对应命令行开关