龙虾说"我要执行命令":你按允许,还是拒绝?

0 阅读6分钟

一个危险的 CVE,正在你的批准里悄悄生长。


ce702354cdd430d94330953e69ae3eb1.png 凌晨两点,你的 AI 助手发来一条消息:

⚡ exec-approvals: 请求执行 rm -rf /tmp/test-* [ allow-once ] [ allow-always ] [ deny ]

你揉了揉眼睛,点了"允许"。

然后你开始想:刚才那个 allow-always,是只对这条命令生效,还是对所有"删除临时文件"的命令都生效?

你不知道。

大多数人也不知道。

而这,正是今天这篇文章要撕开给你们看的东西。


一、为什么这个话题值得吵

在 AI Agent 时代,我们越来越多地把命令行控制权交给 AI——让它帮你部署服务、清理磁盘、安装依赖、管理服务器。

这个过程里,有一个绕不开的问题:

谁来为这条命令负责?

AI 会执行,但它的"理解"和你的"意图"之间,永远存在一条裂缝。你说"帮我清理日志",它理解为"删掉所有带 .log 后缀的文件"。但它没告诉你,它用的是 find / -name "*.log"

exec-approvals 就是 OpenClaw 填在这条裂缝上的一层补丁。

但这道补丁,是安全锁,还是效率杀手?这个问题,吵三天三夜也吵不完。


二、exec-approvals 的双层守卫:比你想象的更复杂

很多人以为 exec-approvals 就是一个"执行前问你要不要批准"的弹窗。错了。它有两层守卫,而且这两层是完全独立的。

第一层:Policy 层——全局策略的大门

Policy 层是全局配置,决定的是:哪些命令需要问,哪些命令直接放行

模式行为
always所有命令都问,不管你是谁
on-miss只在命令没有匹配到 allowlist 时问
off完全不问,所有命令直接放行(危险!)

注意这个逻辑:always 模式下,哪怕一个命令已经被加入 allowlist,每次执行还是会问。off 则是彻底躺平——只要进了 policy 层,就没有任何阻拦。

第二层:Allowlist 层——精确到命令的逐条审批

Allowlist 是你真正"批条子"的地方。它管的不是"要不要问",而是"批准了之后能跑多久"。

这里有三个选项,它们的语义非常微妙:

allow-once:单次有效,精确绑定到这一次命令 ID,执行完毕立即失效。

allow-always:永久有效,下次遇到相同命令直接放行,不需要再问。

deny:永久禁止,加入黑名单,下次遇到直接拒绝。

问题来了——什么是"相同命令"?


三、allow-always 的 command ID 绑定:一个被低估的漏洞

这是整篇文章最关键的部分,请逐字阅读。

当你对一条命令点了 allow-always,系统记录的"命令 ID"是基于命令的原始文本生成的。

# 你批准了这条
time npm test

# 下次 AI 送来的是这条
time rm -rf /

系统认为这是两条完全不同的命令——因为它们的文本不同,command ID 也不同。所以 allow-alwaystime npm test 的批准,不会自动覆盖 time rm -rf /。系统会走正常的 ask 流程,看起来"没问题"。

但换一个更真实的例子:

# 你批准了
curl https://api.example.com/upload -F "file=@docs.pdf"

# 下次 AI 送来了
curl https://api.example.com/upload -F "file=@secrets.zip"

Command ID 不同,因为文件路径不同。但语义完全一致——都是往同一个 API 端点上传文件。如果第一次上传的是普通文档,第二次上传的是敏感数据,allow-always 不会阻止你。

这不是 bug,这是设计上的权衡。

但它的安全含义是:allow-always 不是"授权这类操作",而是"授权这个 exact 字符串的命令"。

一旦你理解了这个本质,你就会明白为什么很多安全工程师看到 allow-always 会血压升高。


四、safeBins vs Allowlist:两个不同职责的守卫

很多人把 safeBins 和 allowlist 搞混,觉得它们是同一套系统的两个名字。不是的。

safeBins 是一份"免审批白名单",由系统或管理员预先定义。它针对的是那些经过验证、风险可控的常见命令,比如 lscatpwd——你用这些命令不需要任何审批流程,因为它们本身就是只读或无害的。

Allowlist 是你手动添加的审批记录。每一条记录都是你对某条具体命令的授权行为。

换句话说:

  • safeBins 是"默认信任",不需要你来审批
  • Allowlist 是"我批准了",代表你主动做了授权决策

这两个机制协同工作,构成了 exec-approvals 的完整权限体系。


五、两种立场的核心矛盾

立场 A:安全派

每次审批都是必要的,allow-always 是危险的懒政。

安全派的逻辑是:AI 的行为是不可预测的,你今天批准了 curl 上传文件,明天它就可能上传一个恶意脚本。Allow-always 本质上是把一个动态的、可能变化的 AI 行为,锁死在一个静态的授权里——这是用昨天的信任,透支明天的安全。

更极端一点的安全派会说:off 模式是自杀,on-miss 是在赌命,只有 always 模式才是正经做事的态度。

立场 B:效率派

权限限制过细就是浪费生命,YOLO 模式才是正确姿势。

效率派的反驳也很直接:如果你每跑一条命令都要审批,你和 AI 协作的效率会低到让你想回到纯手工时代。Allow-always 不是懒政,是对"我已经验证过这条命令可靠"的合理确认。你不会每次 ls 都要审批一次,为什么 AI 帮你 ls 就要审批?

而且,很多 AI Agent 的使用者本身就是经验丰富的工程师,他们有能力判断一条命令的风险——强制审批是对他们能力的否定,也是对时间的浪费。


六、那道裂缝依然在那里

回到文章开头。

你点了"允许"。

但你真的知道自己在允许什么吗?

这个问题,exec-approvals 没有解决,它只是把它显性化了。

审批机制的存在本身,就是在承认一件事:我们不完全信任 AI,但我们在用它。

安全派说:那就别用,用了就承担后果。

效率派说:那就让审批流程做到足够顺滑,让信任和效率兼得。

而 OpenClaw 的 exec-approvals,给了你配置这几层守卫的工具——但最终按不按"允许"的,是你。


你站哪边?

安全锁,还是效率杀手?

欢迎在评论区留言——告诉我你的立场和使用场景,我会在评论区等你们 🦞


如果你对 exec-approvals 的具体配置感兴趣,欢迎翻阅 OpenClaw 官方文档,那里有关于 policy 层、allowlist、safeBins 更详细的说明。但记住——工具是工具,选择还是你的。