编程 Agent 漏洞修复可能绕过依赖告警
文章援引安全研究称,opencode 1.18.32 在 Windows 和 WSL 的 MCP OAuth 登录流程中存在远程命令执行漏洞,1.18.33 已修复。由于修复未伴随 CVE 或安全公告,作者主张为编程 Agent CLI 建立快速更新机制和最低版本要求。
AI 深度解读
装在开发机上的 AI 编程 CLI,可能已经修过高危漏洞,你的依赖扫描却始终没有报警。原文讨论的 opencode 案例就属于这一类:远程 MCP 服务能借 OAuth 登录流程,在 Windows 和 WSL 上触发无需额外确认的远程代码执行,修复却被放进一次名为「重构」的变更里。
作者的结论是:这类工具应该参照浏览器管理,及时更新、设置最低版本、直接盘点安装情况。这套建议值得看,但也要分清漏洞事实、研究者统计,以及作者提出的管理主张。
一次打开浏览器,为什么会变成执行命令
据原文引用的 Pillar Security 报告,受影响的是 Anomaly 开源编程代理 opencode,版本范围为 1.0.137 至 1.18.32,影响 Windows 和 WSL,macOS 与 Linux 不受影响。
攻击入口在远程 MCP 服务的 OAuth 认证流程。MCP 用来给代理接入外部工具,但这次问题与模型生成内容无关,也不需要提示词注入。
流程可以拆成四步:
- 远程 MCP 服务返回 OAuth 发现结果,其中的
authorization_endpoint由服务端指定。 - opencode 把这个地址交给 npm 包
open,当时使用的版本是10.1.2。 - Windows 上,
open通过 PowerShell 打开浏览器,而 PowerShell 会展开双引号字符串里的$(...)。 - 地址虽然是格式正确、没有空格的
https://URL,其中的表达式却可能先被执行。浏览器随后启动失败,也无法撤回已经发生的执行。
这里跨越了一条信任边界:允许 MCP 服务提供登录地址,不等于允许它向本机 shell 提交命令。只检查 URL 是否以 HTTPS 开头,挡不住后续命令解释器对字符串的再次处理。
Pillar 给出的时间线是:8 月 29 日私下报告,9 月 25 日收到 Anomaly 回复并合入修复,9 月 28 日随 1.18.33 发布。修复把 open 升到 11.0.4,统一浏览器启动入口,只接受 http 和 https,并在 OAuth URL 交接处增加协议检查。不能把全部修复效果归功于其中某一项。
Pillar 提议的 CVSS 评分是 9.8,但没有对应 CVE,所以这不是正式登记的评分。原文还对比了同类问题:mcp-remote 在 2025 年 7 月获得 CVE-2025-6514,评分为 9.6。
Anomaly 表示,恶意 MCP 服务通常不在其威胁模型内。作者不接受这个边界,理由也很直接:用户添加服务是为了获得工具,而且服务可能在配置完成之后才被攻陷。
扫描没有报警,究竟漏在了哪里
这次修复没有 CVE,也没有安全公告。PR 标题是 refactor(core): share a browser opener across opencode and tui;1.18.33 的发布说明只提到,浏览器启动器立即退出时会报告 MCP 浏览器启动失败。
描述没有错,却很难让负责安全更新的人识别出背后的命令执行问题。
作者指出了两个不同的缺口。第一个是漏洞情报:按原文引用的 Dependabot 文档,只有进入 GitHub Advisory Database、并经 GitHub 审核的公告才会触发警报。没有相应记录,就不能指望它提醒。
第二个是资产范围:Dependabot 检查仓库默认分支的依赖,而通过 curl、Homebrew 或 npm -g 安装在开发机上的 CLI,通常根本不在项目依赖图里。
仓库依赖检查通过,不能证明开发机上的代理 CLI 已经安全更新。

原文又引用 Adversa AI 在 9 月 23 日发布的统计:涉及 Claude Code 的十项已记录攻击中,只有两项产生了 CVE;没有 CVE 的案例之一 Plugin4Shell,在 2.1.179 修复。四项带有厂商拒绝受理的记录,其中两项来自 Anthropic,其余来自其他厂商。
这些数字能说明公告覆盖存在缺口,但只是该目录的样本,不能推算整个行业的漏报比例。「SBOM 看不到任何一项」也应放回具体资产和工具范围理解,不能推广成所有 SBOM 都没有价值。
参照浏览器更新,具体要改哪几件事
作者提出三件事:默认更新、执行最低版本要求、自己维护安装清单。理由是代理持续接触网页、Issue、README、他人仓库和 MCP 服务,输入来源复杂,更新不能完全依赖 CVE 通知。
不同安装方式的行为差别很大。按原文引用的文档,Claude Code 原生安装会在后台自动更新;Homebrew、WinGet、apt、dnf、apk 安装默认不会。它提供 latest 和 stable 通道,后者通常落后约一周,避开出现重大回归的版本。
opencode 则会检查并提示新版,但不会自动安装。用户需要在 TUI 中运行 /update,或执行 opencode upgrade。
版本下限也要区分用途。Claude Code 的 minimumVersion 阻止更新机制安装低于指定下限的版本;组织托管设置中的 requiredMinimumVersion,才会让低于组织要求的版本拒绝启动。原文示例使用 "autoUpdatesChannel": "stable" 与 "minimumVersion": "2.1.100",这个数字是配置示例,不是本文确认的安全基线。
先盘点机器实际能找到哪些 CLI,可以使用原文这段脚本:
for cli in claude codex opencode; do
if command -v "$cli" >/dev/null 2>&1; then
v="$("$cli" --version 2>&1 | head -n 1)"
printf '%s: %s\n' "$cli" "$v"
else
printf '%s: not installed\n' "$cli"
fi
done
要注意 command -v "$cli":它检查当前命令搜索路径能找到的程序,不保证发现同一机器上的全部安装副本。
针对这次漏洞,原文还给出了最低版本检查:
min="1.18.33"
have="$(opencode --version 2>/dev/null \
| grep -Eo '[0-9]+\.[0-9]+\.[0-9]+' | head -n 1)"
low="$(printf '%s\n%s\n' "$min" "$have" | sort -V | head -n 1)"
if [ -z "$have" ]; then
echo "opencode not found"
elif [ "$low" != "$min" ]; then
echo "opencode $have is below $min: run opencode upgrade"
else
echo "opencode $have: ok"
fi
这里要检查 sort -V 的可用性,它并非所有系统自带的 sort 都支持;输出 ok 也只表示通过 1.18.33 这个版本下限,不代表排除了其他漏洞。WSL 与 Windows 原生安装还应分别盘点,避免漏掉另一份程序。
我的判断
我认同作者对管理方式的修正。代理 CLI 能读取项目、调用工具、执行本机操作,却经常由开发者自行安装。只靠仓库锁文件和依赖告警,确实覆盖不到这些入口。
但「像浏览器一样更新」是一项管理建议,原文没有提供团队采用前后的对照数据。稳定通道能缓冲部分已暴露的回归,不能保证拦住供应链攻击;Claude Code 提供的 GPG 签名校验清单,解决的又是分发文件被篡改这一类问题。更新节奏与制品验证,需要分别考虑。
固定版本也有合理用途,例如保证团队行为一致、复现代理任务。关键是有人负责检查和推进版本,并设定更新时间,而不是固定之后再也无人过问。
还要识别作者的商业立场:他开发 Hermes IDE。文中展示的 Hermes 2.3.4 能列出本机代理及版本,包括 Claude Code 2.1.299、Codex 0.145.0,并直接运行代理自己的终端界面。因此更新本机 opencode 后,下一次会话就能使用新版本。但作者也明确说,它不负责更新代理,不是漏洞扫描器,更不能替代团队设备清单。
能拿来做什么
- 给团队开发机增加代理 CLI 版本盘点,至少记录
claude、codex、opencode的版本和安装方式,并分别检查 Windows 与 WSL。不要只查看前端或 Node 项目的package.json。 - 对受影响平台上的 opencode,把
1.18.33作为这次漏洞的最低修复线;检查未通过时执行opencode upgrade。暂时无法升级的机器,可按 Pillar 建议移除未经审查的远程 MCP 服务。 - 根据安装方式明确更新责任。支持自动更新的选择合适通道;需要手动更新的指定负责人和检查周期,避免把「会提示新版」误当成「已经安装新版」。
- 排查 MCP 接入时,把 OAuth 登录、URL 打开和本机进程调用一起检查。模型没有执行危险指令,并不能排除认证流程已经触发危险行为。