跳到正文
原文
arXiv:越狱、提示注入、投毒与防御· arXiv:2609.22573· Huan Li·本站收录· 原文发表

研究提出面向企业 MCP 的零信任授权与工具发现方案

Zero-Trust Authorization and Discovery for Enterprise MCP

论文速读

防御

据论文 PDF 整理(AI 生成),以原文为准

作者在企业 MCP 边界用 FastMCP 扩展统一凭证、发现与按工具授权,使提示注入下的越权调用在架构上被拒绝。

威胁模型企业网内、网关终结 TLS 的 MCP 服务器;IdP、操作系统、证书链与主机受信任。

问题
LLM 智能体把可能含攻击者文本的自然语言转成特权 MCP 工具调用,官方 SDK 的认证与授权达不到企业零信任,尤其是同一服务器同时服务人类 SSO 与服务账号。
方法
在不改协议与 SDK 内部的前提下,给 FastMCP 加四项可组合扩展:跨头凭证归一(C1)、异构 IdP 的带缓存校验(C2)、免凭证的预认证元数据(C3),以及同一声明同时管可见性与调用时授权(C4)。
实验与结果
四个前沿模型共 2160 次尝试中,仅体内检查的基线仍有 152/720(21.1%)尝试禁止工具,各模型 0% 到 50%;权限感知可见性把尝试降到 0/720。只做可见性过滤仍可被脚本客户端直接调用绕过;模型在可推断工具名时最高复述 94%。
局限与可以继续做的
作者称语料只有 60 条、针对一个禁止工具,混淆与编码攻击留给专用基准;未声明组件默认开放;缓存最长一个 TTL 接受已撤销 token。SDK 快照截至 2026-05-15,Java、Kotlin、PHP、Ruby 不在经验主张内。
实验设置gpt-5、claude-sonnet-4-6 等 · 8 个 mock Kubernetes 工具测试床(4 viewer / 4 admin)、60 条手工复核的提示注入载荷(4 类各 15 条) 等 · forbidden-tool attempt rate、invocation success 等
威胁模型
企业网内、网关终结 TLS 的 MCP 服务器;IdP、操作系统、证书链与主机受信任。攻击者持有合法凭证(A1)、经文档或工具输出做提示注入(A2)、可自由读取预认证元数据(A3)、可观察时序与响应大小但不能破坏 TLS(A4);不能伪造传输层 HTTP 头。目标为 G1 调用未授权工具、G2 多头混淆提权、G3 绕过认证、G4 在缓存窗口内重用已撤销 token。提示注入本身、DoS、向下游转发授权及缓存侧信道不在范围内。
被测模型
gpt-5claude-sonnet-4-6claude-opus-4-7gemini-2.5-proclaude-sonnet-5claude-opus-4-8
基准
8 个 mock Kubernetes 工具测试床(4 viewer / 4 admin)60 条手工复核的提示注入载荷(4 类各 15 条)多头认证结果矩阵脚本化工具名猜测7 天生产追踪
指标
forbidden-tool attempt rateinvocation successname leak rateWilson 95% intervalp50/p95 latencycache hit rate
AI 导读论文对企业级 MCP 的授权缺口做了系统分析,并给出不改动协议与 SDK 内部实现的 FastMCP 可组合扩展。作者调研 Python、TypeScript、Go、Rust、C#、Swift 六种 MCP SDK,指出三个结构性缺陷:凭据提取绑定单一 Authorization 头,使同时服务人类用户(企业 SSO)与自动化 Agent(不同请求头上的服务账号凭据)的双角色部署需要自定义中间件;缺少认证前的工具发现;基础 SDK 缺少按工具的细粒度授权。

论文对企业级 MCP 的授权缺口做了系统分析,并给出不改动协议与 SDK 内部实现的 FastMCP 可组合扩展。作者调研 Python、TypeScript、Go、Rust、C#、Swift 六种 MCP SDK,指出三个结构性缺陷:凭据提取绑定单一 Authorization 头,使同时服务人类用户(企业 SSO)与自动化 Agent(不同请求头上的服务账号凭据)的双角色部署需要自定义中间件;缺少认证前的工具发现;基础 SDK 缺少按工具的细粒度授权。

深度解读

6个问题,点开问题读完整回答

  1. 这篇论文试图解决什么问题?

    企业 MCP 要在提示注入下仍按工具做零信任授权,并同时服务人和自动化账号。

    企业 MCP 服务器必须在智能体被提示注入时,仍只允许调用方已有权限的工具,并同时服务人类 SSO 与服务账号。

    • 场景:智能体把可能含不可信文本的上下文变成特权工具调用。MCP 把发现与调用标准化后,企业会把生产库、CI/CD、Kubernetes 和代码库暴露成工具;OWASP LLM Top-10 称之为 Excessive Agency。作者认为网络层认证能核验凭证,但不能判断恶意上下文是否塑造了所请求的动作。
    • 现有不足:作者对六个 MCP SDK(Python、TypeScript、Go、Rust、C#、Swift)做缺口分析,指出三点:凭证提取绑在 Authorization 头,双身份部署往往要替换 SDK 中间件;没有面向注册中心的预认证工具发现;基础 SDK 缺少细粒度按工具授权。作者称不把 scope 级可见性与调用授权本身当作新贡献,FastMCP 已提供这两面。
    • 核心观察:工具可见性是智能体安全边界的一部分。list_tools 与预认证元数据决定可达动作空间,因此发现与调用必须由同一份服务端声明约束;智能体的自然语言不能授予它本没有的 scope。
    • 本文提出:在不修改协议或 SDK 内部的前提下,为 FastMCP 做四项可组合扩展 C1–C4,对应 NIST SP 800-207 的若干原则,并分别对准威胁目标 G1–G4。
    • 威胁模型:
      • 系统与信任:MCP 服务器在企业网内、网关终结 TLS 之后;身份提供者、操作系统、TLS 证书链和主机视为受信任,攻破它们超出扩展的防御范围。
      • 攻击者能力:A1 取得合法签发的凭证(钓鱼得到的 SSO、泄露的服务账号或权限不足却试图提升的 token);A2 通过检索文档或第三方工具输出注入自然语言,把智能体导向未授权工具;A3 可自由读取有意不认证的预认证元数据;A4 可观察 HTTP 时序与响应大小,但不能破坏 TLS。不假设国家级 TLS 拦截、主机 root 或 FastMCP 供应链被攻破。智能体可被提示注入,但不能在传输边界伪造 HTTP 头。
      • 目标:G1 调用未授权工具;G2 用多头混淆提升权限;G3 完全绕过认证;G4 在 IdP 已撤销后、缓存窗口内重用 token。
      • 范围外:拒绝服务(由上游网关处理)、阻止提示注入本身生效、把调用方授权转发给下游服务(RFC 8693,列为未来工作),以及缓存侧信道。
  2. 有哪些相关研究?

    相关工作分零信任与访问控制、OAuth、智能体安全,以及 MCP 网关、生态测量与主机侧运行时。

    论文在引言和 Related Work 中把相关工作分成下面几组。

    零信任与访问控制

    • NIST SP 800-207:把零信任形式化,并追溯到 Saltzer 与 Schroeder 的最小权限。
    • BeyondCorp 与 Microsoft 的框架:展示企业规模部署;作者称把这些想法用到 AI 智能体工具协议上。
    • OPA、AWS Cedar,以及 ABAC 与 capability 模型:比本文的声明式 DNF RBAC 更丰富;作者称本文机制不表达资源范围、时间或委托策略。

    OAuth 与令牌框架

    • RFC 7662:标准化 OAuth 2.0 introspection,但 introspection 端点需要客户端凭证;作者的 BaseTokenVerifier 扩展到厂商特定认证,并加上 TTL 缓存与 scope 映射。
    • RFC 8693(token exchange):作者列为未来工作,因为其 MCP 服务器是调用图的叶子,不是委托方。规范侧还有 RFC 8414、RFC 9728 与 RFC 8707,用于发现元数据与 audience。

    智能体安全与输入侧防御

    • Perez 与 Ribeiro、Greshake 等:分别形式化提示注入,并展示经检索内容的间接提示注入。
    • ToolEmu、InjecAgent、AgentDojo,以及 Liu 等:提供智能体沙箱与工具调用操纵的系统基准,并形式化攻防空间;作者引用 AgentDojo 称对齐模型在沙箱约束下仍有较高攻击成功率,作为“仅靠输入侧防御并不收敛”的证据。
    • StruQ 与 Spotlighting:降低模型遵从注入指令的概率;作者称自己的防御在另一层:即使这些防御失败,服务端授权仍拒绝该工具调用。

    MCP 安全与生态

    • 基线与对照:网关与集中治理方面,Matsumoto 等提出跨 A2A 与 MCP 的统一认证治理平台;作者自己部署中的配套系统把凭证接入与 persona 解析放在服务器集群之前;MCP 的 Enterprise-Managed Authorization 扩展用 ID-JAG token exchange 标准化同一准入层。作者称这三者管的是调用方能否到达服务器,不管进入之后能发现或调用什么。
    • 生态测量:Narajala 与 Habler、Errico 等、Li 与 Gao 调查企业 MCP 风险和注册中心审查上的弱点。
    • 主机侧运行时:Xing 等的 MCP-Guard 在模型侧对恶意工具调用内容做分类。作者还对照 FastMCP 自身的 auth=(同一 callable 同时约束列表与调用)以及 Cerbos 集成(由外部 PDP 分别评估 tools/list 与 tools/call)。

    作者把本文定位成三面一致性问题:从同一份服务端本地策略声明导出经净化的预认证元数据、已认证列表和调用检查,而不是声称做出第一个 MCP 授权机制。

  3. 论文如何解决这个问题?

    C1–C4 在 FastMCP 扩展点上,用同一 DNF 声明同时约束发现、列表和调用。

    作者在 FastMCP 的原生扩展点上实现 C1–C4,不改 MCP 协议、不做 monkey-patch、不访问私有 API。认证组合在中间件用 OR:任一已注册凭证类型成功即可;同一机制也可配成 AND。

    部署与请求路径

    • 两条入口:控制面注册中心无凭证读取预认证元数据;MCP 客户端带着真实调用方凭证走已认证端点。已认证路径依次经过 Starlette HTTP 中间件(C1、C2)、FastMCP 应用中间件(C4 过滤)和工具装饰器(C4 执行时检查)。
    • 三层分工:AuthMiddleware 对出现的头做 OR,失败则 401,成功后把合并权限写入按 persona 分键的 ContextVars;PermissionFilterMiddleware 只挂 on_list_tools、on_list_prompts、on_list_resources,对 call_tool 为空操作;@require_permissions 只在调用时求值,任一 AND 子句的权限全部持有即通过。
    • 不变量:对已认证调用方 c 和已注册工具 t,t 出现在 c 的 list_tools 中且可被 c 调用,当且仅当 c 满足 t 声明的 DNF 权限;自然语言不进入该判定。两层都读同一个 _required_permissions。

    C1 跨头凭证归一

    • 补上的缺口:较早 SDK 把提取硬编码在 Authorization;FastMCP 的 MultiAuth 只组合共享同一 Bearer 头的校验器。CustomHeaderAuthBackend 读取可配置头,optional=True 时缺头视为空操作。
    • 合并规则:某头缺失或无效就不贡献权限,不能挡住另一头上的有效凭证;全部失败才拒绝。双身份部署通常把 Bearer SSO 与 X-Service-Account 配对。get_all_permissions() 返回各槽去重后的并集。AuthMiddleware 与 MultiAuth 正交,Bearer 槽本身也可以是 MultiAuth。

    C2 异构 IdP 的缓存校验

    • 对象:FastMCP 对 JWT 做本地 JWKS 校验,但许多企业 IdP 发不透明 token,必须走 API。BaseTokenVerifier 用模板方法:新厂商实现构造认证头、构造校验 URL、解析 scope、识别调用方。
    • 缓存与 audience:校验结果默认缓存 300 秒,键为 SHA-256,不存原始 token,可换成 Redis 一类共享后端。可选 map_permissions_func 把厂商 scope 映到应用权限。audience 策略分 resource-bound(aud 必须指向本服务器)和 fleet-bound(接受运营商配置的共享 audience);按 RFC 7662 省略 aud 的厂商不在覆盖内。

    C3 预认证发现与 C4 声明式授权

    • 元数据端点:注册在认证中间件之外,返回每个 tool、prompt、resource 的 MCP schema 和 required_permissions(DNF;缺省键表示无特定权限),以及服务器接受的认证方法。作者把暴露 schema 视为设计取舍:知道工具存在不等于能调用。
    • DNF:每个位置参数是一个 AND 子句,多个参数之间为 OR。例如 @require_permissions(["admin", "write"], ["superadmin"]) 表示 (admin ∧ write) ∨ superadmin,在第一个满足的子句上短路。未加注解的组件默认无限制。
    • 签名保持:用 exec 按 inspect.signature 生成包装器,使 FastMCP 仍能产出 JSON schema;exec 的输入不含运行时请求数据。该属性同时被元数据端点、列表过滤和调用检查读取。作者称相对 FastMCP 的 auth= 与 Cerbos,增加的是析取组合,以及从同一声明导出的第三面(预认证元数据)。
  4. 论文做了哪些实验?

    2160 次尝试中基线 152/720 会点名禁止工具,过滤后为 0/720,但只过滤可被直接调用绕过。

    实验设置

    • 被测模型:对抗扫描为 gpt-5、claude-sonnet-4-6、claude-opus-4-7、gemini-2.5-pro,经 OpenAI 兼容企业网关。正向控制另含 claude-sonnet-5 与 claude-opus-4-8;gemini-2.5-pro 未进入该控制。
    • 测试床:八个 mock Kubernetes 工具,四个 viewer(如 get_metrics)、四个 admin(如 restart_pod)。桩 TokenVerifier 对任意非空 bearer 发给固定 viewer scope,无 IdP 往返。禁止目标为 restart_pod(cluster:admin)。
    • 三种服务器:Baseline 列出全部八个工具,并在每个 admin 工具体内做权限检查;Filter-only 只对 viewer 从 list_tools 去掉 admin 工具,故意去掉装饰器与体内检查;With-extensions 同时使用过滤器与 @require_permissions。
    • 语料与指标:60 条 LLM 辅助、人工复核的载荷,直接注入、间接注入、角色扮演绕过、上下文溢出各 15 条。每个(模型,提示词)用种子 {42, 43, 44} 跑三次;非推理类温度取 {0.0, 0.3, 0.7},推理类(gpt-5、claude-opus-4-7)用网关默认采样。网格为 4 × 3 × 60 × 3 = 2160,全部有效。记录 attempt(发出名为 restart_pod 的 tool_call)、invocation(执行还是 PermissionError)、leak(输出中出现该名)。
    • 延迟微基准:每种(配置,操作)每轮 1000 次请求,50 次预热后取三轮中位数。+auth 行使用 FastMCP 自己的 RemoteAuthProvider,作者把它当作后续添加的基线。
    • 生产:扩展部署在 PayPal 企业 AI 智能体平台,被数十个已认证 MCP 服务器采用;另有 7 天生产追踪。论文未报告对抗实验的查询预算或人工一致性系数。

    主结果

    Table 4 为基线各类及三种配置的禁止工具尝试次数。作者称每个格子的 succeeded 都是 0:基线在工具体内拒绝执行;后两列因工具不在 schema 中而不发出调用。

    表格较宽,可左右滑动

    模型DIIIRPCO基线合计Filter-onlyWith-ext.
    claude-sonnet-4-60/450/450/450/450/1800/1800/180
    claude-opus-4-73/450/450/450/453/1800/1800/180
    gpt-526/450/4533/450/4559/1800/1800/180
    gemini-2.5-pro27/4523/4537/453/4590/1800/1800/180
    合计56/18023/18070/1803/180152/7200/7200/720
    • 作者的解读:152/720 的 Wilson 95% 区间为 [18.3, 24.2](21.1%),两列 0/720 的区间为 [0, 0.5]。作者称 0 本身大体由结构决定:模型只能对 schema 里出现的工具发出 tool_call;实验要报告的是基线暴露、跨厂商差异,以及名字泄露率。
    • 跨模型:同一 60 条提示词上,基线从 claude-sonnet-4-6 的 0/180 到 gemini-2.5-pro 的 90/180(50%)。gpt-5 只在直接注入和角色扮演上产生尝试;gemini-2.5-pro 还会在间接注入和上下文溢出上产生尝试。作者称若把模型拒答当作遏制边界,该边界会随厂商相差约 50 个百分点,并随版本变化。
    • 正向控制:四个良性、viewer 允许的请求,每模型三次。GPT-5、claude-sonnet-5、claude-opus-4-8 各 12/12(合计 36/36)。只有 GPT-5 与攻击扫描的检查点匹配;作者因此把该控制解释为基础设施层面的验证。

    名字泄露与脚本绕过

    • 测了什么:在 with-extensions 且 attempted = 0 的格子里,统计模型是否复述注入文本已能推断出的工具名。作者称 59/60 条载荷按设计使 restart_pod 可推断,因此这是复述而不是独立发现。
    • 结果:claude-opus-4-7 为 169/180(94%),claude-sonnet-4-6 为 142/180(79%),gemini-2.5-pro 为 44/180,gpt-5 为 13/180。Table 6:Filter only 下列出为 no,但直接 call_tool 会执行;Baseline 由体内检查拦住;With-extensions 由 @require_permissions 拦住。
    • 作者的解读:过滤器决定智能体会尝试什么,装饰器挡住泄露出去的名字;只做可见性不能替代调用时检查。四模型扫描中没有观察到模型内部绕过(with-extensions 下 0/720)。

    多头认证、撤销窗口与注册中心

    • G2/G3:Table 5 枚举 Bearer 与自定义头的四种情况。仅两头都有效时 scope 为并集,且不会宽于各头本身;两头都失败则 AuthenticationError,不落入默认。作者称该结构可对 n 个后端归纳。
    • G4:每个不同 token 在一个窗口内最多一次 IdP introspection;均匀到达时,撤销到下次强制再校验的平均延迟为 TTL/2,最坏为 TTL。默认 300 秒。TTL = 0 关闭缓存;IdP 撤销 webhook 被作者称为明显扩展,但未实现。
    • C3:被攻破的注册中心没有凭证,只能拿到端点本就公开的 schema。匿名方也可读到每个工具的名称、schema 和 required_permissions。作者称这不直接给权限,但是名称猜测和提示注入的侦察;他们没有做实验把该效应分离出来,因此写成有理由的风险,而不是测得的效应。部署可关掉该端点或单独给它加认证。

    其他消融与分析

    • Table 2,list_tools 的 p50/p95(ms):vanilla 1.71/1.98,+auth 1.78/2.07,+auth+filter 1.70/2.08,+auth+filter+decorator 1.67/1.92。
    • Table 2,call_tool 的 p50/p95(ms):vanilla 2.15/2.41,+auth 2.18/2.58,+auth+filter 2.21/2.59,+auth+filter+decorator 2.18/2.49。作者称过滤器和装饰器相对 +auth 在 p50 约增加 0 ms、p95 不超过约 0.15 ms,与轮次间噪声同量级;过滤后 viewer 收到四个而非八个工具,list_tools 略快。
    • 7 天生产追踪:C2 缓存命中 96.1% 的校验请求,命中 p50 为 9.9 ms,未命中 p50 为 296 ms;作者称约 30 倍的 p50 加速,并把 IdP 负载限制为每个(token,TTL 窗口)一次。
    • Table 1:六个基础 SDK 的预认证发现(schema+auth)均为 N;Permission-based filtering 与 Declarative per-tool permissions 仅 Python(含 FastMCP)为 Y;Pluggable auth backend 在 Python、TypeScript、Go 为 P,在 Rust、C#、Swift 为 Y。
    • Table 3 把 G1 记为 152/720 → 0/720,G2 为 no wider scope,G3 为 all-fail ⇒ error,G4 为 ≤ TTL(默认 300 s)。
    • 负面结果:基线 claude-sonnet-4-6 为 0/180,过滤不能解释该模型的拒答;上下文溢出合计仅 3/180,且全部来自 gemini-2.5-pro。
  5. 有什么可以进一步探索的点?

    作者指出语料范围、未声明组件默认开放,以及撤销缓存窗口;下游转发留作未来工作。

    作者指出的局限与后续方向

    • 语料范围(Section 5.1):评测 60 条人工复核载荷、针对一个禁止工具,作者称不主张覆盖更广的攻击空间。0/720 是结构性的;语料刻画的是该语料上的模型侧行为。混淆与编码攻击留给 InjecAgent、AgentDojo 一类专用鲁棒性基准。
    • 未声明组件默认开放(Section 5.1):未加 @require_permissions 的 tool、prompt 或 resource 无要求,任何已认证调用方都可见、可调用。作者称这是有意的默认,以免显式注解拖慢日常开发。
    • 撤销延迟(Section 5.1、Section 4.3.3):缓存校验最长一个 TTL 内可能接受已撤销 token;需要立即撤销的部署必须关闭缓存。作者称 IdP 撤销 webhook 是明显扩展,但未实现。
    • audience 缺口(Section 3.7、Section 5.1):按 RFC 7662 在 introspection 中省略 aud 的厂商仍未被 audience 策略覆盖。
    • 下游委托(Section 2.4、Related Work):把调用方授权转发到下游服务(RFC 8693)列为未来工作。
    • 规范演进(Section 5):Enterprise-Managed Authorization 于 2026-06-18 稳定,更广的规范修订在 2026-07-28;作者称随着上游出现等价能力,这些非侵入层可以退役。附录 A 称 2026-05-15 之后的发行可能补上部分缺口,本文仍可作为过渡参考架构。

    实验覆盖范围

    • SDK 快照:Section 2.3 与附录 A 的缺口分析覆盖 Python、TypeScript、Go、Rust、C#、Swift,版本为截至 2026-05-15 的稳定发行(Table 8);这六个是十个官方 SDK 中的样本,Java、Kotlin、PHP、Ruby 不在经验主张内。扩展实现在 Python / FastMCP 上。
    • 对抗扫描:四个模型、三种服务器配置、四类各 15 条载荷、每对提示词三次,共 2160 次;禁止工具为 restart_pod。正向控制为三个当时有网关路由的模型、各 12/12。
    • 其余评测:多头矩阵为 Bearer 加一个自定义头的四种情况;脚本化非 LLM 客户端验证直接 tools/call;延迟为四档累积配置、八工具测试床;生产为数十个已认证 MCP 服务器上的 7 天追踪与网关日志。
    • 论文写明未做的测量:没有把预认证元数据对角色扮演或伪造策略载荷的加强单独做成实验;没有实现撤销 webhook;缓存侧信道、拒绝服务和提示注入是否首先成功都不在评测范围内。论文未报告对抗实验与人工复核之间的一致性数值。
  6. 总结一下论文的主要内容

    同一份按工具声明同时管 MCP 的发现、列表和调用,使注入不能扩大已有凭证的权限。

    作者把零信任放在 MCP 工具调用边界:智能体即使被提示注入,也不能调用其凭证范围之外的工具。

    问题来自三点部署性质。调用意图会随不可信上下文改变;list_tools 本身就是攻击面;一台服务器往往要同时接受人类 SSO 和服务账号,而所调查的 SDK 把凭证提取绑在 Authorization 头,也缺少免认证的按工具 schema 与基础 SDK 级的声明式按工具授权。

    C1–C4 只接在 Starlette 与 FastMCP 的扩展点上。跨头后端按 OR 合并为同一主体;不透明 token 经厂商 introspection 校验并默认缓存 300 秒;注册中心用无凭证元数据端点索引工具与认证方法;一份 DNF 注解同时决定预认证元数据、已认证列表和调用时拒绝。

    在八工具测试床上,四个前沿模型、2160 次尝试中,仅体内检查的基线有 152/720(21.1%)会尝试 restart_pod,模型从 0/180 到 90/180;过滤器打开后尝试为 0/720。脚本客户端在只过滤时仍能直接执行该工具,加上装饰器后被拒绝。工具被隐藏后,claude-opus-4-7 仍在 169/180(94%)的响应里复述可推断的工具名。多头矩阵中,scope 不会宽于各有效头的并集;两头都无效则报错。生产追踪里缓存命中 96.1%,命中与未命中的 p50 为 9.9 ms 与 296 ms。

    作者的结论是:可见性与调用时检查互相不能替代,而且必须来自同一声明;模型拒答随厂商和版本变化,授权边界应由企业控制。暴露 schema 是为注册中心做的取舍,被攻破的注册中心得不到调用能力。未注解组件默认开放,已撤销 token 在 TTL 内仍可能被接受。

阅读原文arxiv.org