pstack 的安全实践:为什么 Agent 子进程不该继承整个环境变量
【免费下载链接】pstack-claudeClaude Code, Codex, Copilot, Pi, OpenCode, Gemini, and Prime Agent versions of Poteto's pstack. Rigorous agent workflows with Cursor primitives translated for other harnesses.项目地址: https://gitcode.com/GitHub_Trending/ps/pstack-claude
pstack 是面向 Claude Code、Codex、Copilot 和 Pi 等 AI 编程助手的严谨 Agent 工作流插件。它的一个容易被忽略的安全细节是:启动子进程时,刻意不把整个环境变量原样交给子进程——因为你的 shell 里通常躺着 API Key、Token 等凭据,少传一个变量,就少一分泄密面。
先看风险:环境变量是"隐形行李箱"
在终端里,环境变量会像行李箱一样被"整箱搬运"给所有子进程。里面除了PATH这类无害内容,往往还有:
- 🗝️ 各家大模型的 API Key(如
ANTHROPIC_API_KEY) - 🎫 版本平台的访问 Token(如
GH_TOKEN) - 📍 指向私有配置目录的路径变量
对 AI Agent 来说风险被放大:Agent 会自动运行命令、派生子 Agent。如果每个子进程都默认拿到"完整行李箱",一旦某个子命令把环境打印出来(env、调试日志),凭据就可能进入 Agent 的上下文,甚至被写进提交记录。
pstack 的安全范围声明里也明确把"让 Agent 泄密或执行用户未授权的命令"视为漏洞范畴,见 SECURITY.md。
实践一:跨进程传值走命令行参数,不走环境变量
pstack 的 Pi 扩展要启动子 Agent 时,需要告诉子 Agent"你是第几层"(用于限制 Agent 嵌套深度)。早期版本的做法是复制一份完整环境变量、塞进一个PSTACK_PI_DEPTH变量再交给子进程——这是插件里"最后一处"向子进程递出整包环境的位置。
新版本的做法更干净:子进程原样继承平台默认环境,深度值改用--pstack-depth命令行标志传递。父进程没有多复制一份环境,子进程也没有"偷偷多装"一个变量,深度限制和行为完全不变。
相关改动记录见 CHANGES.md。这个原则值得记下来:能用参数说清楚的事,不要靠环境变量捎带。
实践二:测试子进程只拿 PATH 和必需变量
看 pstack 的测试代码会更直观。测试里启动的子进程一律只给最小环境:
- 例如 tests/pre-tool-use.test.mjs 中,子进程环境只有
PATH加上测试显式设置的变量; - 又如 orch.test.ts 中,子进程只拿到
PATH和一个测试专用的存储目录变量。
这样做有两个好处:
- 凭据不流入测试子进程,即使测试失败打印了环境,也不会带上你的 API Key;
- 结果可复现:测试行为不受你本地 shell 配置(比如颜色、代理变量)影响。
配套地,插件目录曾把$PWD当作"凭据类变量名"处理过——因为插件市场的安全校验会把指向远程仓库的凭据类变量视为风险。pstack 索性在仓库里彻底避开了这类写法(见 CHANGES.md),连"被误伤"的机会都消除了。
实践三:Pi 子 Agent 不继承父级的敏感命令行标志
pstack 在 Pi 上运行子 Agent 时,每个子 Agent 是独立的pi --mode rpc进程,由 plugins/pstack/pi/child.ts 管理其生命周期。值得注意的是:子进程不会继承父进程的一次性命令行标志,例如-e(扩展加载)、--api-key(内联密钥)等。
也就是说,如果你只是临时用--api-key启动了父会话,子 Agent 不会把这个密钥"继承"走;子 Agent 只读取磁盘上自己保存的包和配置。密钥停留在该出现的进程里,不会顺着进程树层层扩散。这条设计说明记录在 pi-tools.md。
小结:三条可以直接抄走的经验
| 经验 | pstack 的做法 | 适用场景 |
|---|---|---|
| 参数传值优先 | 深度值走--pstack-depth标志,不再复制整包环境 | 自研插件、CLI 工具 |
| 最小化子进程环境 | 测试子进程只给PATH+ 显式变量 | 任何会启动子进程的代码 |
| 敏感标志不下传 | 子 Agent 不继承--api-key等一次性标志 | 多进程架构 |
核心思想一句话:子进程该知道什么,就精确给什么;宁可显式,不要"顺手全继承"。对于正在写 AI Agent 工具或自动化脚本的新手来说,这比任何一行代码都重要——你的环境变量里装着钥匙,别把它挂在每个子进程的门口。
更多背景可参考 docs/reference.md 与 CHANGES.md 中关于凭据处理的完整演进记录。
【免费下载链接】pstack-claudeClaude Code, Codex, Copilot, Pi, OpenCode, Gemini, and Prime Agent versions of Poteto's pstack. Rigorous agent workflows with Cursor primitives translated for other harnesses.项目地址: https://gitcode.com/GitHub_Trending/ps/pstack-claude
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考