Pi 为什么说权限弹窗是「安全剧场」?
本课一问:第 3 课说「问多了人就不看」,主流 harness 的回答是分层放行、模型审批。Pi 的作者给了另一个回答:权限弹窗多半是「安全剧场」。他为什么这么说,Pi 又拿什么代替?
这一课先不碰:容器与沙箱的具体做法(A4);Pi 在其他方面「不做什么」的清单(课程其余章节各自讲)。
从已有出发
第 3 课的组件里有一行 Pi:默认没有权限层,修 test_parse_date 的每次调用都直接执行;加上 permission-gate 扩展之后,我们真实运行里的测试命令一条都不命中它的正则,弹窗仍然是 0。
这不是 Pi 的疏忽,而是一个写进仓库的立场。
先自己设计:把权限弹窗当成安全边界
最常见的想法:危险操作前弹一个确认框,用户点「是」才执行——有了这道闸,就算安全了。
- ① 朴素方案
- ② 它在哪失败
- ③ 改进方案
| 这道闸靠什么 | 真实情况 | 出处 |
|---|---|---|
| 人会认真看每个弹窗 | 用户批准了约 93% 的弹窗 | Anthropic 官方自报(第 3 课) |
| 换成模型来看 | 真实越权动作上漏判 17%(n = 52) | Anthropic 官方自报(第 4 课) |
| 正则能认出危险命令 | Pi 的 permission-gate 在 6 条危险命令里放过 4 条 | pin 源码实跑(第 1 课) |
Pi 的回答分两层:确认框只当减少手滑的护栏,做成可选的扩展,不进核心;边界交给进程之外——容器、微虚拟机或策略沙箱。下一节是作者自己的论证。
立场:进程内的闸门,给不了真正的边界
三处一手材料(均钉 pin 31b513e3;2026-09-22 起现行 README 已删掉 Philosophy 一节,引用只能钉这个 SHA):
- 作者的博客(2025-11-30)写得很直接:Pi 默认就是「YOLO」模式,不做权限检查;别家 coding agent 里的安全措施,「they’re mostly security theater」——一旦 agent 能写代码、跑代码,基本就拦不住了 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条维护者本人的观点陈述,不是实验结论;他在 wordman.dev 播客 Ep.19(2026-06)里说法相同,该转录经三方核查 3-0 通过。 出处Mario Zechner 博客 ↗需联网 。
- 根 README:Pi 没有内置的权限系统,默认以启动它的用户和进程的权限运行;需要更强的边界,就把 Pi 放进容器或沙箱,并给出三种做法:Gondolin 扩展(工具调用转进本地 Linux 微虚拟机)、整个进程跑在 Docker 里、跑在 OpenShell 这类受策略控制的沙箱里(
README.md:38-46)。 - 安全文档:进程内做一个「半截的沙箱」,很容易被误认为安全边界,而它照样依赖宿主的 shell、文件系统、包管理器、凭据和扩展代码;真正的隔离只能来自操作系统或虚拟化、容器边界(
packages/coding-agent/docs/security.md:31-37)。
把这三处连起来,论证有两步:
- 弹窗挡不住有意的绕过:第 1 课已经看到,规则只认命令文字;第 4 课看到,连专门的审批模型也有 17% 漏判。
- 弹窗还会制造虚假的安全感:第 3 课的 93% 批准率说明,用户在大量点「是」;既然这道闸靠不住,不如坦白告诉用户「这是 YOLO 模式」,需要边界就用容器。
不做,不等于做不出来
Pi 的仓库里恰好有这个功能的示例扩展——作者不是做不出,而是不放进核心:
| 核心不做的功能 | 仓库里的示例扩展 | 行数(pin 上 wc 实测) |
|---|---|---|
| 权限确认框 | examples/extensions/permission-gate.ts | 34 |
| 子 agent | examples/extensions/subagent/index.ts + agents.ts | 1,141 |
权限门只要 34 行:注册一个 tool_call 处理函数,bash 命令命中 3 条正则(rm -rf、sudo、chmod/chown 777)就弹一个是 / 否,没有 UI 时直接拦下。它能挂上去,靠的是核心留的拦截点 beforeToolCall(packages/agent/src/agent-loop.ts:619-647):返回 block 的调用会变成一条错误 tool result 回给模型,而不是抛异常中断循环。
第 1 课的组件把这 3 条正则原样跑过:11 条命令里它命中 3 条,4 条本意危险的命令它放过了。作者当然知道——所以它只是示例,不是边界。
常见误解:「Pi 认为权限不重要。」
它的立场是:这个功能只值一个 34 行的扩展,不该占核心的复杂度和系统提示词;真正的边界应该是容器。要确认框的人可以装扩展,要隔离的人应该上容器,两件事都不该假装成对方。
和另外几家放在一起
| 核心里的权限 | 真正的边界放在哪 | |
|---|---|---|
| Pi | 无;拦截点 beforeToolCall + 34 行示例扩展 | 容器 / 微虚拟机 / OpenShell(用户自己选) |
| Claude Code | 规则引擎 + 六种模式 + auto 分类器 | 内置 OS 沙箱(官方自认「not a complete isolation boundary」);bypassPermissions 只建议在隔离环境用 |
| Hermes | 4,553 行的 approval.py | 它的 SECURITY.md 说唯一的安全边界是操作系统;默认的 local 后端在宿主机上直接执行,另有 docker、singularity 等可选的容器与云沙箱后端 |
三家说的是同一件事的不同侧面:进程内的判断(规则、弹窗、模型审批)管的是「想做什么」,能兜底的只有进程外的隔离。区别只在于要不要在核心里再放一层进程内的判断,以及放多厚。
- Pi 核心、bypassPermissions、CoreCoder --yes解决了零打断,模型想跑什么马上跑。卡在L1 的 6 条本意危险的构造命令(含
rm -rf /)会全部直接执行。 - 朴素 黑名单:子串或正则lcc s01 / s03、CoreCoder bash 正则、Pi permission-gate解决了把已知危险的写法挡在执行之前,代码只有几行。卡在lcc s03 三道闸(pin 源码实跑):6 条危险命令里漏拦 4 条,5 条日常命令里误拦 2 条(
cat sudoku_solver.py因含子串 sudo 被拒)。 - 第一代 每次都问人CoreCoder 交互模式、Claude Code Manual、lcc s03 的第三道闸解决了判断交给人,规则写不全也不怕。卡在我们 26 次真实运行的 139 次工具调用,在 CoreCoder 交互模式下有 74 次要停下来问(53%);Anthropic 自报用户批准了约 93% 的弹窗——问多了,人就不看了。
- Claude Code(deny → ask → allow)、OpenCode(last-match)、Codex(最严格者胜)解决了把常见的放行和拒绝写成规则,只有规则没覆盖的才问人。卡在同一份规则换一种求值语义可能换一个答案:同一份
rules-standard.json改用 first-match,真实运行 pd-firstmatch-s1 里模型的python -m unittest -v test_dateparse.py被规则 #8 拒掉。 - 第三代 分层放行 + 模型审批Claude Code auto、Codex Auto-review(代码名 Guardian)、Hermes smart解决了只读直放、项目内编辑免审,其余交给另一个模型判断;弹窗接近清零。卡在Anthropic 自报:auto 分类器在真实越权动作上仍有 17% 漏判(n = 52),官方原话「does not guarantee safety」。
- 下一章 与 OS 沙箱分层Claude Code sandbox、Codex Seatbelt / bubblewrap解决了规则管「允许调用什么」,沙箱管「调用之后能碰到什么」。卡在L1 的
python3 -c "import shutil; shutil.rmtree(…)"在四个黑名单里被 4 个全部放行;规则看不见脚本在运行时做什么 → A4。
数字口径:黑名单与「每次都问」由原实现在 pin 源码上实跑(a03-permission-fixtures.json,2026-09-26);真实运行 = 本课程项目 miniagent 用 Qwen/Qwen3-8B-MLX-4bit 本机录制;93% 与 17% 为 Anthropic 官方自报。
证据三问
| 问 | 本课的回答 |
|---|---|
| ① 它解决什么问题? | 避免给用户一道「看起来安全、其实靠不住」的闸 |
| ② 为什么这样可能对? | 进程内的判断拦不住有意的绕过,又会因为审批疲劳失效;OS 或容器边界不依赖命令写法 证据等级 · 有理论动机 有数学或机制上的理由说明它可能有效,但没有证明它一定更好。最后是否采用,仍然要看实验。 本条机制推理:与第 1、3、4 课的实测与官方自报数字一致,但 Pi 没有给出自己的实验。 出处待补 |
| ③ 实践上? | 作者自述、仓库文档与示例扩展行数都是一手材料;是否比「规则 + 弹窗 + 沙箱」的纵深防御更好,没有对照实验 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条维护者发言(满票核查)与 pin 源码行数(wc 实测)。没有第三方评测。 出处待补 |
一句话
Pi 的立场不是「权限不重要」,而是「进程内的弹窗给不了边界,只值一个 34 行的扩展;要边界就上容器」。
下一个缺口
回到主线:让另一个模型来审批,审批者该有多大权限?Pi 选择不审;Claude Code 和 Codex 选择让模型审。如果要审,审批者自己也得被关在一个更小的笼子里。
你可能会问
- 「那我用 Pi 时该怎么办?」 照它 README 说的:要么装 permission-gate 这类扩展做确认,要么把整个 Pi 放进容器或微虚拟机。前者减少误操作,后者才是边界。
- 「这和 bypassPermissions 有什么区别?」 效果接近:都不弹窗。区别是 Claude Code 把它当作一个需要显式开启、只建议在隔离环境里用的模式,Pi 把它当作默认,并把隔离交给用户。