从执行记录推导编程 Agent 沙箱权限
文章提出利用 Claude Code、Codex 的历史会话,推导沙箱需要放行的网络与文件访问权限。实现难点包括解析复杂 Shell 命令,以及识别包管理器等工具隐含的联网和缓存行为。
AI 深度解读
编码 Agent 的沙箱难落地,卡住人的往往不是安全原理,而是白名单怎么填:npm 要联网,开发服务器要监听端口,缓存还得写到项目外。权限收紧后命令接连失败,用户很容易直接关掉沙箱。
作者做了 sandfit,尝试从历史会话反推权限,再预测启用沙箱后哪些命令会坏。它值得关注的地方,是把权限配置变成可解释、可测试的工程流程;但文中的漂亮数字来自示例数据,不能直接当成普通团队的效果承诺。
白名单为什么可以从历史命令里找
原文列出的入口包括 Claude Code 的 /sandbox、Codex 的 workspace-write,以及 sandbox-runtime、nono。作者把它们概括为默认拒绝,再按白名单放行。
困难在于,你很难提前列全项目需要访问的网站和目录。npm install 要访问包源,pip 要写缓存,git push 可能需要读取 SSH 密钥。一次次补权限,最后容易变成允许访问整个家目录,失去收紧权限的意义。
sandfit 的输入是已有会话:Claude Code 保存在 ~/.claude/projects,Codex 保存在 ~/.codex/sessions。这些记录包含 Agent 执行过的命令,可以作为推导权限需求的材料。
但历史里出现 npm install,并不等于记录里已经列出了 registry.npmjs.org 和 ~/.npm。从命令到权限,中间还需要解释工具行为。
作者强调了三件事:
- 用真正的 shell 解析器处理管道、重定向、heredoc、目录切换,以及
bash -c、sudo、env、timeout、xargs、npx、python -m等包装调用。 - 理解工具的隐式行为,例如
cargo build访问什么主机、uv把缓存放在哪里、哪些pnpm子命令会启动服务器。 - 控制规则扩张的范围。缓存需求只放行缓存目录;
gh、docker、通过 SSH 执行的git push等凭据相关操作,按作者的方案放到沙箱外运行。
历史命令是生成权限策略的线索,不能直接成为授权依据。
「零失败」是怎么测出来的
sandfit 会分别按当前沙箱配置和建议策略回放历史,预测哪些命令会失败。为避免策略只适配已经见过的命令,它用较早的记录生成规则,把最新的 20% 留作测试。
下面是原文提供的一周 Next.js 示例,保留完整输出,方便看清统计口径:
If you turn on the sandbox today
███████░░░░░░░░░░░░░░░░░░░ 28% of your shell commands would break (69 of 243)
With the sandfit policy
░░░░░░░░░░░░░░░░░░░░░░░░ 0% would break (0 of 49 commands from your newest 20% of history, which the policy never saw)
2 commands that read secrets are blocked on purpose
Manual approvals you would no longer need: 24 of 35
要看的是 0 of 49 那一行:它测试的是预留历史,不是未来真实工作;前后的分母也不同,不能把 28% 到 0% 当成同一组命令的直接对照。
这份数据随仓库的 demo/ 目录提供,作者明确称其为 sample data。它能演示方法,但不能证明不同项目都会得到零失败结果。另外,输出还单列了 2 条故意拦截的读取秘密命令,不能把零失败理解成所有操作都获准。
能写哪些文件,比能写多少更关键
原文引用了一组安全事件:作者称,Pillar Security 在 2026 年 7 月针对 Cursor、OpenAI Codex、Gemini CLI 和 Antigravity 展示了绕过沙箱边界的攻击。路径不是破坏隔离机制,而是修改文件,等沙箱外的可信工具随后读取并执行。
这里需要分清:这些事件是作者援引的材料,不是 sandfit 的测试结果,本文也未独立核验。
它提出的权限判断很实用:项目目录内的文件也可能成为执行入口。因此,即使历史命令需要,策略仍应禁止写入 git hooks、.git/config、~/.zshrc、~/.bashrc、.mcp.json、.vscode 下的任务配置,以及 Agent 自己的设置。
读取限制则覆盖 ~/.ssh、~/.aws、~/.npmrc 和 .env 文件。作者还引用了 2026 年针对 Cline GitHub 分诊机器人的提示注入事件,说明发布凭据泄露的后果。
预测也需要接受真实隔离环境的检验。作者称,他们在 sandbox-runtime 中运行正常需求和攻击探针:Linux 使用 bubblewrap,macOS 使用 Seatbelt,再对比实际结果与预测。
测试曾发现 srt 配置漏掉 allowLocalBinding,导致 macOS 开发服务器失败;也发现 mv build.zip ~/Downloads/ 被推导成允许写入整个 ~/Downloads。Linux 与 macOS 对本地端口绑定的行为还有差异。作者称这些问题已修复,并纳入双平台 CI。
我的判断
我认可的是「先预测、再解释、最后用真实沙箱验证」这套流程。相较于手写白名单,它有机会减少遗漏;相较于直接放开家目录,它给权限范围留下了审查依据。
但作者没有提供与人工配置的对照数据,也没有给出多个真实团队的长期结果。减少审批、降低维护成本,目前仍主要是示例和作者经验支持的判断。
历史还有天然盲区:新依赖、新部署目标和偶尔运行的脚本,可能根本没出现过。历史里已有的不安全操作,也不该因为重复发生就获得许可。对于需要 .env 才能启动的项目,禁止读取还要求团队调整配置注入方式,原文没有展开这部分成本。
更适合把 sandfit 当成权限草案生成器和验证工具,而不是自动授权器。
能拿来做什么
- 先在常用项目中运行只读预测,检查被阻断的到底是包源、缓存目录还是端口需求,避免一遇到失败就扩大到整个家目录。
- 用规则解释审查每项授权,特别检查 npm、pnpm 缓存是否被放大成家目录权限,以及凭据相关命令是否应该在沙箱外单独执行。
- 按原文的顺序试用下面三个入口,再用项目的安装、构建和开发服务器流程验证结果:
npx sandfit # read-only: what breaks today, what breaks with the policy
npx sandfit explain # why each rule is there
npx sandfit apply # write it (asks first, keeps a backup)
要注意最后一行:apply 会写入配置,原文称它会先询问并保留备份;前两步才用于查看预测和规则来源。