日期:2026-07-30
环境:Windows 11、Codex Desktop、PowerShell 7.6.4、Windows 原生沙盒
关键词:Codex、Windows Sandbox、PowerShell、MSIX、CreateProcessAsUserW

背景

在 Windows 上使用 Codex Desktop 时,我发现任何需要调用 PowerShell 的普通沙盒命令都会在启动阶段失败。即使只是执行下面这种完全只读的命令,也无法运行:

Get-Location

错误信息是:

windows sandbox: CreateProcessAsUserW failed: 5 (拒绝访问。)

但同一条命令在获准使用非沙盒执行后可以正常运行。这说明问题不是 PowerShell 命令本身,而是发生在 Codex 创建沙盒进程的阶段。

这篇文章记录了从发现问题、走入 ACL 误区、构造对照实验,到最终通过更换 PowerShell 安装类型解决问题的完整过程。

最初的现象

第一次测试时,Codex 沙盒尝试启动的是:

C:\Users\<用户名>\AppData\Local\Microsoft\WindowsApps\pwsh.exe

系统在 CreateProcessAsUserW 阶段直接返回错误 5:

CreateProcessAsUserW failed: 5

对照测试的结果如下:

测试结果
沙盒内执行 PowerShell失败
非沙盒执行 PowerShell成功
工作区文件写入工具成功
PowerShell 版本7.6.4
工作目录正确

初步可以判断:

  1. Codex 本身仍可工作;
  2. 工作区权限不是完全损坏;
  3. 故障集中在 Windows 沙盒创建 PowerShell 子进程的路径上。

第一个误区:怀疑 WindowsApps 别名 ACL

C:\Users\<用户名>\AppData\Local\Microsoft\WindowsApps\pwsh.exe 是一个 App Execution Alias,而不是普通可执行文件。检查发现,该文件最初只显式允许当前用户、管理员和 SYSTEM 访问,没有出现 CodexSandboxUsers

当时很自然地怀疑:沙盒组是否因为缺少别名执行权限而被拒绝?

于是先后尝试给别名和父目录补充最小权限:

icacls "$env:LOCALAPPDATA\Microsoft\WindowsApps\pwsh.exe" `
  /grant "1INXU\CodexSandboxUsers:(RX)"

icacls "$env:LOCALAPPDATA\Microsoft\WindowsApps" `
  /grant "1INXU\CodexSandboxUsers:(X)"

其中:

  • (RX) 表示读取和执行;
  • (X) 对目录表示穿越/执行。

修改后重新启动 Codex,问题仍然存在。再次检查 ACL,确认权限确实已经写入,但 CreateProcessAsUserW 依旧返回拒绝访问。

这个结果证明:单纯修改别名 ACL 并不能解决问题。

为了避免留下没有必要的权限扩展,后续移除了这两条授权:

icacls "$env:LOCALAPPDATA\Microsoft\WindowsApps\pwsh.exe" `
  /remove "1INXU\CodexSandboxUsers"

icacls "$env:LOCALAPPDATA\Microsoft\WindowsApps" `
  /remove "1INXU\CodexSandboxUsers"

这一步是整个排查过程里很重要的纠正:看到“拒绝访问”并不意味着一定要继续扩大 ACL。应先确定究竟是哪一类可执行文件、哪一种令牌和哪条启动路径产生了差异。

转折点:比较不同 Shell

真正定位问题的是一组控制变量实验。

我使用相同的 Codex 受限沙盒,分别启动:

  1. cmd.exe
  2. Windows PowerShell 5.1
  3. Microsoft Store/MSIX 版 PowerShell 7

测试 cmd.exe

codex sandbox -- cmd.exe /c echo CMD_SANDBOX_OK

结果:

CMD_SANDBOX_OK

测试 Windows PowerShell 5.1

codex sandbox -- `
  "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" `
  -NoProfile `
  -Command "'WINDOWS_POWERSHELL_SANDBOX_OK'"

结果:

WINDOWS_POWERSHELL_SANDBOX_OK

测试 Store/MSIX 版 PowerShell 7

codex sandbox -- `
  "C:\Program Files\WindowsApps\Microsoft.PowerShell_7.6.4.0_x64__8wekyb3d8bbwe\pwsh.exe" `
  -NoProfile `
  -Command "'PWSH_SANDBOX_OK'"

结果:

CreateProcessAsUserW failed: -1073283067

这里的 -1073283067 对应十六进制 0xC0070005,低 16 位仍然是错误码 5,也就是 ERROR_ACCESS_DENIED。它不是另一种故障,只是 unelevated 沙盒后端没有正确解码和显示错误。

至此,问题范围已经非常清楚:

Shell沙盒结果
cmd.exe成功
Windows PowerShell 5.1成功
Store/MSIX PowerShell 7.6.4失败

如果是工作区权限、Codex runner 或受限令牌整体损坏,cmd.exe 和 Windows PowerShell 5.1 也应该失败。但它们能够正常运行,说明问题具有明确的安装类型相关性。

互联网与 GitHub Issues 检索

随后检索 OpenAI 官方文档、Microsoft 文档和 openai/codex Issues,找到了与本机情况几乎完全一致的报告。

核心 Issue:#35871

openai/codex #35871 的标题就是:

Windows sandbox: CreateProcessAsUserW fails with error 5 when the resolved shell is the MSIX (Store) build of pwsh

该 Issue 在同一台机器、同一会话中对不同 Shell 各进行了 20 次测试:

Shell失败次数
Store/MSIX pwsh.exe20/20
Windows PowerShell 5.10/20
cmd.exe0/20
Git Bash0/20

Issue 还确认:从交给 Codex 的 PATH 中移除 WindowsApps 路径后,Codex 会回退到 Windows PowerShell 5.1,并正常运行。

截至 2026-07-30,该 Issue 仍为 Open,带有 bugsandboxwindows-os 等标签,尚无关联修复 PR。

错误码显示问题:#35958

openai/codex #35958 专门解释了:

-1073283067

这个负数实际是包装后的 ERROR_ACCESS_DENIED。该 Issue 属于错误信息格式问题,底层启动失败仍由 #35871 跟踪。

其他相关但不同的故障

检索过程中还发现了:

  • #26186:上层症状同样是 CreateProcessAsUserW failed: 5
  • #32655:Codex helper 相对于 PATH shim 解析错误;
  • #31101:错误 1920 和残留 runner 进程;
  • #29072:Codex 沙盒 helper 从 WindowsApps 包路径启动失败。

不过,本次环境中 cmd.exe 能正常通过相同沙盒运行,Codex helper 也可以完成基础启动,因此 helper 丢失、runner 全局失效和工作区 ACL 损坏都不是主要原因。

为什么会安装到 MSIX 版本?

根据 Microsoft 的 PowerShell 7 安装文档,从 PowerShell 7.6.0 开始:

winget install --id Microsoft.PowerShell --source winget

默认安装的是 MSIX 版本。

如果要安装传统 MSI 版本,必须显式指定:

winget install `
  --id Microsoft.PowerShell `
  --source winget `
  --installer-type wix

MSIX 版通常位于:

C:\Program Files\WindowsApps\Microsoft.PowerShell_...\pwsh.exe

MSI 版则位于:

C:\Program Files\PowerShell\7\pwsh.exe

这两个路径是判断 PowerShell 安装类型最直接的证据。

最终解决方案

1. 安装非 MSIX 的 PowerShell 7

使用官方建议的 WinGet 命令安装 MSI/WiX 版本:

winget install `
  --id Microsoft.PowerShell `
  --source winget `
  --installer-type wix

也可以从 Microsoft 文档链接到的 PowerShell GitHub Release 手动下载 x64 MSI。

2. 移除 Store/MSIX 版 PowerShell

在 Windows 的:

设置 → 应用 → 已安装的应用

中卸载 Microsoft Store/MSIX 版 PowerShell,保留 MSI 版。

需要注意:这里卸载的是 PowerShell,不是 Codex Desktop。

3. 验证路径解析

where.exe pwsh

期望首个结果为:

C:\Program Files\PowerShell\7\pwsh.exe

不应该再解析到:

C:\Program Files\WindowsApps\...

或:

C:\Users\<用户名>\AppData\Local\Microsoft\WindowsApps\pwsh.exe

4. 完全重新启动 Codex

关闭 Codex Desktop,并确认相关后台进程已经结束,再重新打开应用,让新的 PATH 和 Shell 解析结果进入 Codex 运行环境。

修复后的完整验证

修复完成后,默认 PowerShell 检测结果为:

Version    7.6.4
Edition    Core
Executable C:\Program Files\PowerShell\7\pwsh.exe

随后重新验证各项沙盒边界。

工作区内写入、读取和清理

结果:

PASS: sandbox-workspace-ok

工作区外写入

向允许根目录之外的现有目录写入探针文件,结果:

Access to the path ... is denied

这说明沙盒没有因为排障而变成“全盘可写”。

网络隔离

沙盒中的直接网络请求被转发至本地拒绝端口并失败,说明网络限制仍然生效。

子进程

CMD_CHILD_OK
MSI_PWSH_CHILD_OK

最终检查矩阵

检查项结果
默认 PowerShell7.6.4 Core
默认路径C:\Program Files\PowerShell\7\pwsh.exe
PowerShell 命令执行正常
PowerShell 子进程正常
cmd.exe 子进程正常
工作区内读写正常
工作区外写入正确阻止
直接网络访问正确阻止
测试文件清理无残留
CreateProcessAsUserW 错误不再出现

Codex Desktop 本身是 MSIX,会不会也有问题?

这次故障来自 MSIX 版 PowerShell,而不是 Codex Desktop 本身。

根据 Codex/ChatGPT Windows 企业部署文档,当前 Windows 桌面 App 只有以下安装路径:

  • Microsoft Store;
  • 官方 Web Installer;
  • 企业直接部署 Store 签名的 x64/Arm64 MSIX。

官方明确说明,目前不提供独立 MSI 或非 Store EXE 的桌面 App。

这并不影响本次修复。Codex Desktop 仍然使用官方 MSIX 包,只要它调用的是普通 MSI 版 PowerShell 7,Windows 原生沙盒就可以正常运行。

如果确实需要非 MSIX 的 Codex 运行方式,可以使用没有桌面 UI 的 Codex CLI 独立安装版:

irm https://chatgpt.com/codex/install.ps1 | iex

但这不是解决本次故障的必要条件。

排障经验总结

1. Access denied 不等于应该继续放宽 ACL

权限错误可能来自:

  • 文件 ACL;
  • 目录穿越权限;
  • 受限令牌;
  • AppX/MSIX 激活模型;
  • Windows 沙盒后端;
  • Shell 解析到了错误的安装类型。

只有在对照实验确认 ACL 是变量时,才应该修改 ACL。

2. 比较不同可执行文件比反复重启更有效

本次最关键的证据不是重启或重装,而是:

cmd 成功
Windows PowerShell 5.1 成功
MSIX PowerShell 7 失败

一组好的对照实验往往可以快速排除整个故障层级。

3. 必须检查实际可执行路径

仅看到“PowerShell 7.6.4”还不够。下面两个 PowerShell 7.6.4 的行为可能完全不同:

C:\Program Files\WindowsApps\...\pwsh.exe
C:\Program Files\PowerShell\7\pwsh.exe

建议同时检查:

$PSVersionTable.PSVersion
(Get-Process -Id $PID).Path
(Get-Command pwsh).Source
where.exe pwsh

4. WinGet 的默认安装类型可能发生变化

PowerShell 7.6.0 起,WinGet 默认选择 MSIX。只写包 ID 并不能保证得到 MSI:

winget install --id Microsoft.PowerShell --source winget

需要 MSI 时,应明确指定:

--installer-type wix

5. 修复后要验证安全边界没有被破坏

一个完整的修复验证不应只检查“命令能跑”,还应检查:

  • 工作区内是否可以正常写入;
  • 工作区外是否仍被阻止;
  • 网络是否仍受限;
  • 临时探针是否清理;
  • 默认 Shell 是否指向预期路径。

结论

这次 CreateProcessAsUserW failed: 5 的根因是:

Codex Windows 沙盒解析到了 Microsoft Store/MSIX 版 PowerShell 7,而该可执行文件无法通过当前 Codex 受限令牌启动路径正常运行。

最终有效的解决方法是:

  1. 安装 MSI/WiX 版 PowerShell 7;
  2. 移除 Store/MSIX 版 PowerShell;
  3. 确认 pwsh 指向 C:\Program Files\PowerShell\7\pwsh.exe
  4. 完全重新启动 Codex;
  5. 验证命令执行与沙盒隔离边界。

修复后,PowerShell 7.6.4、工作区读写、子进程调用和网络/文件权限隔离全部恢复正常。

参考资料

最后修改:2026 年 07 月 30 日
如果觉得我的文章对你有用,请随意赞赏