Skip to content

MCP OAuth 完整 scope 模型 = 首个写操作工具的前置 DoD(含 code 连坐/client GC) #118

Open

Description

@fxbin

背景

PR #117 圆桌评审(2026-10-17,.vidt/roundtables/)裁定:四项残余风险中的轻量加固随 #117 落地,结构性项排期到本 issue,触发条件 = 首个写操作 MCP 工具立项(届时 scope 即真实写权限边界)。本 issue 即该触发器的机器化载体——写工具的 PR 必须先关掉这里的前置项。

前置 DoD 清单

1. 完整 scope 模型(4:0 排期共识)

  • scope 单一事实源:app/mcp/scopes.py 的 TOOL_REQUIRED_SCOPES 从空集升级为真实权限语义(读类 mcp:read,写类 mcp:write 等)
  • DCR ClientRegistrationOptions(valid_scopes=...) 限制可注册 scope
  • RS 端 AuthSettings.required_scopes 与工具级 required ⊆ granted 强制(闸门已在 feat(mcp): 动态 OAuth 授权(浏览器弹窗登录)——AS + 同意页 + 前端回跳 #117 落地,此处只需填语义)
  • 同意页文案从 scope 单一事实源生成,不再人工维护
  • validate_token_resource 双路径收口:带 resource 声明的 OAuth 令牌强制校验(RFC 8707),存量静态令牌以标记位豁免——别让兼容固化为永久语义

2. ③ 已消费授权码重放的连坐撤销(3:1 分歧的推迟部分)

  • mcp_oauth_authorizations 加 family 关联列(或 token 表加 authorization_id),精确连坐——注意同 client+user 多族并存,按 client+user 反查会误伤
  • load_authorization_code 识别 consumed 行 → 撤销该族全部 token
  • 善意重试豁免(可选增强):存 code_verifier 哈希,携带正确 verifier 的重试不连坐(攻击者没有 verifier)
  • 当前 feat(mcp): 动态 OAuth 授权(浏览器弹窗登录)——AS + 同意页 + 前端回跳 #117 已落 warning 日志(泄密信号检测);本项补撤销语义

3. client 垃圾清理(2:2 分歧,采纳排期侧)

  • MCPOAuthClientRepository.delete_stale:注册后 7 天从未完成授权的 client 删除(client_id 为普通列可直删,无迁移)
  • 并入调度器 03:55 cleanup_mcp_oauth 作业 + 2 个测试

依据

  • 攻击树与协议条款论证见圆桌纪要:.vidt/roundtables/rendered/(minutes + argument graph)
  • 修复价值定位:重放连坐是泄密信号检测而非攻击阻断(PKCE 已挡无 verifier 者),写工具上线前不紧急

Activity

  1. fxbin commented on Oct 18, 2026

    @fxbin
    OwnerAuthor

    产品决策(2026-10-17,所有者拍板)

    **MCP 维持只读,不规划写操作工具。**本 issue 的触发条件(首个写操作工具立项)不预期触发,各项保持休眠;若未来方向改变,DoD 清单仍然有效。

    按此决策重新归置各清单项:

    • 完整 scope 模型 / validate_token_resource 双路径 / ③连坐+verifier 豁免:随触发器一并休眠——只读面上它们的收益此前已被论证为不紧急(圆桌纪要)。
    • client 垃圾清理(注册后 7 天未完成授权即删):与写工具无关的表卫生项,是本 issue 唯一仍值得按需处理的内容,可随时摘出来做进任意小 PR;不紧迫(当前 client 表只进不出,增长缓慢)。

    当前保障不变:scope 闸门 fail-closed + CI 断言工具集=登记集,任何新工具(含只读)都会被强制登记 scope。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions