Codex Windows 沙箱中 curl 报 SEC_E_NO_CREDENTIALS 的排查记录

太阳作者太阳
原创内容采用 CC-4.0 协议发布,转载请注明出处

Codex Windows 沙箱中 curl 报 SEC_E_NO_CREDENTIALS 的排查记录

在 Windows 版 Codex App 中执行一个普通的 HTTPS 请求,系统自带的 curl.exe 直接失败了:

curl.exe -I https://registry.npmjs.org

错误信息如下:

curl: (35) schannel: AcquireCredentialsHandle failed:
SEC_E_NO_CREDENTIALS (0x8009030e)
安全包中没有可用的凭证

这个错误很像证书或网络故障,但实际问题不在目标网站。相同命令离开 Codex 的执行环境后可以正常返回 HTTP/1.1 200 OK

先确认故障发生在哪一层

我先检查了 DNS 和 443 端口。域名可以解析,TCP 连接也能建立。说明请求至少已经具备到达目标服务器的条件。

随后测试 PowerShell:

Invoke-WebRequest `
  -Uri "https://registry.npmjs.org" `
  -Method Head `
  -TimeoutSec 10

它同样失败。继续查看内部异常,可以看到完整的调用结果:

System.Net.Http.HttpRequestException:
The SSL connection could not be established

System.Security.Authentication.AuthenticationException:
Authentication failed

System.ComponentModel.Win32Exception:
安全包中没有可用的凭证

curl.exe 和 PowerShell 都使用 Windows 的 Schannel TLS 实现。两者报错一致,问题已经可以缩小到 Schannel。

为什么 Node.js 可以访问

在同一个 Codex 会话中执行 Node.js 请求:

node -e "fetch('https://registry.npmjs.org').then(r => console.log(r.status))"

返回结果是:

200

Node.js 使用的 TLS 实现不依赖 Windows Schannel,所以没有触发同一个错误。这组对照也排除了“整个 Codex 会话无法访问网络”的可能。

沙箱外的 curl 也能正常工作

最直接的验证,是在普通 Windows Terminal 中执行完全相同的命令:

curl.exe -I https://registry.npmjs.org

结果正常:

HTTP/1.1 200 OK

系统里的 curl.exe 没有损坏,Schannel 也不是在所有进程中都不能使用。只有命令进入 Codex 的 Windows 沙箱后才会失败。

SEC_E_NO_CREDENTIALS 在这里是什么意思

Windows 程序建立 TLS 连接前,会通过 SSPI 的 AcquireCredentialsHandle 获取 Schannel 客户端凭据句柄。这里的“凭据”不是网站账号或密码,而是 Schannel 创建 TLS 安全上下文时使用的内部对象。

当前错误发生在这个句柄的创建阶段。TLS ClientHello 还没有发出,后续的服务器证书验证也没有开始。因此,修改 CA 证书、关闭证书吊销检查或切换 TLS 版本都碰不到真正的问题。

Windows 事件查看器中还能找到对应记录:

事件 ID: 36871
创建 TLS 客户端凭据时出现严重错误。
内部错误状态为 10013。

OpenAI Codex 仓库中的同类报告给出了相同特征:

  • PowerShell、.NET 和 Schannel 版 curl.exe 在沙箱中失败;
  • Node.js 或 Python 的 HTTPS 请求正常;
  • 相同的 PowerShell 或 curl 请求在沙箱外正常;
  • 错误集中在 Schannel、SSPI 与 Windows 受限执行上下文之间。

目前可以确认故障边界,但还不能把更底层的原因写死。上游 issue 提到受限令牌和用户配置状态可能参与其中,具体是哪项 Windows 状态无法访问,仍在调查。

当前怎么处理

普通的 HTTP 请求可以改用 Node.js:

node -e "fetch('https://example.com').then(async r => console.log(r.status, await r.text()))"

Python 也不依赖 Schannel:

python -c "import urllib.request; print(urllib.request.urlopen('https://example.com').status)"

如果命令必须使用 Windows Schannel,例如 curl.exe、PowerShell Web 请求或部分 .NET 工具,就需要在 Codex 沙箱外执行。

这个问题不会通过重启终端消失。每次命令进入同类受限环境,Schannel 都可能在创建客户端凭据时再次失败。在上游修复之前,选择不依赖 Schannel 的客户端,或者把对应命令放到普通终端执行,是更稳定的处理方式。

参考资料