Make Origin validation opt-in in the app factories (keep Host validation on for localhost)
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 45/100
Hướng nghiên cứu
The change is in TransportSecurityMiddleware, likely in mcp/server/transport_security.py or a similar module. Start by reading the middleware's current Host and Origin validation logic. The fix involves making Origin validation conditional on a non-empty allowed_origins list and removing default localhost allowed_origins in MCPServer and lowlevel.Server. Test with browser extension clients to verify Origin headers no longer cause 403 errors. Update docs/run/deploy.md to reflect the new behavior.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Description
When enable_dns_rebinding_protection=True, TransportSecurityMiddleware checks Host and Origin together. It can't do one without the other, and an empty allowed_origins means any request that carries an Origin header is rejected. MCPServer and lowlevel.Server also turn this on by default for localhost binds, with a localhost-only allowed_origins.
This blocks browser-based MCP clients such as extensions. A Chrome extension sends Origin: chrome-extension://<id>. The same request with the same credentials gets 200 without an Origin header and 403 with one. The only fix is for every server operator to allowlist each client by hand.
The Origin check doesn't add rebinding protection. The DNS-rebinding advisory (GHSA-9h52-p55h-vw2f) is closed by the Host check. An Origin check is a CSRF control, and it only matters when the server accepts credentials the browser sends automatically, such as cookies. The full threat model is in modelcontextprotocol/modelcontextprotocol#3370.
The Go SDK made this change already. Host protection on loopback is on by default. Origin protection was on by default in v1.4.1 through v1.5.0 and has been off since v1.6.0. The setting that could restore it was removed in v1.8.0.
Proposal:
- Validate
Originonly whenallowed_originsis non-empty. An empty list means no Origin check, not reject-all. - Drop the default localhost
allowed_originsinMCPServerandlowlevel.Server. - Host validation and its defaults are unchanged. When the Origin check is on,
Origin: nullis still rejected. - Update
docs/run/deploy.mdto describeallowed_originsas the CSRF control andallowed_hostsas the DNS-rebinding control.
This doesn't reopen CSRF on unauthenticated localhost servers. The middleware already returns 400 for any POST whose Content-Type isn't application/json, and a cross-site JSON POST forces a CORS preflight. I'd add a test that pins this.
Compatibility: there are two behaviour changes, and I'd like a maintainer's view on whether a 2.x minor release is OK for them.
- Localhost servers using the defaults would no longer reject cross-origin requests that pass the Host and Content-Type checks.
- Anyone who sets
allowed_hostswithoutallowed_originswould no longer reject every request that carries anOriginheader.
In both cases, setting allowed_origins explicitly restores today's behaviour.
Further proposals
-
Scheme wildcards in
allowed_origins. Once Origin validation is opt-in, an operator who turns it on still has to list every browser-extension client by hand. That's impossible for Firefox, whosemoz-extension://<uuid>origin differs on every install. Proposal:- An entry of the form
"<scheme>://*"matches anyOriginwith that scheme, for example"chrome-extension://*"or"moz-extension://*". - Exact entries and the existing
:*port wildcard keep working as today. "http://*"and"https://*"raise aValueError, because they would allow every website. Leavingallowed_originsempty already does that.- This would build on the fix for #3463 (the
:*suffix bug), since it touches the same matcher.
- An entry of the form
-
A machine-readable reason in the rejection body. Today a Host rejection is
421 Invalid Host headerand an Origin rejection is403 Invalid Origin header, both as plain text. A client can't reliably tell these from an auth failure, so it can't tell the user that signing in again won't help. Proposal: keep the status codes, but return a JSON-RPC error body whosedata.reasoncarries a stable code:{ "jsonrpc": "2.0", "error": { "code": -32000, "message": "Invalid Origin header", "data": { "reason": "invalid_origin" } }, "id": null }The reason values would match the ones the TypeScript SDK already computes internally (
missing_host,invalid_host,invalid_origin_header,invalid_origin), so clients can handle both SDKs the same way.
Disclosure: drafted with Claude Code;
- Ngôn ngữ chính
- Python
- Star
- 24.3k
- Fork
- 4k
- Merge trung bình
- 1 ngày 16 giờ
- Pull request đã merge (30 ngày)
- 25
Hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của modelcontextprotocol/python-sdk
-
v1 v2
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 70/100
modelcontextprotocol/python-sdk#3578 · 1 bình luận ·
-
v1 v2
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 65/100
modelcontextprotocol/python-sdk#3573 · 2 bình luận ·
-
v2
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
modelcontextprotocol/python-sdk#3566 ·
-
Streamable HTTP client logs a WARNING for valid 202 Accepted on session termination (DELETE) Đang mởv1 v2
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 85/100
modelcontextprotocol/python-sdk#3546 · 5 bình luận ·
-
v1 v2
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
modelcontextprotocol/python-sdk#3545 · 2 bình luận ·
Tất cả issue của modelcontextprotocol/python-sdk
Issue tương tự
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
stephrobert/dsoxlab#238 ·
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
sublimehq/package_control#1780 ·
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 65/100
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 70/100
nwg-piotr/nwg-displays#145 ·