资讯详情

资讯详情

在 98% 的会话里,agent 从记忆里挑了已弃用的 MCP 包

摘要你让 agent 接个 GitHub它没问你用哪个实现直接挑了一个装上。依据不是仓库现状是训练记忆。安全公司看到这类决定在 98% 的会话里没回到人手上有的案例里它挑的就是早就弃用的参考实现。你让 agent 帮忙接一下 GitHub。它回一句「好的」然后跑了一条npx起了一个 server通了。全程没问你用哪个实现也没问版本。这件事单看没什么。你本来就想省掉这个决定。但它替你做的这个决定依据不是仓库现在有什么是它训练时见过什么。它不问是因为它觉得不用问安全公司 Glow 做过一组观察结论被行业媒体反复引用开发者提出一个能力需求比如「要能读 GitHub」在观察到的会话里有 98% 的比例agent 自己就把包选定了没有回头确认。这个 98% 容易被读错。它不是「98% 的会话装错了包」。它说的是这个决定几乎从不回到人手上。至于选得对不对是另一个发现。同一组观察里有个案例agent 从训练数据里翻出一个 Anthropic 的参考实现装了上去而那个实现早就弃用了官方维护的版本就在同一个仓库里。索引是旧的因为索引是记忆为什么放着新的不用去拿旧的把它想成查表就清楚了。你问它「装哪个」它去查表。表在哪在权重里。权重是某一天冻结的。那天之后仓库改了名字、换了维护者、把参考实现挪进deprecated/目录、README 顶上加了警告——这些它都不知道。所以这不是判断力问题。它记得的那个版本在它学习的时候是对的。你让一个只能回忆、不能检索的东西去做一个必须看现状才能做对的判断。有人会说它不是能联网搜吗能。但那是另一条路径要它主动想起来去搜而「装个包」这个动作太熟练了熟练到它不觉得需要查。就算它真去搜了也补不上这个洞。搜出来的第一个结果不是「最正确的那个」是「最像那么回事的那个」——名字可以像README 可以像星标数也能像。把依据从权重换成搜索结果只是换了一张别人也写得出来的表。那批旧包上挂着四个高危漏洞Glow 在那批弃用的参考实现里翻到四个高危漏洞。哪四个、什么类型、有没有编号我手上的转述都没写原始报告也没拿到——这一条只能按「有人数过」记不能拿来推严重到什么程度。能拿来说事的是下载量更宽的那一批弃用参考实现月下载量大约 165 万次。这个数字同样得打折。它是厂商自己发布的研究我只能按二手转述引165 万次里多少是 agent 装的、多少是人手敲的报告也没拆开。但方向是清楚的有人在持续安装一批明确标了弃用的东西。这也解释了一个反常现象。你在代码仓库里很少见到有人主动npm i一个 README 写着「本仓库已废弃」的包——装的时候会看见。而 agent 不装给你看。最麻烦的是它不在你的清单里npx这东西的工作方式是临时拉下来跑起来不留痕。它不进package.json不进lockfile不进node_modules的长期列表。你的 SBOM 里没有它。你公司每季度做的那次软件资产盘点也扫不到它。问一句你的资产清单上一次更新是什么时候很多团队的答案是「上季度」。而 agent 昨天已经在你机器上装过三个包了。这条缝在两个方向上被撑大。一头是它不属于任何项目的依赖树所以没人负责另一头是它一旦跑起来拿的就是你 agent 手上的权限。OpenCode 那个缺陷是个具体例子。在 Windows 和 WSL 上一个恶意或被劫持的 MCP server 可以把命令塞进 OAuth 授权 URL在你走登录授权那一步这个 URL 被原样拼进了一条 PowerShell 命令。Pillar Security 提出按 9.8 计。修得不算慢8 月底私下报告9 月 28 日的 1.18.33 就改掉了10 月中才由研究者公开。难受的地方在后面。**1.0.137 到 1.18.32 这些版本没有 CVE也没有安全公告。**没编号扫描器就不报。你跑的版本可能在受影响区间里而你的漏洞扫描结果是干净的。为什么没编号厂商给的理由是恶意 MCP server 不在他们的威胁模型里。这句话值得停一下。它不是说「我们忘了发」是说「我们认为这不该算我们的漏洞」。一台装着 agent 的机器被一个你不认识的服务端拿走了命令执行权——在威胁模型那张表格上这一格是空的。批准一次不代表下次还是那个东西还有一种情况比装错包更隐蔽。你装了一个 server看过它的工具列表点了同意。这一步在你的心理账户里是一次性的这个 server 我审核过了。那你当时批准的到底是什么是那个名字还是那一刻的清单可工具列表不是常量。它在你每次连上去的时候重新拉取而工具的描述文字会进入模型的上下文——也就是说描述本身是提示的一部分。于是就有了那种叫 rug pull 的做法先上架一个规矩的工具等你批准之后某次tools/list换成带指令的版本。多数客户端是按工具名缓存授权的名字没变它就不会再问你。这条不是某个产品的漏洞是这套机制的自然结果。你批准的对象是「名字」实际在跑的是「内容」。有人已经在补了那有没有人在管这件事有但补的位置跟你以为的不一样有的补在分发端有的补在运行时。分发端做得比较完整的是 Adyen 的 Agent Marketplace。一份配置能生成八种客户端认的资源——Claude Code、Codex、Cursor、Devin CLI、Factory Droid、Gemini CLI、OpenCode、Windsurf。它做的事很实在钉死版本、校验下载摘要、扫描隐藏内容与可执行脚本与远程 URL 与能力声明遇到本地已有冲突文件就拒绝覆盖。不过他们自己写了一句我觉得比功能列表更值得记「这些检查降低风险但不能证明一个 hook 或 MCP server 是安全的。」运行时那头在收的是工具厂商自己动静集中在十月这一个月。Claude Code 2.1.307 在权限规则、hook、沙箱或任何一种安全机制打断工具调用时会发一条 OpenTelemetry 事件——安全机制出手这件事本身变得可观测了。同一个版本还把掉线的 HTTP MCP 调用限制成只在只读或幂等时才重试。Codex 那边收紧的是把宿主密钥代入代理流量的目标与请求条件。这些都不解决「agent 该装哪个包」。它们解决的是装完之后出事能不能看见。先把它当依赖管别当配置管如果你的团队已经在用 agent 跑真实仓库有三件事现在就能做都不难。**把 MCP server 当依赖不当配置。**配置可以随手改依赖要有人批。给每个要用的服务定一个批准过的实现写死版本记下来源。别让「随手npx一下」成为默认路径。**让它进清单。**不管你的清单是 SBOM、是资产库、还是一个 Markdown 表格先有个地方能查到「这台机器上跑过哪些 server、谁装的、什么时候」。这一步不做后面所有讨论都是空的。**盯住能力不只是盯住包名。**包名不变能力可以变。至少要能回答这个 server 现在能读什么、能写什么、能往外发什么。Adyen 那套扫描里最值钱的一项就是能力声明扫描不是摘要校验。最后依赖可信这件事工程界做了二十年。锁版本、校验摘要、SBOM、私有源、准入清单——该有的都有。Agent 没有推翻这些做法它只是把那个做选择的人换掉了。以前是你在写import那一行时做的决定现在是一个只能回忆的东西替你做的。而它做这个决定的时候不会告诉你它记的是哪一年的仓库。参考资料AI-Native Engineering InsightsThe coding agent control plane gets concreteMCP DefenseMCP 漏洞类型参考作者唐悦玮 | 从后端出发用 AI 拓展到全栈的工程师。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →