安全与信任机制
本教程共 30 篇 · 第 13 篇 · 更新于 2026-08-10 · 约 10 分钟阅读
本节目标:理解 pi 的安全模型,掌握项目信任机制的配置与决策流程,明白 pi 为什么不做内置沙箱,以及在不同场景下如何保护自己的开发环境。
pi 是一个运行在你自己电脑上的编码代理。它不联网运行代码,也不把代码上传到远程服务器——但它的确能读写你的文件、执行 shell 命令、安装依赖。这不是 bug,是设计意图:一个编码代理如果连 npm install 都跑不了,能做的事就太少了。
所以”安全”这个词得拆开了看。pi 的安全不是”把你关在笼子里”,而是”让你决定信谁、信多少”。它提供的是一组让你看清风险、做出选择的机制。
本章基于 pi v0.84.1。
pi 的安全模型
先搞清楚一个基本事实:pi 以你启动它时的用户身份运行。它的权限边界就是你自己的权限边界。
你能读的文件它都能读,你能删的目录它都能删,你能执行的命令它都能执行。这不是 pi 的漏洞,而是 CLI 工具的常态——vim、git、npm 哪个不是这样?
pi 的设计者 Mario Zechner(libGDX 作者)对此的态度很明确:不给用户营造虚假的安全感。一个”看起来有沙箱但实际能被绕过”的半成品隔离层,比没有沙箱更危险——因为它会让用户放松警惕。
pi 的安全思路分两层:
- 输入层:项目信任(Project Trust)决定 pi 启动时是否加载项目本地的配置和扩展
- 执行层:由操作系统、容器或虚拟化来隔离,pi 不越俎代庖
三层搞定:信任管输入、OS 管权限、容器管隔离。你把这三层的关系理顺了,pi 的安全模型就清楚了。
项目信任管什么
项目信任只有一个职责:控制 pi 启动时从项目目录加载哪些东西。
它和”会话开始后 pi 能不能执行 rm -rf /”毫无关系——那个是操作系统你的权限决定的。信任只盖个项目的大门口,门里面你让 pi 干什么它还得靠别的东西来约束。
哪些资源需要信任
pi 在进入一个项目时,会检查当前目录下是否存在这些内容:
.pi/settings.json—— 项目级配置文件.pi/extensions/、.pi/skills/、.pi/prompts/、.pi/themes/—— 项目级资源目录.pi/SYSTEM.md或.pi/APPEND_SYSTEM.md—— 项目级系统提示词.agents/skills/—— 项目 Skills 目录
只要出现其中任何一项,pi 就会触发信任检查。一个空的 .pi/ 目录不算数,不会触发检查。
另外,AGENTS.md、CLAUDE.md 这类上下文文件不管你是否信任项目都会加载——除非你显式关闭了上下文加载。
信任后会发生什么
选择”信任”后,pi 会加载:
.pi/settings.json里的所有配置- 项目扩展、Skills、提示词模板、主题
- 项目 settings 中指定的缺失 package
选择”不信任”则跳过以上所有内容,只加载上下文文件和用户全局配置。
第一次打开项目的确认流程
假设你 clone 了一个别人的项目,里面带着 .pi/settings.json 和几个自定义 Skill。在终端里 cd 进去,敲下 pi——
pi 不会一声不吭就把 .pi/ 里的东西全载入。它先检查这个目录有没有保存过的信任决策,没有的话就按你设好的默认策略来。
默认策略是 "ask",所以你会看到类似这样的提示:
This project contains pi resources that require trust:
.pi/settings.json
.pi/skills
Trust this project? [y]es / [n]o / [a]lways remember
四个选项:
- y:这次信任,下次来还会再问
- n:这次不信任,下次来还会再问
- a:这次信任,并记住这个决定(写入
trust.json) - 直接关掉:等同于 n
如果你选了 a,pi 会在 ~/.pi/agent/trust.json 里记下这个目录的路径和你的决定。以后再来就自动跳过提示了。
Tip信任决策是按目录路径保存的,且会向上查找父目录。比如你对
/home/user/projects/stuff做了信任决定,进入它的子目录时这个决定也会生效。
defaultProjectTrust 三种策略
通过 settings.json 中的 defaultProjectTrust 可以控制全局默认行为:
{
"defaultProjectTrust": "ask"
}
三种可选值:
| 值 | 交互模式 | 非交互模式 |
|---|---|---|
"ask"(默认) | 弹出信任确认提示 | 不加载项目资源(等同于不信任) |
"always" | 自动信任 | 自动信任 |
"never" | 自动拒绝 | 自动拒绝 |
选哪个取决于你的使用场景。日常自己写代码用 "always" 没问题——反正项目都是你写的,没必要每次弹个确认。经常 clone 陌生仓库做代码审查的话,保持 "ask" 更安全。跑 CI 自动脚本可以设 "always" 加 -a 标记确保加载项目配置。
命令行覆盖
不想改 settings 的话,每次启动都可以用命令行参数临时覆盖:
# 这次信任项目
pi --approve
pi -a
# 这次不信任项目
pi --no-approve
pi -na
也可以在交互模式中用 /trust 命令随时保存对当前项目的信任决定:
/trust
Note
/trust保存的是决定,但不会重载当前会话。如果你改了主意,需要重启 pi 才生效。
非交互模式要特别注意
在 Print 模式(-p)、JSON 模式(--mode json)和 RPC 模式(--mode rpc)下,pi 不会弹任何 UI 提示。这时候的行为全靠 defaultProjectTrust:
- 设为
"ask"或"never":项目资源被静默忽略 - 设为
"always":项目资源被加载
如果你在脚本里用 -p 模式处理一个带着 .pi/ 配置的项目,而默认策略是 "ask",那这些配置就永远不会生效——可能你也完全不知道它没生效。
解决方式很简单:非交互模式下用 -a 或 -na 明确表态。
pi 为什么没有内置沙箱
这是很多新用户会问的问题。答案分两层。
第一层:技术原因
pi 的内置工具——read、write、edit、bash——运行在 pi 进程的权限上下文中。Extension 是 TypeScript 模块,加载进同一进程执行。Package 安装、shell 命令、LSP、测试运行器都是普通本地进程。
要在这个基础上加一层进程内沙箱,技术上极其困难,而且容易产生一种”我以为已经安全了”的错觉。
第二层:设计哲学
pi 的定位是 BYOK(自带密钥)的 CLI 编码代理,设计目标就是深度集成你的本地开发环境。一个真正可靠的隔离需要来自操作系统层面或虚拟化/容器边界,而不是在 Node.js 进程里自我欺骗。
你不妨这样理解:项目信任是门禁,OS 权限是围墙,容器是保险箱。门禁防止陌生仓库偷偷改你的配置;围墙决定进程能访问什么文件;保险箱把整个危险操作关进独立环境。三个是互补关系,不是一个能替代另一个。
Note多说一句:来自项目文件、注释、文档或构建输出的 prompt injection(提示词注入)属于本地代理的固有风险,pi 无法可靠阻止。在不信任的内容旁边工作时,容器化是更好的选择。
三种隔离方案怎么选
pi 的官方文档列出了三种隔离方案。每种隔离的对象不太一样:
| 方案 | pi 和凭据在哪 | 工具在哪执行 | 关键风险 |
|---|---|---|---|
| Docker 容器 | pi 和凭据都在容器内 | 内置工具、扩展都在容器内 | -v "$PWD:/workspace" 读写挂载仍会修改宿主文件;别挂载 ~/.pi/agent |
| Gondolin | pi 和凭据留在宿主机 | 七个内置工具和 ! 命令路由到微 VM | 自定义扩展的额外工具默认仍在宿主机执行 |
| OpenShell | 远端 gateway 控制 | 全部在 policy sandbox 内 | 依赖 gateway policy 配置;远端场景走 upload/download 而非 bind mount |
选哪种取决于你的具体场景:
- 审查陌生代码 → Docker 只读挂载
- CI/CD 自动化 → 临时凭据 + 最小文件集 + 网络限制
- 日常本地开发 → 信任你写的项目即可,大部分时候不需要容器
别忘了:绑定了读写(read-write)挂载的容器仍然能修改宿主文件。如果目标是”完全不让它碰到我的原项目”,用只读挂载,或者先把文件复制进沙箱、审查完 diff 再复制回来。
你应该注意什么
几个实战中最容易踩的坑:
第三方扩展可以执行任意代码。 Extension 是 TypeScript/JS 代码,加载进 pi 进程运行。安装之前翻翻源码,哪怕只是扫一眼,也比完全不看强。
第三方 Skill 可以指示模型做任何事。 Skill 是 Markdown 文件,但它描述的指令会被模型认真执行。一个恶意 Skill 完全可以让你运行 curl | bash。审核 SKILL.md 内容,别因为是”文本文件”就觉得无害。
别把敏感的 API Key 写在项目的 .pi/settings.json 里。 尤其是要推送到公开仓库或分享给团队的项目。全局 settings(~/.pi/agent/settings.json)才是放凭据的地方。
长时间无人值守时用容器。 如果你要 pi 通宵跑自动修复任务,把它放进一个只能用临时凭据、只挂载必需目录、网络受控的环境里。
审查输出再合并。 让 pi 干完活后,用 git diff 逐行看看它改了什么。这习惯不只在 pi 上好用,用任何 AI 编码工具都应该这样。
安全这个话题说穿了就是一句话:看清你的权限边界,知道 pi 能做什么,然后选择合适的方式去限制。pi 给了你项目信任、命令行覆盖、容器指南——工具都摆在台面上,怎么组合是你的事。
故障排查
非交互模式配置没生效? 检查 defaultProjectTrust 是不是 "ask",非交互模式下 "ask" 等同于不信任。试试加 -a 参数。
trust.json 里的决定不想要了? 直接编辑 ~/.pi/agent/trust.json 删掉对应条目。JSON 格式,走的是按目录路径匹配,不难手工修改。
容器里 pi 改了宿主文件? 检查 Docker 的 -v 挂载,确保用的是只读挂载或根本没有 bind mount 原目录。