提示注入不是可以用一条正则表达式删除的格式错误请求。它是信任边界失效:本应被当作数据处理的内容改变了语言模型的行为。在 AI 代理中,这种改变可能变成工具调用、消息发送、文件写入,或者发往其他服务的请求。Model Context Protocol(MCP)让工具发现和调用更容易,却也为不可信文本提供了更多进入模型和接触特权系统的路径。
本文把 OWASP GenAI LLM Top 10 2026 应用于读取外部内容并使用 MCP 的代理。这是一份工程威胁模型和防护指南,不是安全审计。没有控制措施能够保证绝对安全。目标是承认注入有时会影响模型,让产生的动作受到限制、可以看见、能够撤销,并且难以转向攻击者目标。
为什么模型不是安全边界
LLM 会在同一个上下文中接收系统指令、用户请求、检索文档、工具描述、工具结果、对话历史和记忆。分隔符、标签和提示语可以表达信任策略,却不能创建真正的架构隔离。模型可能误解标签,把文档中看似合理的一句话当作命令,也可能把多个单独无害的线索组合成危险计划。
OWASP LLM01:2026 把提示注入定义为由直接输入、检索内容、工具输出、图像、音频、视频、中间上下文或持久记忆导致的行为改变。它与敏感信息披露、过度代理权和不安全输出处理是不同类别,但一次事件中经常会连成一条攻击链。注入提供影响,工具提供权限,秘密是需要保护的资产,网络请求、URL 或 shell 命令则可能成为数据外泄的出口。
模型不应保存凭据、决定授权,也不应成为状态变更操作的唯一校验器。这些决定应由应用程序中的确定性代码执行。让模型负责理解和规划,让周围的系统强制执行真正允许发生的动作。
MCP 代理的威胁模型
先画出真实的数据流,不要只画到聊天界面为止。列出用户、模型提供商、代理运行时、MCP 客户端和服务器、授权服务器、下游 API、浏览器、文件系统、记忆、检索索引、日志以及出站网络。标记每条连接来自用户、组织、第三方、公共来源还是未知来源。
攻击者可以是恶意网页或邮件发件人、能修改工单或代码仓库的贡献者、被入侵的依赖或 MCP 软件包、不诚实的工具运营者,或者令牌和会话标识的窃取者。正常用户也可能无意中粘贴包含其他系统指令的文档。内部数据库不会因登录保护就自动可信,记录可能来自公共表单、同步任务或被盗账号。
把资产单独列出:系统和开发者指令、访问令牌、API 密钥、个人数据、代码、私有文档、云元数据、工具配置、记忆,以及发送、删除、购买、部署或修改的能力。标记每项是否可读、可写或可被外部观察。只读工具的结果若发送到攻击者地址也会泄露。接受任意 URL 或正文的通知工具可能成为高影响出口。
为每个工作流写出容易验证的不变量,例如“总结工单但不执行工单中的指令”“只读取这个仓库”“起草邮件但未经批准不发送”。同时写出失败条件,例如工具参数中出现秘密、scope 超出任务、写入工作区之外的路径,或者连接到策略未批准的地址。
可以用五个字段记录风险:传递面、传播方式、编码、权限和出口。传递面可能是聊天、网页、PDF、MCP 描述、工具结果或记忆。传播可能跨越步骤、会话和代理。编码可以是可见文本、HTML、不可见 Unicode、低资源语言、图像、音频或混淆文本。权限是执行时的身份和 scopes,出口产生实际影响。
直接注入和间接注入
直接注入通过用户看到的输入路径进入。用户或攻击者可能要求代理忽略任务、公开隐藏指令、运行无限制命令,或调用不属于当前流程的工具。善意用户粘贴一段含有面向 AI 的指令的文本,也属于这个类别。Jailbreak 是试图绕过模型安全行为的直接注入目标,但造成代理损害不需要 jailbreak。代理礼貌地执行虚假退款指令,仍然越过了应用边界。
间接注入藏在用户没有作为指令提供的内容里。网页可能要求代理上传上下文,邮件附件可能要求重置密码,支持工单可能要求搜索私有仓库。载荷还可以放在数据库记录、issue 标题、软件包 README、图像或工具结果中。用户不一定能看见 HTML、元数据、折叠区域、图片或零宽字符中的字节。
MCP 从两个方向扩大了间接注入面。服务器会发布工具名称、描述、输入 schema、资源和 prompts,客户端再把它们放进模型上下文。被投毒的描述可能要求先调用另一工具,把秘密放入参数,或者信任攻击者提供的 URL。服务器返回结果后,模型又可能把结果当成新指令并发起第二次调用。即使 JSON-RPC 消息完全符合格式,这仍然是工具投毒或工具输出注入。
应把工具元数据看成可执行影响,而不是普通文档。固定软件包版本并验证服务器,审查描述和 schema,比较版本之间的变化,维护每台服务器获准提供的能力清单。签名可以证明来源,却不能证明固定版本没有恶意逻辑。仍然需要检查实现和网络行为。
从影响到数据外泄
提示注入在把来源和出口连接起来时才会变成泄露事件。来源可能是代理检索到的恶意 issue,出口可能是 HTTP 请求、邮件、公开评论、日历邀请、图片 URL、日志或工具参数。只要代理能读取私有数据并向外通信,攻击者就不需要直接访问这些数据。
应明确建模“致命三要素”:不可信内容、敏感数据,以及外部通信或状态变更能力。删除其中一项通常比识别每条恶意句子更可靠。研究代理可以在未登录、受限网络中浏览公共网页。私有文档总结器可以有读权限但没有网络和发送权限。邮件代理可以创建草稿,却没有发送权限。
不能只靠输出过滤。秘密可能出现在合法 JSON 字段、URL 参数、诊断消息、图片、空白字符、Unicode 或看似正常的邮件中。应在出口之前执行目标策略和信息流控制。对日志和追踪脱敏,让出站请求经过能够阻断私有地址、未知域名和异常方法的 egress 代理。
MCP 授权和 OAuth 控制
对于受保护的 HTTP MCP 服务器,要分开协议角色。MCP 服务器是 resource server,客户端代表资源所有者请求访问,authorization server 负责签发令牌。应遵循 MCP 授权规范 及与实际版本匹配的 OAuth 要求,而不要自己发明代理流程。
把令牌绑定到目标 MCP 资源。规范要求客户端在两种请求中都通过 OAuth resource 发送服务器规范 URI,并要求服务器验证令牌的目标。使用 Authorization 请求头,不要放入查询字符串。不得接受或转发其他资源的令牌。调用上游 API 时取得单独令牌。令牌透传会破坏受众隔离、限流和审计,并可能把服务器变成外泄代理。
使用 PKCE 保护授权码,严格匹配已登记的 redirect URI,在生产环境使用 HTTPS,并为每次流程生成加密随机、一次性的 state。支持动态注册客户端的代理,在转发到第三方授权服务器之前必须对每个客户端取得同意。应把同意绑定到 client ID 和请求的 scopes。不能使用只记录“用户已经同意过应用”的通用 cookie,这会产生 confused deputy 问题。
把发现流程当作服务器提供的输入,而不是可信配置。只允许 allowlist 中的安全 scheme 和 host,拒绝 javascript:、data: 和 file:。为防止 SSRF,阻断私有、loopback、link-local 和 cloud metadata 地址,检查每一次重定向,并使用出站代理。不要通过 shell 打开 URL。注入可以尝试利用其中任何一条路径。
采用渐进式 scopes。先授予发现和读取权限,只有操作需要时才请求准确的额外 scope,并用 correlation ID 记录请求集合和授予子集。避免 *、all 和全管理 scope。令牌 claims 不能替代服务端对每个工具和参数的授权。短时令牌、安全存储、公共客户端的 refresh token 轮换和脱敏日志能降低被盗后果。
本地 MCP 服务器需要另一层边界。本地进程可能拥有与客户端相同的权限,可以读取文件、访问网络和运行命令。连接前要向用户显示完整的启动命令及所有参数。优先使用 stdio 或受保护的本地 IPC,不要使用没有认证的 HTTP。把进程放入 sandbox 或容器,默认只授予最小文件、网络和进程权限,再显式授予额外目录和目标地址。
能承受绕过的分层防护
最小权限控制爆炸半径。每个代理只获得一个工作流必需的工具。把读取、起草、审批和提交拆开。使用短期、针对单次操作的凭据,而不是永久用户令牌。执行时再次检查授权,因为模型计划、会话、工具描述和资源可能在规划之后发生变化。
审批门必须是实际的策略检查点。发送、删除、发布、付款、修改权限、部署、访问新数据类别或联系新目标,都需要审批。界面要显示精确动作、参数、身份、目标、数据字段和副作用,而不是模型摘要。审批后重新生成预览,并将同意绑定到操作哈希,避免后续步骤替换参数。低风险操作可以合并,但不能让审核者习惯批准看不懂的提示。
隔离限制成功注入能触及的资源。隔离租户、会话和记忆存储。浏览代理不应拥有私有凭据。编程代理使用窄工作区,默认拒绝网络,并用独立身份安装软件包。结合进程、文件系统、网络和浏览器隔离。容器不是完整策略,还要检查挂载、socket、身份、出站规则和逃逸面。
内容来源信息让决策可以追溯。为文档、工具描述和结果附上来源、作者、获取时间、完整性和信任类别,在总结及代理交接时保留。将外部内容作为数据渲染,标记“不是指令”。标签能帮助模型,但权限必须由应用代码执行。删除或规范化边界上的不可见字符,同时承认可见、编码和多模态载荷仍可能存在。
使用可信代码验证模型输出,执行严格 schema、工具 allowlist、类型化参数、URL 和路径检查、大小与速率限制,以及每个工作流的状态机。不要把第二个模型关于安全性的意见当作授权。批评模型可以发现可疑行为,但最后的决定必须是确定性的。记录原始 prompt、检索来源、工具元数据版本、参数、策略结果、审批事件和响应,不要保存原始秘密。
对抗性评估和运行管理
评估完整的代理循环,而不是只测试聊天 prompt。准备直接覆盖指令、隐藏 HTML、引用邮件、投毒仓库文本、恶意 MCP 描述、要求第二次调用的工具结果、跨会话记忆、多语言和编码载荷、不可见字符、SSRF 地址、错误令牌受众和审批后参数替换等案例。加入看似攻击但正常的内容,分别测量误报和任务完成率。
让适应性攻击者了解分类器、标签、schema 和审批规则,改变措辞、模态、工具顺序、时机和目标。静态 benchmark 可能分数很高,但攻击者仍能寻找新路径。跟踪攻击成功率、未授权调用、到达出口的敏感字节、scope 提升、审批准确率以及发现和撤销时间。每次模型、prompt、服务器、策略或依赖变化都保留回归案例。AI 代理评估指南可以记录流程。
将架构选择与 production AI agent architecture 对照,OAuth 实现细节可参考 MCP server TypeScript with OAuth。
事件响应清单
怀疑发生注入时,先停止受影响的工作流,并禁用足以遏制事件的最小能力。保存 prompt、来源、来源元数据、工具描述和版本、参数、令牌元数据但不保存令牌值、策略决定、审批、网络目标和时间戳。判断路径是直接、间接、来自工具,还是通过记忆持久化。搜索其他租户、索引、队列、日志和代理交接中是否出现相同载荷。
撤销并轮换可能进入上下文或日志的凭据,失效会话并在需要时轮换 refresh token。阻断目标地址和受影响的 MCP 服务器。检查下游 API 是否出现未经授权的读取、写入、消息和 OAuth grants。核对实际执行参数是否与用户看到并批准的预览完全一致。
遏制之后,删除被投毒的记忆和检索记录,恢复可信元数据,把攻击路径加入回归测试。记录模型看到的内容、策略允许的动作、用户批准的动作和失效控制。如果数据越过边界,通知事件响应和隐私负责人。分类器事后识别文本,并不能让事件无害。
防护不能承诺什么
提示注入仍在演变,因为当前模型没有对指令和数据实施形式化分离。训练、分类器、分隔符、来源标签、输出 schema 和人工审查都能降低风险,但适应性攻击者可以改变词语、编码、顺序、时机和模态。人工审批会受到疲劳、错误上下文和误导性预览影响。配置错误的 sandbox 和含有恶意逻辑的合法固定版本软件包也会造成问题。
不能诚实地说代理对提示注入免疫。可以说某个工作流有明确的信任边界、最小能力、确定性检查、可观察决策、经过测试的失败模式和演练过的响应。添加 MCP 服务器、工具、记忆、模型、数据源或出站通道时,应重新评估这些假设。本文是工程指导,不是认证或安全审计。