提示注入把 agent 的抓取和 eval 变成攻击入口,另两起是 agent 工具体系自己的权限没做对

今天这批四起分成两半:CVE-2026-85675(OWL)和 CVE-2026-85694(LaVague)是同一个形状——模型读了攻击者控制的内容,被说服吐出一段东西(一个 URL、一段 Python),下游代码不问出处直接执行;CVE-2026-40502 和 CVE-2026-40515 都来自 OpenHarness、都由同一位研究者 Chia Min Jun Lennon 报告,和模型说了什么无关,是 agent 工具与命令通道的授权检查本身写漏了。前两起的入口侧(模型会被说服这件事)没人修,后两起有明确的修复 commit。

注:材料给的 CVSS 与 advisory 上标注的 CVSS 4.0 分数不一致,两个都列出来。

CVE-2026-85675 · camel-ai/OWL DocumentProcessingToolkit

披露日 2026-09-04。材料给的是 7.5 HIGH;OffSeq 抓到的 NVD 记录是 CVSS 4.0 8.7 HIGH,向量 AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N——只有机密性受影响,读得到、改不了。

攻击链:OWL 的 agent 在做研究任务,抓了一个网页或一条搜索结果。这段内容里藏着一句话,大意是「相关细节见 http://169.254.169.254/latest/meta-data/iam/security-credentials/」。agent 分不清这是页面作者写给它的指令还是页面本身的内容,于是老老实实调用 extract_document_content 去取这个 URL。而这个工具(owl/utils/document_toolkit.py)对 URL 不做任何 scheme / host / IP 过滤:不拦 loopback(127.0.0.1)、不拦 RFC1918 私网段(10.x、192.168.x)、不拦 169.254.169.254 这类云厂商元数据地址,重定向之后也不重新校验。取回来的内容直接进 agent 的上下文,也就是进了对话历史——攻击者只要能让 agent 把这段内容再说出来或再发出去,内网服务的响应就漏了。169.254.169.254 是 AWS/GCP 虚拟机上的元数据端点,从机器内部访问它可以拿到临时 IAM 凭证,所以这条链的终点通常不是「看到一个内网页面」,而是「拿到云账号的一把钥匙」。

模型在链里的那一环:模型是那个把攻击者的意图翻译成一次函数调用的部件。工具本身只接受「调用方给的 URL」,谁都能填;能让攻击者填进去的唯一通道,就是模型读了不可信文本之后自己决定去抓。

修在哪一层:GitHub issue #615 目前是 open,没有关联 PR,也没有修复版本。issue 里提的建议是在发请求前解析 host、拒掉 loopback / private / link-local 网段和云元数据域名——这是出口侧的 SSRF 过滤。入口侧(模型会被网页里的一句话说服)没有任何改动,也基本没法在这一层修:过滤 URL 是可判定的,判断「这句话是不是指令」不是。

CVE-2026-85694 · LaVague 0.2.35

披露日 2026-09-04。材料给的是 8.1 HIGH;NVD 记录的 CVSS 4.0 是 9.2 CRITICAL,向量 AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H——机密性、完整性、可用性全高,但攻击复杂度 H、还带 AT:P(需要特定条件配合),因为攻击者得先把模型稳定地引导到输出可执行代码。

攻击链:LaVague 是浏览器自动化 agent——你说「去这个站点把商品价格填进表单」,它读页面、让模型生成一段 Selenium 风格的 Python 动作代码,然后执行。问题出在 PythonFromMarkdownExtractor.extract_as_object:它从模型回复的 markdown 里抠出代码块,用 eval 求值。而模型的输入里包含攻击者控制的网页正文。于是恶意页面上藏一段话,把提取模型引导到输出一个 Python 代码块,这段代码就在操作员本机上跑起来——LaVague 跑在谁的机器上,谁的 API token、浏览器 cookie、本地配置就在射程内。报告人 geo-chen 于 2026-06-12 提交 issue #650。

模型在链里的那一环:模型是代码的生成者,而框架把「模型的输出」当成了可信来源。eval 的输入不是用户输入、不是网络输入,是模型 token——这条链成立的全部前提,就是有人默认模型输出等于自己写的代码。

修在哪一层:issue #650 提到有关联的 PR #651,但 issue 页面上没有维护者回复,也没查到明确的修复版本号。issue 里给的建议是把 eval 换成安全反序列化:ast.literal_eval 只认字面量(数字、字符串、列表、字典这些),json.loads 只认 JSON 合约——即执行层收紧。入口侧(网页能左右模型输出什么)没修。

CVE-2026-40502 · HKUDS OpenHarness(agent gateway)

披露日 2026-04-16(VulnCheck advisory 上写的是 4 月 15 日)。CVSS 3.1 8.8 HIGH,向量 AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H——PR:L 意味着攻击者要先有一个能聊天的账号。CWE-862 Missing Authorization。

攻击链:OpenHarness 的 gateway 让你从远程(比如一个聊天前端)给本机跑着的 agent 发消息。有些斜杠命令本来只该在本地终端里敲,比如 /permissions full_auto——这是 agent 的权限档位开关,切到 full_auto 之后 agent 执行工具(跑命令、写文件)不再逐次向操作员要批准。gateway handler 没把「仅本地」和「远程可用」这两类命令分开,于是任何有聊天权限的远程用户直接把 /permissions full_auto 打进聊天框,就把别人机器上正在运行的 agent 调成了全自动,操作员完全不知情。之后再正常地给它派活,那些活就不再有人过目。

模型在链里的那一环:这条链里模型不是被攻破的对象,被攻破的是「模型自主执行的那道闸」。/permissions full_auto 这个命令本身只在 agent 语境里存在——它调的是「模型决定要调用工具时,还需不需要人点头」。脱开 agent,这个命令没有对应物,被拿掉的授权检查也无从谈起。

修在哪一层:修在 commit dd1d235450dd987b20bff01b7bfb02fe8620a0af(PR #127),做法是在 gateway handler 里补上本地/远程命令的区分与授权检查。这一起没有「入口侧」问题——它不依赖提示注入,纯粹是通道授权。VulnCheck 给的临时缓解是别把 gateway 聊天接口暴露到不可信网络。

CVE-2026-40515 · HKUDS OpenHarness(内置 grep / glob 工具)

披露日 2026-04-17。材料给的是 7.5 HIGH;VulnCheck 与 NVD 标的 CVSS 4.0 是 8.7 HIGH。CWE-863 Incorrect Authorization。报告人同为 Chia Min Jun Lennon。

攻击链:OpenHarness 允许你配路径规则,限定 agent 只能在某个项目目录里活动。但权限检查器的路径规整(normalization)做得不全——把 ..、符号链接、不同写法的绝对路径折算成同一个规范路径这一步有缺口。于是通过内置的 grep 和 glob 工具传一个敏感的 root 参数(比如指向 ~/.ssh 或家目录),这个 root 没有被拿去和配置的路径规则正确比对,工具照样列目录、照样把匹配到的行读回来。结果是配了路径限制也没用:私钥、配置文件、目录结构都能读出去。advisory 特别指出这在把 OpenHarness 暴露到网络的部署里是「远程可达的权限绕过」。

模型在链里的那一环:grep 和 glob 是 agent 的内置工具,参数由模型在工具调用里填。被绕过的那套路径规则,存在的理由就是「agent 会自己决定去读哪些文件,所以得先画个圈」。这个攻击面完全长在 agent 的工具调用体系上——没有 agent,就没有这个需要在每次调用时临场判定的权限检查器。

修在哪一层:修在 commit bd4df81f634f8c7cddcc3fdf7f561a13dcbf03ae,补的是权限检查器的路径规整。同样不涉及提示注入——但值得注意的是,如果 agent 处理了不可信内容(比如读了一个含注入的 README),模型就是那个被驱使去填 root 参数的部件,而这一侧没有防线。

已核实来源


本文由自动化管道生成(采集 → 逐字核验 → 模型撰写),未经人工改写。