ARTICLE / 安全
同题实跑全部被环境阻断:未形成四工具能力比较
如果有人问你 Claude Code、Codex、Qwen Code、OpenCode 有什么区别,你能答出配置、模型、价格。
但真到了要选一个干活的早上,这些答案一个都用不上。
因为要评估编码能力是否可用,得先排除登录、额度、网络和凭据等环境阻断,再实际运行:谁来跑测试、跑失败了自己知不知道、改完文件有没有验证、额度用完了是安静地停还是大声地停、中途网络抖一下会怎样。
这篇不展开安装与配置细节。下面这次实测在作者自己的开发机上完成:首轮把同一个任务交给四个 AI 编码 CLI,并为每个工具复制一份独立目录;重跑仅涉及 Qwen Code 与 OpenCode。
作者记录称四个工具收到的是同一份任务文本与同一条提示词,但原始发送日志未公开,任务实际送达情况无法独立核验。四个工具均被启动并进入执行流程,都在环境阻断处终止,没有进入可比较的模型处理阶段。文中引用的命令、报错原文、耗时和文件校验和都来自作者本机的执行记录;本文列出的版本号、机器型号、退出码、用时、错误原文与六份副本的 billing.py 校验和前缀(前缀 26945ce3ed502888),据随文汇总记录可核对;原始日志未公开。
需要先说明证据分层:四工具实跑记录(含其中的代理探测与 provider 快照)和两个公开 issue 分别来自不同来源,除文中注明对应关系外,不构成同一次实验。
四个工具本轮均未能完成外部验收,通过验收的运行数为 0 个。 本轮未形成可比较的能力结果:首轮受登录、额度和连接阻断,重跑仍因超时与凭据错误终止。
为什么测这个
四个工具都输出了具体错误文本,日志中可见的错误类别不同:Claude Code 与 Codex CLI 显示账户或额度错误,Qwen Code 与 OpenCode 显示连接错误。至于工具内部的实现层级,本轮只能读到这些错误文本,仍需源码或更完整的日志才能确认。
下面两个公开 issue 各自报告了可查阅的失败形态。这两项均不属于本轮四工具实跑结果,只是提示值得核查的失败路径,不据此判断相关产品的普遍表现,也不用于评价本轮四工具的能力。
- Copilot CLI issue #5318(github.com/github/copilot-cli/issues/5318)
- Gemini CLI issue #29189(google-gemini/gemini-cli/issues/29189)
Copilot CLI 的 issue #5318(github.com/github/copilot-cli/issues/5318)报告称,输出压缩若把数字文件名后缀或目录分量误判为 grep 字段分隔符,内置 rg 可能返回错误的文件名或行号。
图:github/copilot-cli issue #5318 页面(Describe the bug 段落),截取日期:2026-11-10。
Gemini CLI 的 issue #29189 报告称,git diff 的白名单只检查子命令名而不检查参数,参数可能未纳入该白名单判断;具体影响以 issue 原文为准。单个 issue 的报告尚不能证明这类问题普遍存在。
图:github/google-gemini/gemini-cli issue #29189 页面(标题为 Security: git diff –output bypasses permission prompt),截取日期:2026-11-10。
【建议】这两个公开 issue 只作为可选的扩展核查项,用于决定核查清单怎么列。
所以这篇只做一次有限实测:用同一任务记录四个工具在环境阻断前后分别发生了什么,不据此比较工具能力。
测法:同一份任务,四份拷贝
任务是一个范围较小、结果可由外部测试验收的 bug:一个 Python 计费模块,calc_tax 函数写错了(少乘了 price),配套的单元测试里有 2 个失败。
任务文本(作者记录为逐字相同):
billing.py 里的 calc_tax 函数有 bug,单元测试 test_billing.py 有 2 个失败。请修复 bug,让所有测试通过。只改 billing.py,不要改测试文件。完成后说明你改了什么。
每个工具拿到一份独立的目录拷贝,避免前一个改完文件污染后一个的输入。六份副本中的 billing.py SHA-256 前缀一致,确认该文件起点相同。
初始验收记录显示:共执行 3 个测试,其中 2 个失败。验收方式只有一个:在工具之外执行 python3 -m unittest,看 3 个测试是不是全绿。
验收一律在工具之外做。 外部验收只用来判断最终结果是否正确;工具是否自行跑测试、失败后有没有迭代,需要额外采集工具日志——本轮未获得模型处理任务的证据,这一层观察不到。
四个工具的版本:Claude Code 2.1.185、Codex CLI 0.166.0、Qwen Code 0.20.0、OpenCode 1.19.5。实验环境记录为 Mac17,7(M5 Max、128GB 内存)。
结果:四个都没跑通
- Claude Code 用时 2 秒 退出码 1 测试仍是 2 个失败 停止原因:未登录
- Codex CLI 用时 11 秒 退出码 1 测试仍是 2 个失败 停止原因:额度耗尽
- Qwen Code 用时 15 秒 退出码 1 测试仍是 2 个失败 停止原因:连接被重置
- OpenCode 用时 166 秒 退出码 1 测试仍是 2 个失败 停止原因:连接被重置
四次运行均未通过验收。但这不能写成"这四个工具都不行"——那正是测评最容易犯的错。第一轮观察到的失败归为登录状态、额度、连接三个类别。
第一层:日志未显示提示词发送记录。 Claude Code 2 秒就返回,输出是一句 “Not logged in · Please run /login”。仅凭这条错误,无法确认请求是否曾被发出。
第二层:会话头已经打印,但账户状态挡住了后续。 Codex CLI 打印了完整的会话头——模型 gpt-6.1-sol、approval never、sandbox danger-full-access、会话 id 都齐了,看起来一切正常,然后:“You’ve hit your usage limit… try again at Nov 11th, 2026 2:45 PM.” 额度恢复时间精确到了分钟。
第三层:连接层被打断。 Qwen Code 输出 “ECONNRESET: Client network socket disconnected before secure TLS connection was established”,OpenCode 输出 “Cannot connect to API: ECONNRESET”。OpenCode 的日志显示所选模型为 agnes-3.0-flash,但不能据此确认请求实际到达该模型;现有汇总材料未记录 Qwen Code 使用的模型。
这三个位置的区别值得记下来:越早被账户、额度或网络阻断,这一轮越无法观察模型处理能力。 阻断位置、提示方式和可配置性是否属于工具设计,本轮不能据此判断,需要结合实现、配置与额外运行记录另行评估。
一个必须交代的实验污染
OpenCode 和 Qwen Code 的 ECONNRESET 让这轮结果存在被代理环境干扰、无法完全归因的风险,需要结合代理链路和重复运行进一步排查。
排查发现机器上配着三个代理端口:Surge 监听 6152,mihomo 监听 7890,privoxy 监听 1087。作者记录为默认环境变量指向 6152(原始环境变量输出未公开)。对五个端点做直连与 6152 路径复测(2026-11-09 00:35:33 CST):
- api.openai.com:直连 421,走 6152 也是 421
- openrouter.ai:直连 200,走 6152 也是 200
- api.z.ai:直连 301,走 6152 也是 301
- dashscope.aliyuncs.com:直连 404,走 6152 也是 404
- generativelanguage.googleapis.com:直连 404,走 6152 也是 404
同日早些时候保存的代理探测记录,与随后 2026-11-09 00:35:33 CST 的复测结果不一致。 两次记录按四条路径逐项对照(HTTP 状态码,超时记为 TO):
- 下列每项依次为:直连、6152、7890、1087
- 首轮 openrouter.ai 200 TO TO 未记录
- 首轮 api.z.ai 301 TO TO 未记录
- 首轮 dashscope.aliyuncs.com 404 TO TO 401
- 首轮 generativelanguage.googleapis.com 404 TO TO 未记录
- 复测 openrouter.ai 200 200 TO TO
- 复测 api.z.ai 301 301 TO 301
- 复测 dashscope.aliyuncs.com 404 404 TO 404
- 复测 generativelanguage.googleapis.com 404 404 TO 404
在已记录的探测项中可以看到:6152 路径在复测时与直连逐项一致,7890 路径返回超时或未记录,1087 路径对 dashscope 从 401 变成 404。
也就是说,同一主机在不同时间的探测结果存在差异,而这个比较里路径也跟着变了,因此目前无法把差异单独归因于路径或时点。顺带说明一句:421、301、404 只证明端点返回了 HTTP 响应,不代表业务可用。
另外首轮记录里 1087 路径对 dashscope 返回 401、复测则返回 404 这件事:401 表示请求到达了端点,只是凭据不被接受,和"网络不通"是两回事。仅凭这类错误文本,无法判断凭据问题来自本地配置、代理网关还是上游服务,需要结合请求链路日志进一步定位。
随后进行重跑:Qwen Code 与 OpenCode 均显式使用 1087 代理,OpenCode 同时更换了模型。
重跑之后:失败原因换了一批
第二轮依然没跑通。重跑记录到了不同的终止文本和退出码:Qwen Code 与 OpenCode 都换了代理路径,OpenCode 还换了模型,超时设置是否变化未见记录。
- Qwen Code 用时 240 秒 退出码 124 停止原因:超时被杀,输出 “Operation cancelled.” 与第一轮相比:退出码从 1 变成 124,文件零改动
- OpenCode 用时 200 秒 退出码 1 停止原因:换模型后报 “The API key or AK/SK in the request is missing or invalid” 与第一轮相比:从连接被重置变成凭据无效
Qwen Code 这一轮没有秒失败,它撑满了 240 秒才被 timeout 杀掉,文件零改动。可以确认的是它没有再立即报 ECONNRESET;至于模型是否已经开始处理,日志没有给出证据。
OpenCode 这轮的情况是:使用的模型由第一轮的 agnes-3.0-flash 变为 glm-5-3-flash-260828,失败信息也从连接被重置变为凭据无效。现有记录未说明切换原因。
本轮重跑的具体记录如下。
同一时段保存的 provider 状态快照显示,不同服务在该时点被面板标记为不同状态——随附快照记录于 2026-11-09 00:30:33,13 个 provider 分为 ok、degraded、skip、error 四类。它与本次重跑使用的具体服务和请求链路并不完全对应,只能作为环境状态复杂性的旁证,不能解释重跑失败的具体原因。
这份快照只能提示环境状态可能波动。后续做类似测评时,值得记录测试时间,并在可能时一并记录实际调用的服务与 provider 状态。
“会用"这件事,拆开看是四层
基于本轮观察到的失败结构,作者提出一份工作假设式的记录清单——它不是经过验证的评测框架,读者可用它作为自查维度。下面分四类观察,并标注每一层的来源:【本次观察】来自这轮实测,【公开案例】来自可核验的 issue,【建议】是评测时的行动建议,不声称已验证有效。
第一层:能跑通。【建议/工作假设】对本次任务型评测而言,能跑通是观察后续行为的前提,也是本轮主要受限的一层。本轮只记录到"未完成外部验收”,没有观察到工具跑通之后的行为,需要在选型时单独记录。登录状态、额度、代理、网络、模型服务可用性——本轮各工具分别停在这几类阻断上。本轮可确认相关工具显示了错误文本。
第二层:本轮失败是否显示了可辨识的错误文本。【本次观察】本次运行中,Codex CLI 与 Claude Code 都直接显示了失败原因;Codex CLI 还给出额度恢复时间。这只能说明错误信息可见,尚不足以评价失败交互的完整性或质量。若失败原因不可见,排查可能因此延迟,这种延迟是否造成损失取决于任务流程。首轮四项与重跑两项的错误文本都来自汇总记录。本轮六次汇总记录均有输出;本次记录不足以评估其他失败形态是否缺少明确提示。
第三层:自我验收。【建议】观察工具是否主动运行测试、根据失败继续迭代,以及是否留下可核验的验证记录。这是一种评测维度,不是任务完成的唯一标准。本轮四个工具都没走到能观察这一层的位置。
第四层:安全边界是否覆盖完整。【公开案例】Gemini CLI 的 issue #29189 报告了一个具体案例。这个公开案例提示,评估安全边界时还应检查参数解析、权限判断和审批机制是否覆盖完整;是否普遍存在仍需更多案例验证。
怎么自己测一次
如果这篇文章只能留下一个可执行动作,我希望是这个:先排除环境,再谈选型。
- 挑一个真实但范围受控的小任务;如果目标是观察边界行为,再补充权限、异常输入和大仓库等场景。
- 每个工具一份独立的目录拷贝,并用校验和确认起点一致,避免互相污染。
- 用工具之外的方式验收——命令行跑测试、跑构建、跑 linter。让工具自报"测试通过"不算数。
- 记录失败的样子,而不只是成功的样子。记录失败路径有助于缩小环境与行为问题的排查范围;要归因于工具差异,仍需控制模型、账户、网络等变量并重复验证。
- 先检查你的网络和账户状态,把环境问题挡在门外,否则你测的是代理不是工具。
每次记录建议固定几个字段:错误类型、是否显示原因、文件是否改动、外部验收结果。字段固定了,几次运行的记录才能横向对比。
最后
先排查并记录登录、额度、网络和凭据的状态,再在受控的重复运行后讨论模型与工具能力。
参考来源
- Copilot CLI issue #5318 Copilot CLI grep compaction corrupts filenames and line numbers(github/copilot-cli,报告者 aaroneng 提交)https://github.com/github/copilot-cli/issues/5318
- Gemini CLI issue #29189 Security:
git diff --outputbypasses permission prompt(google-gemini/gemini-cli,报告者 PakCyberbot 提交)https://github.com/google-gemini/gemini-cli/issues/29189
(以上网页采集日期:2026-11-10。issue 内容可能随维护者回复变化,以原始页面为准。)
本文面向授权安全研究与防御建设,未经授权对任何系统实施文中技术属违法行为。文中两个公开 issue 的复现步骤只应在各自作者的环境里验证,本文没有复现,只引用 issue 原文。

