代码 Agent 沙箱怎么做最小验收?我用 4 条命令先验 repo 只读、scratch 可写、默认无网
我在 Docker 28.5.2 上直接跑了 4 条命令,先验 代码 Agent 沙箱 最容易被讲空的 3 条底线:repo 只读、scratch 可写、默认无网。短答案是:这轮最小验收值得所有准备让代码 Agent 读仓库、跑测试、改文件的团队先做一遍;但如果你只是起了个容器,还没有把审批和日志留在控制面,那还不能算拿到了可上线的代码 Agent 沙箱。 OpenAI 刚在 Running Codex safely at OpenAI 里把这个边界讲得很直白:Codex 新闻稿说的是产品内部部署,文档里更通用的名字则是 Sandbox Agents 和 Guardrails and human review;前者是执行环境,后者是审批与控制面。
执行面先验清,治理面再放权。
这个边界和我们之前写过的 OpenAI Agents SDK 边界梳理 能直接对上;如果你在补更大的 Agent 基础设施,也可以顺手对照 infra 主题页 和那篇 Cloudflare 内部 AI 工程栈拆解:真正要补的不是一个新名词,而是边界和审查链路。
这轮代码 Agent 沙箱最小复现:4 条命令
环境标签:Docker 28.5.2 + Alpine + 本机目录挂载。
docker run --name codexsmoke_ro_1201 --network none \
-v /Users/fuuqiu/clawd/automation/ghost/ops/codex-sandbox-smoke/repo:/workspace:ro \
alpine touch /workspace/WRITE.txt
docker run --name codexsmoke_scratch_1201 --network none \
-v /Users/fuuqiu/clawd/automation/ghost/ops/codex-sandbox-smoke/repo:/workspace:ro \
-v /Users/fuuqiu/clawd/automation/ghost/ops/codex-sandbox-smoke/scratch:/scratch \
alpine touch /scratch/out.txt
docker run --name codexsmoke_netnone_1201 --network none \
alpine wget -O- https://example.com
docker run --name codexsmoke_netok_1201 \
alpine wget -O- https://example.com
对应输出也很直接:
- repo 只读写入失败:
touch: /workspace/WRITE.txt: Read-only file system - scratch 写入成功:容器退出码
0 - 默认无网:
wget: bad address 'example.com' - bridge 网络放开后:
wget能正常拿回Example Domain
如果你要做一轮最便宜的 代码 Agent 沙箱 smoke test,这 4 条命令已经足够回答第一层问题:你的执行边界到底是靠参数真收紧了,还是还停留在“默认希望 Agent 不会乱来”。
第一步:先验 repo 是不是真的只读
执行:
docker run --name codexsmoke_ro_1201 --network none \
-v /Users/fuuqiu/clawd/automation/ghost/ops/codex-sandbox-smoke/repo:/workspace:ro \
alpine touch /workspace/WRITE.txt
通过信号:
touch: /workspace/WRITE.txt: Read-only file system
失败时说明什么:
- 如果这条命令执行成功,你的 repo 默认就是可写的
- 这意味着 Agent 第一轮就能直接改源码、脚本、配置和 hooks
- 这种基线不适合直接进入真实仓库读写链路
为什么这一步要排第一?因为只要源码目录一开始就可写,后面再讲“先观察再执行”“让 reviewer 再看一眼”,往往都会退化成事后补救。对已经在让 Agent 批量产出补丁或 PR 的团队,这个风险和我们那篇 reviewer 证据链 讨论的是同一件事:不是先追求更快提交,而是先证明边界没塌。
第二步:再验 scratch 有没有被单独留出来
执行:
docker run --name codexsmoke_scratch_1201 --network none \
-v /Users/fuuqiu/clawd/automation/ghost/ops/codex-sandbox-smoke/repo:/workspace:ro \
-v /Users/fuuqiu/clawd/automation/ghost/ops/codex-sandbox-smoke/scratch:/scratch \
alpine touch /scratch/out.txt
通过信号:
- 容器退出码是
0 docker inspect codexsmoke_scratch_1201里能看到/workspace是rw=False- 同一份 inspect 里
/scratch是rw=True
失败时说明什么:
- 如果 scratch 也不可写,Agent 很难保存 patch、日志、截图、临时报告
- 如果 repo 和 scratch 混成同一个可写挂载,Agent 又会重新拿回对源码目录的直接改写权
这一步的目标不是让 Agent 完全不能写,而是把“写哪儿”这件事先收紧。更稳的基线不是“一刀切全只读”,而是 repo 只读,scratch 可写。
第三步:把默认网络改成先关后开
执行:
docker run --name codexsmoke_netnone_1201 --network none \
alpine wget -O- https://example.com
通过信号:
wget: bad address 'example.com'
对照命令:
docker run --name codexsmoke_netok_1201 \
alpine wget -O- https://example.com
对照输出:
<!doctype html><html lang="en"><head><title>Example Domain</title>...
失败时说明什么:
- 如果
--network none这条还能直接出网,你的隔离层根本没有按预期收口 - 如果你平时默认就是 bridge 网络,那很多本来该挂到审批或 allowlist 的外连,第一天就已经放过去了
对 代码 Agent 沙箱 来说,默认 bridge 网络不是“中立配置”,而是已经替 Agent 开了一层外连能力。先关后开,比先全开再补审批更容易解释,也更容易审计。
第四步:用 inspect 把“看起来像隔离”变成“配置上真隔离”
执行:
docker inspect codexsmoke_ro_1201
docker inspect codexsmoke_scratch_1201
docker inspect codexsmoke_netnone_1201
我这轮看到的关键状态是:
codexsmoke_ro_1201:/workspace挂载rw=False,NetworkMode=nonecodexsmoke_scratch_1201:/workspace只读、/scratch可写,NetworkMode=nonecodexsmoke_netnone_1201:退出码1,NetworkMode=nonecodexsmoke_netok_1201:退出码0,NetworkMode=bridge
通过信号:配置结果和命令意图一致。
失败时说明什么:如果运行输出和 inspect 结果对不上,优先信配置层。因为很多“看起来没写进去”“好像没联网”只是偶然结果,不能拿来当正式基线。
代码 Agent 沙箱上线前,最小顺序应该怎么排
如果你下周就要在团队里试点,我建议直接照这个顺序走:
-
把 repo 先挂成只读
通过:直接写入报只读错误;失败:源码目录还能被容器写。 -
给 Agent 单独留一个 scratch 目录或工作卷
通过:产物能落到 scratch;失败:要么哪儿都不能写,要么源码目录也跟着被放开。 -
默认网络收紧
通过:无网容器不能直接拉外部页面;失败:默认外连已放开。 -
把越界动作接到审批层
通过:改写 repo、出网、敏感命令会产生审批事件;失败:所有风险动作都靠容器内部脚本兜底。 -
把日志、diff 和产物接回 review 流程
通过:reviewer 能看见 Agent 做了什么;失败:只剩一个“任务完成”的结果,没有过程证据。
前 3 步是这轮已经实测过的;后 2 步则是 OpenAI 这次讲 Codex 安全时最值得拿回去补的地方。OpenAI 的原话不是“沙箱解决一切”,而是 approvals and sandboxing work together。如果你的 rollout 只做到了前 3 步,那它更像一个合格的执行面基线,还不是完整治理面。
这篇 tutorial 没覆盖到什么
这轮本机实验没有验证 3 件事,所以别把结论说大:
- 没有验证审批工作流本身:这需要控制面或 harness,不是 Docker 参数自己能证明
- 没有验证审计日志链路:我只验证了执行边界,没有验证谁批准了什么、为什么批准
- 没有验证真实代码变更回写流程:这篇教程故意把 repo 保持在只读基线,没有继续演示 patch 回写
所以这篇文章能支撑的判断很收敛:代码 Agent 沙箱 的第一层基线,完全可以先用只读挂载、scratch、默认无网和 inspect 校验跑通;但如果要把它推进生产,审批和日志还得回到控制面去补。
结论
如果你们现在正准备让 Agent 真读仓库、真跑命令、真碰配置,我会建议把这轮 代码 Agent 沙箱 最小验收排到很前面。它的价值不在于“又加了一层容器”,而在于你终于能用明确的通过/失败信号回答 4 个问题:repo 能不能直接写、临时产物写到哪、默认能不能出网、配置层到底有没有真的收紧。
而 OpenAI 这次把 Codex 安全边界讲透后的最大提醒,也不是“Codex 很安全”,而是执行面和治理面要拆开验。先把这 4 个本地检查做扎实,再谈自动化放权,顺序通常会更稳。
来源
- OpenAI News: Running Codex safely at OpenAI
- OpenAI API Docs: Sandbox Agents
- OpenAI API Docs: Guardrails and human review