ProductsMulti-sourceSelected70°

OpenAI 给 Codex 在 Windows 造沙箱,过程比想象中曲折

Why we picked it

Windows 开发者终于有了正经的本地 AI 编程沙箱——Codex 团队用四层架构解决了 OS 级隔离难题,做安全或工具链的值得点开学习设计思路。

OpenAI Codex 团队为了解决 Windows 上缺乏类似 macOS Seatbelt 或 Linux seccomp 的进程级沙箱能力,经历了两轮方案迭代。

Body

最初尝试免提权沙箱,通过合成 SID 和 Write-Restricted Token 实现文件写入限制,但网络限制只能靠环境变量软封锁,无法对抗恶意代码。最终不得不接受提权方案,引入两个本地沙箱用户和防火墙规则,并设计四层架构(codex.

exe、setup、runner、子进程)来安全执行受限命令。该方案已落地,为 Windows 上的 Codex 用户提供了与 macOS/Linux 一致的默认安全体验。

Original · shao__meng

OpenAI 给 Codex 在 Windows 造了一个沙箱,过程比想象中曲折 ...

来自 Codex 团队 David Wiesen 非常有深度的技术博客,推荐阅读! https://t.co/TL7eUHRut7

问题的起点:Windows 上的 Codex 没有沙箱 Codex 运行在开发者本地(CLI / IDE 扩展 / App),默认以当前用户身份执行命令——既能读写文件、跑测试、操作 Git,也意味着潜在风险。

macOS 有 Seatbelt,Linux 有 seccomp/bubblewrap,Windows 原生缺乏这种"按进程做强约束"的能力。结果 Windows 用户只能在两个糟糕方案中二选一: · 每条命令都审批(甚至读操作),打断流畅性; · 开启 Full Access,放弃所有约束。

团队的目标,是把 Codex 在 macOS/Linux 已有的"默认安全"体验搬到 Windows:只能在工作区内写、默认无网络访问,且全程不需要用户介入。

现成 Windows 方案为什么都不够用? · AppContainer:是为"功能边界清晰的应用"设计的;Codex 要驱动 shell、Git、Python、构建工具等任意二进制,形状不对 · Windows Sandbox:它是隔离的"另一个桌面",无法直接作用于用户的真实仓库;且 Windows Home 版根本没有 · Mandatory Integrity Control:把工作区标成 Low,等于让所有 Low 进程都能写入,宿主信任模型被破坏,副作用太大

第一版原型:「免提权沙箱」(Unelevated Sandbox) 设计原则:不弹 UAC、不要求管理员。需要解决两件事:限制文件写入 + 限制网络。

1. 文件写入:靠 SID + Write-Restricted Token 真正落地 · 合成 SID:Windows 允许创建一个不绑定真实用户、却能出现在 ACL 中的身份。Codex 为此造了一个专属的 sandbox-write SID。 · Write-Restricted Token:一种特殊进程令牌,写操作要双重放行——token 的真实用户身份有权限; token 的"受限 SID 列表"中至少一个 SID 也被授权。

把 sandbox-write SID 通过 ACL 授予: · 当前工作目录 · config.toml 里配置的 writable_roots

并显式拒绝其写入 .git / .codex / .agents。 → 这是真正的 OS 级写边界。

2. 网络访问:只能"劝退",无法强制 Windows Firewall 必须管理员权限,于是只能做环境层面的软封锁: HTTPS_PROXY / ALL_PROXY / GIT_HTTPS_PROXY = http://127.0.0.1:9 GIT_SSH_COMMAND = cmd /c exit 1 外加在 PATH 前塞 denybin,让假的 ssh/scp 先被解析到。

效果:拦得住行为良好的工具;但凡自己实现网络栈、绕过 PATH、或直接开 socket 的程序——一律失效。仅是 advisory,挡不住对抗性代码。

改版关键:为什么必须接受"需要提权" 要让 Windows Firewall 真正生效,必须按"身份"匹配规则。但: · 防火墙规则不能匹配 restricted token 中的合成 SID; · 按 codex.exe 路径匹配,覆盖不到它派生的 Git/Python 等子进程; · 按用户匹配又会误伤真实用户本人; · 按端口/地址匹配是错的策略——目标不是封 443,而是封这一棵受限进程树的所有出站流量。

唯一的出路:让沙箱命令以"另一个 Windows 用户"的身份运行。这就必须放弃"免提权"约束。

最终方案:「提权沙箱」(Elevated Sandbox)

1. 引入两个本地用户 Codex 在安装时创建: · CodexSandboxOffline —— 防火墙规则全封; · CodexSandboxOnline —— 不被防火墙规则覆盖。 子进程依旧跑在带 [Everyone, Logon, Synthetic] 受限 SID 列表的 write-restricted token 下,但 token 的主体(principal)换成了沙箱用户,而不是真实用户。

5.2 一次性 setup 步骤(需要管理员) · 创建合成 SID; · 创建在线 / 离线沙箱用户; · 凭据用 DPAPI 加密存储,沙箱用户自己读不到; · 为 CodexSandboxOffline 创建"封禁所有出站"的防火墙规则; · 给沙箱用户补 读 ACL——因为新用户默认读不到其他用户的 profile、C:\Users、C:\Program Files 等常用目录。这一步耗时,异步执行,不阻塞用户。

5.3 为什么需要 codex-command-runner.exe 直觉的流程是: codex.exe → LogonUserW → CreateRestrictedToken → CreateProcessAsUserW(child) 但在 CreateProcessAsUserW 这一步存在特权墙:以"真实用户"身份是无法可靠地把进程以另一个用户的受限 token 拉起来的。

解法是把流程切成两段: Part 1(在真实用户侧) · codex.exe 用 CreateProcessWithLogonW 把 codex-command-runner.exe 以沙箱用户身份拉起(此时还不是受限 token)。 Part 2(已经在沙箱用户侧) · runner 用 OpenProcessToken 拿到自己的 token; · GetTokenInformation 取出 logon SID; · CreateRestrictedToken 构造最终受限 token; · CreateProcessAsUserW 拉起真正的子进程。

5.4 最终四层架构 · codex.exe —— 普通非提权的 harness; · codex-windows-sandbox-setup.exe —— 一次性的提权安装; · codex-command-runner.exe —— 在沙箱用户内造受限 token 并起子进程; · child process —— 真正受约束的命令。

拆成独立二进制的好处:codex.exe 在其他平台不被 Windows 专属逻辑污染;UAC 边界只在必要时跨越;setup 的长耗时与主进程生命周期解耦。

Industry Coordinates & Source Verification

This report is categorized under AITOP's "Products" desk, focusing on US frontier AI labs and Silicon Valley technology leaders. Within our cross-regional analytical framework, it directly maps to AI developer toolchains, coding agents, and engineering workflows. Key entities and technical topics under continuous tracking include Codex, Windows 沙箱, 安全隔离, AI 编程助手.

Source attribution: curated from shao__meng (@shao__meng). Cross-source corroboration: 11 independent sources have covered this development (including OpenAI Blog, Greg Brockman, 向阳乔木), confirming industry-wide signal strength.