Pi 为什么宁可不做沙箱?
本课一问:Codex 把沙箱做到 122 行,Claude Code 内置沙箱 + 审批。Pi 却在文档里明说「不做内置沙箱」。它为什么这么选?
这一课先不碰:各家隔离机制的细节(主线第 3 课);Pi 在权限、子 agent 等其他方面「不做什么」的清单(各章各讲)。
从已有出发
第 3 课的对照表里,Pi 那一栏「隔离机制」写的是「核心不含内置沙箱」。这和 A3 岔路里 Pi 对权限弹窗的态度是同一个思路:进程内的东西给不了边界。
先自己设计:做个进程内的部分沙箱
很自然的想法:哪怕做个「部分沙箱」——限制一下文件和网络——也比什么都不做强。
- ① 朴素方案
- ② 它在哪失败
- ③ 改进方案
「部分沙箱」的问题是心理上的:用户看到「有沙箱」,就会把不可信仓库、无人值守任务放心交给它。可只要它还跑在宿主进程里,shell、凭据、扩展代码都在攻击面上。
Pi 的选择:核心不做进程内沙箱,坦白告诉用户默认就是 YOLO;要边界,就把整个 Pi 放进容器 / 微虚拟机 / 策略沙箱。真正的隔离来自 OS 或虚拟化边界,而不是一段进程内的检查。
立场:一手材料
Pi 把这段写进了 docs/security.md(pin 31b513e3):
配套的两处一手材料:根 README.md:38-46 给出三种容器化做法——Gondolin 微虚拟机(工具调用转进本地 Linux micro-VM)、整个进程跑在 Docker 里、跑在 OpenShell 这类策略沙箱里;SECURITY.md:50 把「本地代码执行或沙箱行为」明确列为不在安全响应范围,并注明「the Pi coding agent intentionally does not have a sandbox」。 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条pin 源码直证;勘误表 P7:最新版该文档改名「Run Pi safely」、逐字引文已删,立场仍在,故引用钉 pin SHA。 出处Pi README(pin 31b513e3) ↗需联网
不做,不等于做不出来
Pi 的仓库里恰好有一个 sandbox 示例扩展:它用 @anthropic-ai/sandbox-runtime(macOS 上 sandbox-exec、Linux 上 bubblewrap)给 bash 加 OS 级限制,默认 denyRead 掉 ~/.ssh、~/.aws、~/.gnupg,只允许写 . 和 /tmp。作者不是做不出沙箱,而是不放进核心——和 A3 岔路里那 34 行 permission-gate 示例扩展是同一个态度:确认框和沙箱都做成可选扩展,核心保持最小,边界交给用户按需选。
- 上一章 只有进程内规则A3 权限规则、Pi 的确认弹窗解决了在执行前按「工具名 + 命令文字」裁决,拦住模型明着提出的危险调用。卡在规则看不见子进程实际做什么:不套沙箱时,
python -m unittest …; python -c "写 ~/.ssh"里权限层按前缀放行(rule_index 8),复合命令里的 python -c 把内容真的写进了伪 HOME(T9 r07)。 - 第一代 朴素 OS 沙箱:只放行工作区allow default 再挖掉写与网络解决了约束进程实际发出的系统调用(含全部子进程):写工作区外、联网被内核拒。14 条命令里拦下 6 条。卡在工作区里面不设防:同一条写
.git/config的命令,朴素策略下照样成功(T9 r03)——能借此改 remote、植入 git hook。 - Codex Seatbelt(seatbelt_base_policy.sbpl,122 行)解决了从
(deny default)起步,可写根用参数注入,.git/.codex/.agents用锚定正则单独保护,默认断网。workspace-write 下拦到 9 / 14 条。卡在沙箱挡写和联网,不挡读:读伪 HOME 里的假私钥,在四种策略下全部成功(T9 r12)——读到的东西还能经合法命令传出去。 - 第三代 分层:沙箱 + 审批 + 容器Claude Code(OS 沙箱 + 审批)、claude.ai(gVisor 容器)、Cowork(完整 VM)解决了把边界移出进程,按「爆炸半径」分档;规则管「允许调用什么」,隔离管「调用之后能碰到什么」。卡在私有数据 + 不可信内容 + 外发能力三者同在时,数据可经已放行的域名外传——规则与沙箱都放行(lethal trifecta,→ 岔路 B1)。
- Pi 核心、bypassPermissions解决了不做「半个沙箱」以免被误认为边界;坦白这是 YOLO,把真正的隔离交给容器 / 微虚拟机。卡在什么都不套时,T9 的 14 条越界命令全部发生(none 策略拦下 0 条);所以 Pi 说:要边界就上容器。
数字口径:全部由本机 sandbox-exec 加载 Codex 真策略录制(T9,2026-09-26 · macOS 26.6.2 · 伪 HOME,不碰真实 ~/.ssh);a04-sandbox-fixtures.json,2026-09-26 生成。
正相反。Pi 的论证恰恰是出于安全考虑:与其给一道会被误认为边界的半截墙,不如明说「这里没有墙,要墙请上容器」。它把「进程内的判断」和「进程外的隔离」分得很清——前者(规则、弹窗、部分沙箱)都拦不住有意的绕过,只有后者(OS / 容器 / VM)才是边界。这与本章主线完全一致,只是 Pi 把它推到了「核心一层都不做」。
证据三问
| 问 | 本课的回答 |
|---|---|
| ① 它解决什么问题? | 避免给用户一道「看起来安全、其实靠不住」的进程内沙箱 |
| ② 为什么这样可能对? | 进程内的部分沙箱仍依赖宿主 shell / 凭据 / 扩展,拦不住有意绕过,还会制造虚假安全感;真隔离来自 OS 或虚拟化边界 证据等级 · 有理论动机 有数学或机制上的理由说明它可能有效,但没有证明它一定更好。最后是否采用,仍然要看实验。 本条机制推理,与本章主线(进程内判断 vs 进程外隔离)一致;Pi 未给出对照实验。 出处待补 |
| ③ 一手材料? | docs/security.md、README、SECURITY.md 明说不做,仓库里却有 sandbox 示例扩展——是刻意选择,不是能力缺失 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条维护者文档自述 + 示例扩展 wc 实测;无第三方评测。勘误表 P7:引用钉 pin SHA。 出处pin 源码 ↗需联网 |
一句话
你可能会问
- 「那我用 Pi 时怎么办?」 照它 README 说的:装 sandbox 示例扩展给 bash 加 OS 限制,或者把整个 Pi 放进容器 / 微虚拟机。前者减少误伤,后者才是边界。
- 「这和 Claude Code 的 bypassPermissions 是一回事吗?」 效果接近(都不拦),但定位相反:Claude Code 把「不拦」当成一个需要显式开启、只建议在隔离环境用的模式;Pi 把它当默认,并把隔离责任明确交给用户。