fix(claw-server): admit Electron-based MCP clients past the /mcp hygiene filter - #2536
fix(claw-server): admit Electron-based MCP clients past the /mcp hygiene filter#2536Dani Akash (DaniAkash) wants to merge 1 commit into
Conversation
…ene filter The loopback /mcp hygiene filter rejected any request carrying a `Sec-Fetch-*` header. Chromium/Electron-based desktop MCP clients (e.g. Cherry Studio) attach browser-default Fetch Metadata to every outgoing request and cannot strip it, so they were blocked with 403 "unsupported request". `Sec-Fetch-*` presence does not identify a webpage: only `Origin` does. An MCP call is a POST with `application/json`, which is never a CORS simple request, so any page capable of making one always carries `Origin`, which stays rejected. The content-type gate continues to cover the origin-less page vectors. Drop the `Sec-Fetch-*` presence check and keep the `Origin` rejection. Fixes #2458
Greptile SummaryThis PR changes the Rust loopback MCP hygiene filter to admit Electron clients that attach Fetch Metadata while retaining Origin and JSON content-type checks.
Confidence Score: 4/5The policy change appears defensible, but the shared MCP transport contract must be updated with it before merging to avoid a failing affected test suite. The Rust middleware now admits a request that the repository’s claw-mcp contract explicitly requires to return 403, creating a deterministic conformance-test failure. Files Needing Attention: packages/browseros-agent/apps/claw-server-rust/src/api/http/mod.rs; packages/browseros-agent/contracts/claw-mcp/tests/cases-transport.ts Important Files Changed
Prompt To Fix All With AI### Issue 1
packages/browseros-agent/apps/claw-server-rust/src/api/http/mod.rs:139
**Transport contract rejects admitted requests**
When the claw-mcp contract suite sends its JSON request with `Sec-Fetch-Site: cross-site` and no `Origin`, this middleware now admits it even though the shared transport contract requires a 403, causing the affected conformance suite to fail.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Reviews (1): Last reviewed commit: "fix(claw-server): admit Electron-based M..." | Re-trigger Greptile |
|
Closing: the Sec-Fetch-Site rejection here is a deliberate DNS-rebinding/CSRF defense mirrored across both MCP servers and enforced by the shared transport contract, and Electron-based clients are indistinguishable from browser attacks by that header, so this endpoint filter cannot be safely relaxed. |
❌ Tests failed: 13/756 failedRan 3 of 16 suites (13 not affected by this change).
Failed tests
|
What
The loopback
/mcphygiene filter rejected any request carrying aSec-Fetch-*header (403 {"error":"unsupported request"}). Chromium/Electron-based desktop MCP clients such as Cherry Studio attach browser-default Fetch Metadata to every outgoing request and cannot strip it, so they could not connect at all.This drops the
Sec-Fetch-*presence check and keeps theOriginrejection.Why this is safe
The filter exists to reject requests originating from a webpage, so a page the user visits cannot drive their browser through the loopback MCP endpoint.
Sec-Fetch-*presence does not identify a webpage; onlyOrigindoes:POSTwithContent-Type: application/json. That is never a CORS "simple request", so any webpage capable of making one always sendsOrigin, which stays rejected.application/jsoncontent-type gate continues to cover the origin-less page vectors (navigations, no-cors simple requests), none of which can carry a JSON-RPC body.This restores parity with the previous MCP server, which accepted
Sec-Fetch-*and rejectedOrigin, and which these clients connect to natively.Tests
mcp_hygiene_rejects_browser_originated_requests:Originstill returns403.mcp_hygiene_admits_electron_sec_fetch_clients(new): aninitializePOST carryingSec-Fetch-Site/Mode/Destand noOriginreaches the service and returns200with a session id.mcp_hygiene_rejects_non_json_writes: unchanged.Reported behavior and reproduction in #2458.
Fixes #2458