Skills: URI traversal validation skips percent-encoded dot-segments
維護者通常 1 天內回覆
還沒有人認領這個 Issue。
評估
研究方向
閱讀 src/mcp/shared/skills.py,著重檢視 _validate_resource_uri_in_skill() 和 validate_directory_result()。先追蹤每個函式如何拆分並檢查 URI 路徑區段,再為兩條驗證路徑中的百分比編碼點區段新增回歸測試。完成標準是拒絕編碼後的 . 和 .. 區段,同時有效的資源 URI 和直接子項仍可通過。
由索引模型根據 Issue 內容生成。
描述
Initial Checks
- I confirm that I'm using the newest release of my line (the latest 2.x, or the latest 1.x if I'm still on v1)
- I confirm that I searched for my issue in https://github.com/modelcontextprotocol/python-sdk/issues before opening this issue
Release line
2.x (current stable)
Description
In src/mcp/shared/skills.py (added in #3485 for the SEP-2640 Skills extension), _validate_resource_uri_in_skill() and validate_directory_result() check for directory traversal segments against the raw URI path segments:
# src/mcp/shared/skills.py (line 253)
if any(segment in (".", "..") for segment in resource_parts.path.split("/")):
raise ValueError(f"resource URI {resource_uri!r} contains a traversal segment")
Because URI paths are not URL-unquoted prior to validation, percent-encoded traversal segments (e.g. %2e%2e, %2E%2E, or %2e) bypass this check.
Specifically:
- In
_validate_resource_uri_in_skill(), a resource URI such asskill://acme/billing/refunds/%2e%2e/other/secret.txtstarts withroot + "/"(/billing/refunds/), but its segments (["", "billing", "refunds", "%2e%2e", "other", "secret.txt"]) do not literally equal".."or".". As a result, the resource is admitted as a valid member ofskill://acme/billing/refunds/SKILL.md. - In
validate_directory_result(), line 293 checksrelative in (".", ".."). A child URI containing%2e%2eor%2ebypasses this check and is admitted as a valid direct child.
Example Code
from mcp.shared.skills import Skill, SkillResource, ReadDirectoryResult, validate_directory_result
from mcp_types import Resource
root = "skill://git-workflow/SKILL.md"
digest = "sha256:" + "a" * 64
# 1. Percent-encoded traversal bypasses manifest validation:
s = Skill(
uri=root,
frontmatter={"name": "git-workflow", "description": "d"},
resources=[
SkillResource(uri=root, digest=digest, size=10),
SkillResource(uri="skill://git-workflow/%2e%2e/evil.md", digest=digest, size=10)
]
)
# Expected: ValueError / ValidationError for traversal segment
# Observed: Accepted without error
# 2. Percent-encoded dot-segment bypasses directory validation:
res = ReadDirectoryResult(resources=[Resource(uri="skill://pdf/templates/%2e%2e", name="x")])
validate_directory_result("skill://pdf/templates", res)
# Expected: ValueError ("is not a direct child")
# Observed: Accepted without error
Proposed Fix
Normalize path segments with urllib.parse.unquote() before splitting and inspecting dot-segments in both _validate_resource_uri_in_skill and validate_directory_result.
I have a minimal regression test and fix ready and would be happy to submit a PR if this looks good.
- 主要語言
- Python
- 星號
- 24.5k
- 分支
- 4k
- 平均合併
- 18 小時 31 分鐘
- 30 天內合併 PR
- 38
環境準備
- 沒有 Dockerfile 或 Docker Compose 檔案
- 有 Pull Request 範本
- 閱讀貢獻指南
從這裡開始
- 先讀完整個 Issue,再讀專案的貢獻指南。
- 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
- Fork 儲存庫,在一個分支上完成修改。
- 送出 Pull Request,並在描述裡引用這個 Issue 編號。
modelcontextprotocol/python-sdk 的其他 Issue
-
Streamable HTTP: Content-Type handling is order dependent and accepts invalid values可能已有人在做 @jayzuccarelli 於 1 天前認領。 未關閉bug v1 v2
難度 2/5 1-3 小時 新手友好度 76/100
modelcontextprotocol/python-sdk#3691 · 1 則留言 ·
維護者通常 1 天內回覆
-
Type annotation gaps and unhandled FileNotFoundError in src/mcp/cli/cli.py可能重新可做 關聯的 PR 已關閉且未合併。 未關閉enhancement
難度 2/5 1-3 小時 新手友好度 84/100
modelcontextprotocol/python-sdk#3673 · 4 則留言 ·
維護者通常 1 天內回覆
-
Streamable HTTP server rejects a mixed-case Content-Type with 415可能已有人在做 @CRYPTONIKAV 於 3 天前認領。 未關閉bug v1 v2
難度 2/5 1-3 小時 新手友好度 75/100
modelcontextprotocol/python-sdk#3670 · 4 則留言 ·
維護者通常 1 天內回覆
-
Audio(data=b"") raises "Either path or data can be provided", while Image(data=b"") works可能已有人在做 @ajay206 於 1 天前認領。 未關閉bug v1 v2
難度 1/5 1 小時以內 新手友好度 85/100
modelcontextprotocol/python-sdk#3656 · 2 則留言 ·
維護者通常 1 天內回覆
-
enhancement
難度 2/5 1-3 小時 新手友好度 66/100
modelcontextprotocol/python-sdk#3655 ·
維護者通常 1 天內回覆
查看 modelcontextprotocol/python-sdk 的全部 Issue
相似的 Issue
-
難度 2/5 1-3 小時 新手友好度 72/100
維護者通常 1 天內回覆
-
task
難度 2/5 1-3 小時 新手友好度 78/100
danparshall/claude_researcher#87 ·
維護者通常 1 天內回覆
-
bug
難度 2/5 1-3 小時 新手友好度 85/100
datajoint/datajoint-python#1586 ·
維護者通常 1 天內回覆
-
1D intercept of length 1 is accepted as `fix_params` in population GLM with more than 1 unit可能已有人在做 @dhvani7014 今天認領。 未關閉bug good first issue
難度 2/5 1-3 小時 新手友好度 72/100
flatironinstitute/nemos#642 · 1 則留言 ·
維護者通常 1 天內回覆
-
難度 1/5 1 小時以內 新手友好度 78/100
uniswap-python/uniswap-python#487 ·