Agent 选择工具时,通常把工具名称、自然语言描述和参数 schema 一起交给模型。开发者很容易把这些元数据当成无害说明,但 ContextLeak 展示了一种更隐蔽的风险:恶意工具的实现可以只是普通接口,真正的攻击载荷藏在名称与描述里,诱导模型主动选中它,并把运行时上下文填进调用参数。
这类攻击不需要直接读取记忆文件,也不必在工具代码中包含明显窃取逻辑。数据泄露发生在工具执行之前——Agent 自己组织参数时,已经把用户提示、对话历史或其他工具信息复制到外部边界。
#工具选择与参数传递是两个攻击目标
过去的工具投毒研究多关注“让 Agent 选错工具”。但工具被选中不等于敏感信息会进入参数。ContextLeak 同时优化两个条件:恶意工具要在多个候选中胜出,还要让 Agent 把目标上下文完整放入调用参数。
研究使用一个攻击模型生成语义上看似合理的工具名称和描述,再用强化学习优化。训练环境由一组模拟用户组成,每个用户有不同提示、对话历史和正常工具。奖励分别衡量恶意工具是否被选中,以及参数对目标上下文的还原程度。
训练使用的是“影子用户”,评测用户在提示、历史和工具列表上完全不同。研究还跨领域、跨数据集和跨后端模型测试,以判断攻击是否只记住训练样本。
#三类上下文都可能被带出
实验覆盖用户当前提示、完整对话历史和工具列表。前两者属于当前任务上下文,工具列表则可能暴露跨任务能力、内部服务名称与集成结构。
在同数据集、同领域但样本不重合的设置中,恶意工具被选中的比例分别达到 0.92、0.89 和 0.86。条件于工具被选中,用户提示的 token 编辑距离相似度为 0.99,语义相似度为 1.00;对话历史为 0.85 和 0.96;工具列表 F1 为 0.68。
这说明攻击不只是触发一次无意义调用。尤其对文本上下文,参数可以接近完整重建。跨数据集与未见领域时效果有所下降,但仍保持明显有效,领域变化比数据集变化带来的影响更大。
#开源代理上训练,可以转移到商用系统
攻击模型只针对 Qwen3.5-9B 影子目标训练。研究随后把 100 个生成的恶意工具放进 Claude Code 与 Claude Sonnet 4.6 的原生工具选择场景,每次共有 20 个候选工具。
Claude Code 在 100 次中有 22 次选择恶意工具。条件于选择,抽取的编辑距离分数为 0.77、语义相似度为 0.96。22% 并不等于所有真实部署的成功率,但足以证明:在开源代理上学到的元数据攻击模式,可以越过模型与系统差异转移到生产型工具调用 Agent。
#现有防御为什么漏掉它
代码扫描器会检查文件访问、网络调用和数据流,而 ContextLeak 的工具实现可以是无害占位;敏感数据由 Agent 在参数构造阶段主动提供。只检查实现代码,无法识别工具描述对模型决策的操纵。
研究测试 PromptGuard、DataSentinel、PromptArmor 和 MCPScan 的元数据检测。在各类上下文攻击上,这些方法漏报率为 0.97 至 1.00,几乎没有识别出恶意描述。原因是描述仍然语义连贯,没有明显攻击字符串。
StruQ 与 SecAlign 等预防训练能降低攻击成功,但正常工具选择与参数质量也明显下降。换言之,一部分“安全提升”来自模型不再擅长调用任何工具。Meta-SecAlign 较好保留效用,却没有显著阻断攻击,呈现清晰的安全—可用性冲突。
#工具供应链需要新的信任边界
第一层防线是最小化上下文暴露。模型选择工具时不应默认看到不相关的对话、记忆和完整工具清单;路由器可以先按权限和任务过滤候选,再把必要描述交给模型。
第二层是在调用前做结构化数据流检查。参数 schema 要声明允许的数据来源,敏感字段离开本地前需要策略验证、脱敏或用户确认。不能因为参数是模型生成的,就把它视为用户授权。
第三层是把工具元数据当作可执行供应链资产。名称、描述和 schema 的变更需要版本、签名、差异审查和行为测试;安装时既扫描代码,也用对抗任务测试模型会选择它做什么、会传入哪些信息。
研究只覆盖三类上下文,而且大多数攻击让恶意工具成为第一次、也是唯一一次调用,没有测量执行正常工具后产生的完整轨迹。现实系统的模型、权限、候选过滤和确认 UI 也会显著影响成功率。
但它给出了足够明确的架构警告:工具描述不是文档,而是进入模型控制平面的指令性输入。只要模型同时负责路由和参数组装,元数据就必须按潜在代码处理,工具参数也必须按潜在数据外泄出口处理。