Enforce permitted MCP request profiles at the forwarding boundary
还没有人认领这个 Issue。
评估
- 难度
- 5/5
- 预计耗时
- 一周以上
- 新手友好度
- 25/100
- Issue 类型
- 功能
- 描述清晰度
- 基本清楚
- 活跃度
- 停滞
- 技术栈
- rust
调研方向
先阅读 PR #3199、#3241、#3251 和 #3335 中的验收标准与实现顺序,然后审查所引用的 proof commit。只有在获准的 MCP 配置文件、batch 和 rewrite 检查、policy/storage 路径、文档、已合并的 proof、必需的检查以及人工审查全部满足所列的证据要求,且不存在未解决的正确性缺陷时,才算完成。
由索引模型根据 Issue 内容生成。
描述
User Story
As a sandbox operator, I want MCP traffic checked against an explicitly permitted request revision and my method/tool policy, so that valid supported clients work and the request reaching the upstream matches the request OpenShell authorized.
Problem Statement
MCP revisions differ in request grammar, batching, method availability and HTTP metadata. An endpoint allowlist alone does not establish which revision governs a request, whether every operation is authorized, or whether middleware preserves that decision. A version-independent parser can reject valid older traffic or accept a request shape unavailable in the selected revision.
The acceptance scope is correctness around the request OpenShell authorizes and forwards. This replaces the earlier proposal's OpenShell-owned wire registry and negotiated-session/response guarantees with the request contract below. It does not describe those broader guarantees as implemented.
Impact / Why This Matters
Unconditional MCP batch rejection breaks the March 2025 request contract; unconditional acceptance admits forms later revisions prohibit. Operators also need protection against a request being inspected under one interpretation and forwarded under another after a rewrite. Requiring a proxy session registry or extra handshake round trips would add operational burden without establishing a demonstrated requirement for the method/tool authorization boundary.
Proposed Design
An operator configures a nonempty allowlist of supported exact revisions with mcp.versions. The supported vocabulary is 2025-03-26, 2025-06-18, 2025-11-25 and opt-in 2026-07-28. Omission keeps the pinned ["2025-11-25"] default; adding support in a dependency cannot widen an existing policy.
OpenShell selects one endpoint-permitted profile for each request outside valid standalone legacy initialization. That initialization is an explicit bootstrap exception: structural inspection and endpoint method policy still apply, but the client's proposed params.protocolVersion is not treated as an effective or negotiated revision. For subsequent requests, the allowlist never unions profile grammar. The missing-header fallback for legacy requests is March 2025, which must itself be allowed; it is distinct from the policy default. July 2026 requires its sessionless request metadata and matching HTTP mirrors.
Tower owns revision-specific JSON-RPC/MCP structure, method availability, direction, typed parameters and batch grammar. OpenShell owns its supported policy vocabulary, endpoint authorization, request limits, HTTP/body consistency, audit behavior and forwarding. Typed inspection is not a claim of complete JSON-schema validation.
Every policy-relevant operation is checked, including every batch member. In enforce mode a denied member prevents forwarding the complete batch. Malformed or ambiguous protocol input remains rejected in audit mode. Unknown extensions require exact-method permission; deny rules retain precedence. Generic JSON-RPC keeps its separate policy contract.
The final forwarded representation must preserve the authorization decision. Replaced bodies are reinspected and reauthorized; final header-selected grammar and required metadata mirrors are checked before forwarding. Middleware cannot change method, path or query. Future changes that alter policy inputs must reauthorize those inputs. This does not claim arbitrary tool-argument authorization or unconditional OPA reevaluation for every header change.
Client and server retain negotiation and session lifecycle ownership. This scope does not certify initialization results, validate server response contents, correlate callbacks/resumed responses, or prove equality with an earlier negotiated revision. It also does not claim complete MIME/Accept or lifecycle conformance: legacy DELETE cleanup is unsupported. Existing response forwarding, framing and streaming behavior is preserved within the tested boundaries. Any demonstrated interpretation or forwarding bypass of the retained request contract remains a correctness defect that must be fixed before closure.
Acceptance Criteria
- Canonical revision allowlists survive all policy, provider, protobuf/storage, update, projection and activation paths without silent loss or widening.
- Outside valid standalone legacy initialization, each inspected request uses one supported permitted profile; conflicting, duplicate, unknown or disallowed selection signals fail closed. Bootstrap initialization remains structurally inspected and subject to method policy without treating the proposal as the effective or negotiated revision.
- Supported valid requests and explicitly permitted extensions work; unavailable methods, invalid shapes, ambiguous JSON and bounded-request violations are rejected.
- Enforce-mode batch denial is atomic, with valid, malformed and audit controls proving the documented behavior.
- Middleware rewrites preserve the configured method/tool policy behavior. In enforce mode, denied rewrites forward no request bytes; audit may forward otherwise valid policy-denied rewrites. Malformed or profile-invalid rewrites are rejected in both modes, and forwarded rewrites have the expected representation.
- Authenticated proxy evidence covers every supported revision and a multi-version endpoint; relay evidence covers both entry paths, bootstrap, final-request checks and relevant transport rejection cases.
- Clients require no proxy-managed session registration, added handshake round trip, manual session bookkeeping or extra version-selection knob.
- User/architecture documentation states the default, ownership boundary, audit behavior and compatibility limits consistently.
- Required implementation and proof commits are merged, required checks/reviews pass, and the final upstream source matches the acceptance evidence with no unresolved in-scope correctness defect.
Alternatives Considered
- Reject or accept batches for every MCP endpoint: either choice violates one of the supported request profiles.
- Use a
disable_batchswitch or dependency-selected defaults: these create contradictory policy settings or silently changing policy semantics. - Permit only one revision per endpoint: this excludes legitimate clients using different supported revisions at the same endpoint.
- Maintain a second MCP schema registry in OpenShell: this duplicates protocol ownership already provided by Tower.
- Enforce initialization responses and session equality now: this can detect additional server/session inconsistencies, but requires an explicit policy guarantee, correlation/state ownership and resource limits. It is separately scoped unless a concrete failure shows it is necessary for the retained authorization boundary.
Agent Investigation
The implementation sequence includes #3199, #3241, #3251 and the current #3335. The latter delegates inspection to pinned tower-mcp-types 0.22.2 and includes the canonical policy-schema integration and deterministic boundary-digest correction.
Published proof commits 5e9a833ba and d34c38946 cover atomic March batch denial, actual middleware tool rewrites and per-profile sandbox execution. The final sandbox harness executed both tests successfully. The supported November conformance scenarios passed separately; neither result establishes complete conformance across all revisions. Final-head hosted Branch Checks passed; local workspace/server verification and required human review remain in progress. Issue closure requires merged acceptance evidence, not merely this implementation status.
Checklist
- I've reviewed existing issues and the architecture docs
- This is a design proposal, not a "please build this" request
- 主要语言
- Rust
- 星标
- 8.7k
- 派生
- 1.3k
- 平均合并
- 2 天 7 小时
- 30 天内合并 PR
- 243
贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
NVIDIA/OpenShell 的其他 Issue
-
area:docs
难度 1/5 1 小时以内 新手友好度 88/100
-
state:triage-needed
难度 2/5 1-3 小时 新手友好度 82/100
-
area:cli state:validated
难度 2/5 1-3 小时 新手友好度 72/100
-
state:triage-needed
难度 1/5 1 小时以内 新手友好度 90/100
-
area:build spike state:review-ready state:stale
难度 2/5 半天 新手友好度 68/100
相似的 Issue
-
risk:low runtime status:in-progress type:test
难度 1/5 1 小时以内 新手友好度 92/100
zeroclaw-labs/zeroclaw#11023 ·
-
good first issue refactor
难度 2/5 1-3 小时 新手友好度 72/100
-
难度 2/5 1-3 小时 新手友好度 86/100
kwakseongjae/auto-hwp#319 ·
-
area:cli bug filter-quality good first issue priority:medium
难度 2/5 1-3 小时 新手友好度 84/100
-
难度 1/5 1 小时以内 新手友好度 72/100
bevyengine/bevy#25861 ·