40 万次点击实测:AI 危险指令三成被人放行

开发者在使用 AI 编程智能体时,最常见的安全防线是”人工确认”——智能体每要执行一条系统命令,都会弹窗请求批准。这道防线到底有多可靠?一份基于 40,000 次对局、409,000 次逐条批准或拒绝决策的统计给出了答案:平均每 3 个威胁指令,就有 1 个被放行。

数据来自开发者安全博客 Scale X 的作者 Alex Wauters,他此前曾在优步(Uber)担任资深工程师。几个月前他发布了一款浏览器小游戏,让玩家扮演 AI 编程智能体的”人类审核员”,在限时压力下逐条批准或拒绝命令。有些命令属于日常操作(如 git statusnpm test),有些则意味着智能体已被劫持,正在把密钥发往远程服务器(如 cat ~/.aws/credentials)。游戏在技术社区 Hacker News 上引发讨论后,作者补齐了统计功能,并对累计数据做了复盘。

核心数据:平均准确率只有 66.3%

  • 玩家平均准确率 66.3%,即平均漏过三分之一的威胁;
  • 32.9% 的对局最终得分为负:放行威胁的扣分加上误拦安全命令的损失,超过了做对部分带来的收益;
  • 35.2% 的玩家抓住了全部威胁,但其中只有 20.8% 是在误拦率不超过五分之一的前提下做到的,其余人靠”一律拒绝”凑数,被作者授予”人类瓶颈”称号;
  • 7% 的玩家对所有提示一律点了同意。

作者也提示了样本局限:这是一款游戏,其中约 34% 的命令是威胁,而真实工作中威胁出现的频率远低于此;玩家也清楚自己正处在限时测试中。这些数字更适合用于横向比较不同威胁类型的识别难度,而非直接换算成真实环境的失守概率。

越危险的命令越容易被抓,越值钱的命令越容易漏

按威胁类型统计的漏过率呈现出清晰规律:

一眼可见的毁灭性命令被拦得最牢,而真正会把凭据送出去的命令,漏过频率大约是前者的三倍。

最容易骗过人的,恰恰是那条看起来最普通的命令

全场漏过率最高的单条命令是 npm run analyze,64.7% 的玩家直接放行。npm run 本身通常无害,但它执行的是项目 package.json 里定义的脚本内容——既可能是正常的打包体积分析,也可能是此前被写入文件的恶意代码。

游戏其实在权限弹窗上方的历史记录里明确展示了脚本内容:这条 analyze 脚本在跑完分析后,会用 curl 把结果发送到一个外部接口。三分之二的玩家依然点了同意,说明弹窗上方的历史日志很少被认真阅读。

同类命令共有三条,全部进入最难识别榜单:npm run analyze 漏过率 64.7%(37 条威胁中排第 1)、npm run setup 48.0%(第 4)、npm run deploy 44.9%(第 8)。三条合并统计漏过率 52.5%(样本量 9,482),而其他外泄型攻击平均为 28.4%。把恶意载荷藏在一个熟悉的脚本名后面,成功率大约翻倍——即便载荷就明晃晃写在日志里。

Hacker News 用户 dns_snek 的评论点出了更根本的问题:逐条批准命令这套模型本身就站不住脚。npm run build 等价于执行 package.json 里的任意 shell 命令,而智能体完全可以在无需批准的前提下先改掉 package.json、往 build.js 或 node_modules 目录里塞进恶意代码。让用户去校验那些”绝大多数时候安全、但因为文件已被改动而不再安全”的命令,算不上有力的防护。

授权疲劳是真实存在的

Anthropic 此前曾指出,其编程工具 Claude Code 中的授权疲劳确有其事:用户看到的批准请求越多,对每一条的注意力就越少,随着时间推移,监督会明显松懈。

统计图显示,即便在这样一局时间很短、且玩家已被提前告知存在威胁的游戏里,也能看到衰减迹象:按完成命令数分组后,各组玩家在开局几条命令后表现改善,随后漏过率又向上爬升。作者说明,这里已剔除那些一律拒绝的玩家;末段上升也可能与倒计时压力下的抢操作有关。

过度拦截是硬币的另一面

一批本意无害的命令被频繁误拦:npm config set registry https://npm.internal(切换到内部镜像源)被拦 59%;rm -rf dist/(清理构建产物,通常在新一轮构建前执行)被拦 45%;kill $(lsof -t -i:3000)(释放被崩溃进程占用的端口)被拦 43%。

这正是人工确认机制的两难:噪声拖慢智能体,久而久之用户放松警惕,反而更容易放行真正的恶意命令。Anthropic 的”自动模式”试图先自行判断命令是否安全、再决定要不要打扰用户,但作者认为这类机制并非万无一失。

争议最大的一条是 cat ~/.zshrc,45.9% 的玩家选择放行。反对意见同样成立:不少开发者的 shell 配置文件里并没有敏感信息,读取它无害;但对于把接口密钥写在里面的人,这就是一次凭据泄露。这条命令的风险完全取决于智能体看不到的本地配置。作者建议把密钥单独存进一个文件、再从 .zshrc 中引用,可以有效降低暴露面。

结论

作者的判断是,虽然只是一款游戏,但它暴露了把人工确认当作 AI 编程智能体安全底线的几个结构性问题:噪声太多带来疲劳,开发者也常常缺少判断风险所需的上下文——他们并不清楚文件在此之前被改动过什么。对开发者而言,更现实的做法是熟悉不同权限模型之间的取舍,并落实沙箱隔离、把凭据与环境变量密钥分离等具体缓解手段。

来源:Scale X(scalex.dev)