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

TL;DR · AI 摘要
OpenAI 为 Windows 上的 Codex 构建了基于双用户模型和受限令牌的沙箱系统,解决了原生安全机制缺失问题,实现默认安全执行环境。
核心要点
- 通过创建 CodexSandboxOffline/Online 两个本地用户,结合防火墙规则实现网络隔离。
- 使用合成 SID 和 Write-Restricted Token 实现文件写入的 OS 级控制,仅允许工作区目录写入。
- 引入 codex-command-runner.exe 绕过 CreateProcessAsUserW 的权限限制,完成受限进程链启动。
结构提纲
按章节快速跳转。
Windows 原生无类似 macOS Seatbelt 或 Linux seccomp 的机制,导致 Codex 难以实现默认安全执行。
AppContainer、Windows Sandbox 和 Mandatory Integrity Control 均因设计目标不匹配而无法满足通用命令执行需求。
利用合成 SID 和 Write-Restricted Token 成功限制文件写入,但网络封锁只能依赖环境变量,防护力弱。
发现防火墙规则无法基于受限令牌中的合成 SID 匹配,唯一可行路径是切换到独立用户身份运行沙箱进程。
由 codex.exe、setup 工具、command runner 和子进程构成四层结构,兼顾安全性与工程解耦。
command runner 在沙箱用户上下文中创建受限令牌并启动真实命令,绕过了跨用户受限进程创建的技术障碍。
思维导图
用一张图看清主题之间的关系。
查看大纲文本(无障碍 / 无 JS 友好)
- Codex Windows 沙箱设计
- 问题挑战
- 无原生进程沙箱
- 现有机制不适用
- 技术方案
- 合成 SID + 写受限令牌
- 双沙箱用户模型
- 四层进程架构
- 核心突破
- runner 绕过权限墙
- DPAPI 加密凭据存储
- 异步 ACL 补全
金句 / Highlights
值得收藏与分享的关键句。
把 sandbox-write SID 通过 ACL 授予当前工作目录和 writable_roots,并显式拒绝其写入 .git / .codex / .agents。
防火墙规则不能匹配 restricted token 中的合成 SID;按路径或用户匹配都会误伤,最终选择以沙箱用户身份运行进程。
拆成独立二进制的好处:codex.exe 在其他平台不被 Windows 专属逻辑污染;UAC 边界只在必要时跨越。
来自 Codex 团队 David Wiesen 非常有深度的技术博客,推荐阅读! https://t.co/S8KFYc8Pjt
问题的起点:Windows 上的 Codex 没有沙箱 Codex 运行在开发者本地(CLI / IDE 扩展 / https://t.co/8zr7NVhjFS" / X
OpenAI 给 Codex 在 Windows 造了一个沙箱,过程比想象中曲折 ... 来自 Codex 团队 David Wiesen 非常有深度的技术博客,推荐阅读! openai.com/index/building问题的起点: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 的长耗时与主进程生命周期解耦。
Quote
Tibo
@thsottiaux
10h
We are continuing to invest in making agents work better on Windows. Highly recommend reading David's engineering post on our unique approach to windows sandboxing for Codex: openai.com/index/building