Skip to content

第 18 章 · 安全模型与环境变量

本章目标:建立对 pi 威胁模型的正确认知——它"信任本地用户、不信任仓库内容",学会用项目信任机制、容器隔离与环境变量管理把风险压到可接受范围。

18.1 威胁模型:本地信任边界

官方 security 文档开宗明义:pi 以启动它的用户账号的全部权限运行,该用户可写的文件都在同一本地信任边界内。这意味着三类典型风险:

  1. 提示注入(Prompt Injection)——仓库里的 README、代码注释、构建输出都可能包含"指令",被模型读进上下文后诱导它执行危险操作。官方原话:这是本地 agent 的预期风险,pi 无法可靠阻止;
  2. 恶意仓库——clone 下来的项目可能带 .pi/settings.json、恶意扩展或技能,在你不知情时改变 pi 行为;
  3. 命令执行——bash 工具以你的身份跑任意命令,没有内置确认弹窗(Philosophy 明确 "No permission popups")。

对应的防线是三层的:项目信任(输入加载闸门)→ 工具开关(行为约束)→ 容器隔离(真正的边界)。上一章讲的工具开关只是第二层,本章讲一三两层。

18.2 项目信任机制(Project Trust)

项目信任决定"pi 是否加载这个项目自带的配置与扩展"。当 pi 在项目里发现以下任一内容时,就认为该项目"含有需要信任的资源":

  • .pi/settings.json
  • .pi/extensions.pi/skills.pi/prompts.pi/themes
  • .pi/SYSTEM.md.pi/APPEND_SYSTEM.md
  • 当前目录或祖先目录的项目级 .agents/skills

裸 .pi 目录不算

只有一个空的 .pi 目录不触发信任确认——判断依据是上面列出的具体资源。

信任决定保存在 ~/.pi/agent/trust.json(按目录记录),最近的祖先目录决定优先于全局默认值。交互模式下会弹出询问;非交互模式(-p/json/rpc)不询问,回退到全局设置 defaultProjectTrust

取值非交互行为
"ask"(默认)忽略需信任的项目资源
"never"忽略需信任的项目资源
"always"信任并加载

单次运行可用 -a/--approve 强制信任、-na/--no-approve 强制忽略:

bash
# CI 中信任自家仓库的项目配置(确认仓库可信时)
pi -a -p "运行项目自带的检查"

# 审计陌生仓库:忽略其全部项目资源 + 只读工具
pi -na -t read,grep,find,ls -p "这个项目是干什么的?"

关键认知:信任只是输入加载闸门。它防止仓库在你批准前悄悄改掉 pi 的设置和扩展,但不会让不可信代码、提示注入或模型输出变得安全。

18.3 没有内置沙箱:隔离要靠操作系统

pi 故意不提供内置沙箱(Philosophy 与 security 文档双重确认)。理由是:进程内沙箱仍依赖宿主 shell、文件系统、包管理器、凭据和扩展代码,容易被误解为安全边界。真正的隔离必须来自操作系统或虚拟化边界。

对不可信仓库、无人值守任务,官方给出的容器化清单(详见第 19 章):

bash
# 只挂载工作区,不挂载宿主 ~/.pi/agent(避免暴露会话与凭据)
docker run --rm -it \
  -e ANTHROPIC_API_KEY \
  -v "$PWD:/workspace" \
  -v pi-agent-home:/root/.pi/agent \
  pi-sandbox

要点:只挂载任务需要的路径;传最少的 API key 或用短生命周期凭据;任务不需要网络时限制网络;结果拷回可信环境前先审查 diff。若以读写方式 bind-mount 宿主目录,容器内的写操作仍会落到宿主文件——需要更强保护时用只读挂载或拷入拷出。

18.4 API Key 与敏感凭据的存放

  • provider 凭据放环境变量或 pi 的 auth 文件/login 管理),不要写进 shell 历史或仓库;
  • --api-key 参数会出现在进程列表(ps)中,只适合临时调试;
  • 容器场景:用 -e KEY 从宿主注入,或像 OpenShell 那样把原始 key 留在网关上游、容器内只访问 https://inference.local 推理路由。

18.5 环境变量完整参考

pi 的环境变量分三类(官方 environment-variables.md):

① pi 自身配置

变量作用
PI_CODING_AGENT_DIR覆盖配置目录(默认 ~/.pi/agent
PI_CODING_AGENT_SESSION_DIR覆盖会话存储目录(--session-dir 优先)
PI_PACKAGE_DIR覆盖包目录(Nix/Guix 场景)
PI_OFFLINE关闭启动期网络操作(更新检查、遥测)
PI_SKIP_VERSION_CHECK跳过 pi.dev 版本检查
PI_TELEMETRY0/false/no 关闭安装/更新遥测
PI_CACHE_RETENTION设为 long 启用扩展提示缓存(Anthropic 1h / OpenAI 24h)
HTTP_PROXY / HTTPS_PROXY出站代理

② 进程标记(CLI 与 RPC 入口自动设置,供子进程识别)

变量作用
AI_AGENT=pi通用标记
PI_CODING_AGENT=truepi 专属标记

③ bash 工具会话环境(注入给模型调用的 bash 命令;注意 !/!! 用户命令不会注入)

变量作用
PI_SESSION_ID当前会话 ID
PI_SESSION_FILE当前会话 JSONL 绝对路径(临时会话未设置)
PI_PROVIDER / PI_MODEL当前模型提供方/ID
PI_REASONING_LEVEL当前思考级别
bash
# 模型自己就能这样自检,而不是靠猜系统提示词
printf '%s/%s\n' "$PI_PROVIDER" "$PI_MODEL"

自定义 bash 工具可通过 createBashTool()exposeSessionEnvironment: false 关闭注入,避免嵌套 pi 进程拿到过期的父会话信息。

18.6 本章小结

  • 威胁模型:信任本地用户、不信任仓库内容,提示注入是预期的本地风险;
  • 项目信任只管"要不要加载项目资源",判定物是 .pi/ 下具体资源与项目级 .agents/skills
  • 非交互模式靠 defaultProjectTrust-a/-na 单次覆盖;
  • 无内置沙箱是设计决定:真隔离用容器/微 VM,只挂工作区、最小凭据、按需限网;
  • 环境变量三类:pi 配置(PI_OFFLINE 等)、进程标记(AI_AGENT)、bash 会话环境(PI_SESSION_ID 等)。

🧪 随堂测验

点击你认为正确的选项。答错时会展示正确答案与原因解析。

1. 下列哪一项不会触发项目信任确认?

2. 非交互模式下 defaultProjectTrust 取默认值 "ask" 时,项目资源会被?

3. 为什么官方不建议用进程内沙箱替代容器隔离?

4. 关于 bash 工具的会话环境变量,下列说法正确的是?

🛠️ 动手实践

  1. 在一个测试仓库里创建 .pi/SYSTEM.md,分别在交互模式、-p 模式、-na -p 模式下启动 pi,观察三种模式下该文件是否被加载。
  2. 用 Docker 把 pi 跑进容器:只挂载工作区、使用命名卷存 ~/.pi/agent,验证容器内无法读到宿主会话。
  3. 写一个脚本打印 bash 工具会话环境:让 pi 执行 env | grep ^PI_,对照文档核对每个变量的值与含义。