Public mode

No access to your tenant or devices. Every item links to its source. What this means

Some sources, documents or advisories need attention: 272/272 feeds/APIs · 469/469 docs · 8/9 advisories · checked 09:38 UTC Customize Public modeDiscuss ChangeIntel on Discord

MCP Registry: Stored XSS in catalogue UI via attribute-quote breakout in publisher-controlled `websiteUrl`

Collected exploitation and prediction evidence

Risk source coverage

CISA KEV is observed exploitation evidence. FIRST EPSS is a dated prediction of exploitation in the next 30 days. Missing scores are unknown. This collector requests predictions only for explicit CVE aliases in the public NuGet archive; Microsoft release views retain their existing prediction scope.

No collected risk observation for these identifiers. This does not establish absence of exploitation or a zero probability.

cve-program · CVE-2026-44429

Published

The MCP Registry provides MCP clients with a list of MCP servers, like an app store for MCP servers. Prior to 1.7.7, the public catalogue UI served at GET / (file internal/api/handlers/v0/ui_index.html) is vulnerable to stored cross-site scripting via the server.websiteUrl field of any published server.json. Server-side validation in internal/validators/validators.go (validateWebsiteURL) only checks that the URL parses, is absolute, and uses the https scheme; it does not reject quote characters. Client-side, the value is interpolated into a double-quoted href attribute via innerHTML, using a homegrown escapeHtml helper that performs the standard textContent → innerHTML round-trip. Per the HTML serialisation algorithm, that round-trip encodes only &, <, > and U+00A0 inside text nodes — it does not encode " or '. A literal " in websiteUrl therefore breaks out of the href attribute, allowing arbitrary on* event handlers to be appended to the same <a> element. The Content-Security-Policy on / is script-src 'self' 'unsafe-inline' https://cdn.tailwindcss.com, so the injected event handlers execute. Any user able to obtain a publish token (e.g. via POST /v0/auth/github-at with their own GitHub account, or POST /v0/auth/none on a deployment that has anonymous auth enabled) can plant a poisoned record visible to every visitor of the registry homepage. This vulnerability is fixed in 1.7.7.

Source published
14 May 2026 21:05:56 UTC
Source modified
15 May 2026 14:20:27 UTC
Observed here
23 Oct 2026 15:48:27 UTC
Source terms
CVE Program Terms of Use

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: cve-program · CVE Program Terms of Use. Source text is retained; field grouping and change labels are provided by ChangeIntel.

CVSS 4.0 · 5.1 CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:P/VC:N/VI:N/VA:N/SC:N/SI:L/SA:L

euvd · EUVD-2026-30487

Published

The MCP Registry provides MCP clients with a list of MCP servers, like an app store for MCP servers. Prior to 1.7.7, the public catalogue UI served at GET / (file internal/api/handlers/v0/ui_index.html) is vulnerable to stored cross-site scripting via the server.websiteUrl field of any published server.json. Server-side validation in internal/validators/validators.go (validateWebsiteURL) only checks that the URL parses, is absolute, and uses the https scheme; it does not reject quote characters. Client-side, the value is interpolated into a double-quoted href attribute via innerHTML, using a homegrown escapeHtml helper that performs the standard textContent → innerHTML round-trip. Per the HTML serialisation algorithm, that round-trip encodes only &, <, > and U+00A0 inside text nodes — it does not encode " or '. A literal " in websiteUrl therefore breaks out of the href attribute, allowing arbitrary on* event handlers to be appended to the same <a> element. The Content-Security-Policy on / is script-src 'self' 'unsafe-inline' https://cdn.tailwindcss.com, so the injected event handlers execute. Any user able to obtain a publish token (e.g. via POST /v0/auth/github-at with their own GitHub account, or POST /v0/auth/none on a deployment that has anonymous auth enabled) can plant a poisoned record visible to every visitor of the registry homepage. This vulnerability is fixed in 1.7.7.

EUVD source date text has no stated timezone and is retained without inventing a UTC instant. Related bulletin membership is not an alias, common cause or applicability claim. A missing vector with a zero score is treated as unrated. Complete vendor/product and underlying source evidence remains in the original JSON.

Original publisher date fields

datePublished: May 14, 2026, 9:05:56 PM

dateUpdated: May 15, 2026, 2:20:27 PM

Source published
May 14, 2026, 9:05:56 PM (timezone not stated)
Source modified
May 15, 2026, 2:20:27 PM (timezone not stated)
Observed here
28 Oct 2026 06:07:35 UTC
Source terms
ENISA EUVD · source terms and attribution apply

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: euvd · ENISA EUVD · source terms and attribution apply. Source text is retained; field grouping and change labels are provided by ChangeIntel.

EUVD CVSS 4.0 · 5.1 CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:P/VC:N/VI:N/VA:N/SC:N/SI:L/SA:L

nvd · CVE-2026-44429

Published

The MCP Registry provides MCP clients with a list of MCP servers, like an app store for MCP servers. Prior to 1.7.7, the public catalogue UI served at GET / (file internal/api/handlers/v0/ui_index.html) is vulnerable to stored cross-site scripting via the server.websiteUrl field of any published server.json. Server-side validation in internal/validators/validators.go (validateWebsiteURL) only checks that the URL parses, is absolute, and uses the https scheme; it does not reject quote characters. Client-side, the value is interpolated into a double-quoted href attribute via innerHTML, using a homegrown escapeHtml helper that performs the standard textContent → innerHTML round-trip. Per the HTML serialisation algorithm, that round-trip encodes only &, <, > and U+00A0 inside text nodes — it does not encode " or '. A literal " in websiteUrl therefore breaks out of the href attribute, allowing arbitrary on* event handlers to be appended to the same <a> element. The Content-Security-Policy on / is script-src 'self' 'unsafe-inline' https://cdn.tailwindcss.com, so the injected event handlers execute. Any user able to obtain a publish token (e.g. via POST /v0/auth/github-at with their own GitHub account, or POST /v0/auth/none on a deployment that has anonymous auth enabled) can plant a poisoned record visible to every visitor of the registry homepage. This vulnerability is fixed in 1.7.7.

NVD analysis and CPE criteria are source context, not proof that a package or your environment is affected. Complete affected data, logical configurations and SSVC are retained in the original JSON.

Source analysis status: Analyzed

Weakness classifications: CWE-79 · CWE-116

Original publisher date fields

published: 2026-05-14T21:16:46.677

lastModified: 2026-10-26T14:10:00.130

1 source CPE criteria · context only
  • cpe:2.3:a:lfprojects:mcp_registry:*:*:*:*:*:*:*:*

The original JSON retains the logical configuration operators, exclusions and version bounds.

Source published
14 May 2026 21:16:46 UTC
Source modified
26 Oct 2026 14:10:00 UTC
Observed here
27 Oct 2026 11:12:09 UTC
Source terms
NIST NVD usage terms; underlying source attribution retained

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: nvd · NIST NVD usage terms; underlying source attribution retained. Source text is retained; field grouping and change labels are provided by ChangeIntel.

CVSS 4.0 · [email protected] · Secondary · 5.1 CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:P/VC:N/VI:N/VA:N/SC:N/SI:L/SA:L/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X

CVSS 3.1 · [email protected] · Primary · 5.4 CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N

osv · GHSA-rqv2-m695-f8j4

Published

## Summary The public catalogue UI served at `GET /` (file `internal/api/handlers/v0/ui_index.html`) is vulnerable to stored cross-site scripting via the `server.websiteUrl` field of any published `server.json`. Server-side validation in `internal/validators/validators.go` (`validateWebsiteURL`) only checks that the URL parses, is absolute, and uses the `https` scheme; it does not reject quote characters. Client-side, the value is interpolated into a double-quoted `href` attribute via `innerHTML`, using a homegrown `escapeHtml` helper that performs the standard `textContent` → `innerHTML` round-trip. Per the HTML serialisation algorithm, that round-trip encodes only `&`, `<`, `>` and U+00A0 inside text nodes — it does **not** encode `"` or `'`. A literal `"` in `websiteUrl` therefore breaks out of the `href` attribute, allowing arbitrary `on*` event handlers to be appended to the same `<a>` element. The Content-Security-Policy on `/` is `script-src 'self' 'unsafe-inline' https://cdn.tailwindcss.com`, so the injected event handlers execute. Any user able to obtain a publish token (e.g. via `POST /v0/auth/github-at` with their own GitHub account, or `POST /v0/auth/none` on a deployment that has anonymous auth enabled) can plant a poisoned record visible to every visitor of the registry homepage. ## Affected component - Validator: `internal/validators/validators.go` — `validateWebsiteURL` (lines 153–199) - Sink: `internal/api/handlers/v0/ui_index.html` — `toggleDetails(card, item)` at line 432, the `href` attribute built around `escapeHtml(server.websiteUrl)` - Helper: `escapeHtml` defined at `internal/api/handlers/v0/ui_index.html` lines 494–498 ## Proof of concept 1. Obtain a Registry JWT for any namespace you control (a GitHub OAuth exchange against a throwaway account suffices): ```bash 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) ``` 2. Publish a server with a poisoned `websiteUrl`. The literal `"` is preserved end-to-end: ```bash 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.<your-account>/xss-poc", "version": "0.0.1", "description": "hover the website link", "websiteUrl": "https://example.com/\"onmouseover=alert(document.domain)//" } EOF ``` 3. Visit `https://registry.modelcontextprotocol.io/`, search for `xss-poc`, click the card to expand it, then hover the **Website** link in the details panel. The injected `onmouseover` fires and `alert(document.domain)` runs on the `registry.modelcontextprotocol.io` origin. ## Why server-side validation does not catch this Go's `net/url.Parse` accepts literal `"` in the path component: ``` input="https://example.com/\"onmouseover=alert(1)//" IsAbs=true Scheme="https" Path="/\"onmouseover=alert(1)//" ``` Neither the Huma `format:"uri"` annotation nor `validateWebsiteURL`'s scheme/`IsAbs` triplet rejects this string. The architecture's existing protection — `repository.url` is regex-locked to `^https?://(www\.)?github\.com/[\w.-]+/[\w.-]+/?$` and therefore cannot contain quotes — does not extend to `websiteUrl`, which has no allowlist. ## Why client-side `escapeHtml` does not catch this ```js function escapeHtml(text) { const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } ``` Per the HTML5 spec (§13.3 Serialising HTML fragments), the only characters encoded inside the text content of an element are `&`, `<`, `>`, and U+00A0. `"` and `'` are **not** encoded because in a text-content context they are not special. The helper is therefore safe in element-text contexts (where it is correctly used for `name`, `version`, `description`, etc.) but unsafe inside an attribute value, which is precisely where it is invoked for `href` on lines 432 and 426. ## Impact - Stored XSS on the official MCP Registry homepage. The malicious entry sits in the public catalogue alongside legitimate ones; any user expanding the entry triggers the payload. - Because the page is served on the official `registry.modelcontextprotocol.io` origin, the injected script can: - Read and overwrite `localStorage` (`baseUrl`, `customUrl`), pinning the user's subsequent reads to an attacker-controlled "Custom" base URL. - Issue any same-origin or cross-origin XHR (`connect-src *` is granted). - Phish for Registry JWTs by injecting fake auth flows on the trusted origin. - The CSP `script-src 'self' 'unsafe-inline' https://cdn.tailwindcss.com` does not block this because `'unsafe-inline'` permits inline event-handler attributes. ## Suggested remediation (any one suffices) 1. Replace the homegrown `escapeHtml` with an attribute-safe encoder that also escapes `"`, `'`, backtick, and `=` — the OWASP HTML attribute-encoding rule. 2. Avoid building the `href` via string templates. Use `setAttribute('href', value)` instead — `setAttribute` is not subject to HTML tokenisation, so no breakout is possible. 3. Tighten `validateWebsiteURL` to reject any URL whose raw bytes contain `"`, `'`, `<`, `>`, ` `, `\t`, or `\n`, or — conservatively — store the canonical re-serialised form (`parsedURL.String()` percent-encodes such characters in the path). 4. Drop `'unsafe-inline'` from `script-src` after auditing the inline scripts on the page. Approach (3) is the smallest server-side change and immediately neutralises the exploit for any new publishes; approaches (1) or (2) close the class of bug at the sink so future fields with similar patterns are safe by default.

Source published
8 May 2026 17:18:32 UTC
Source modified
10 Sep 2026 03:50:55 UTC
Observed here
24 Oct 2026 13:19:41 UTC
Source terms
GitHub Advisory Database · CC-BY-4.0

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: osv · GitHub Advisory Database · CC-BY-4.0. Source text is retained; field grouping and change labels are provided by ChangeIntel.

CVSS_V3 · CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N

CVSS_V4 · CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:P/VC:N/VI:N/VA:N/SC:N/SI:L/SA:L

Publisher rating · MODERATE

osv · GO-2026-5637

Published

MCP Registry vulnerable to stored XSS in catalogue UI via attribute-quote breakout in publisher-controlled `websiteUrl` in github.com/modelcontextprotocol/registry

Source published
25 Jun 2026 22:34:38 UTC
Source modified
25 Jun 2026 23:01:36 UTC
Observed here
24 Oct 2026 13:19:41 UTC
Source terms
OSV · upstream source license applies

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: osv · OSV · upstream source license applies. Source text is retained; field grouping and change labels are provided by ChangeIntel.

ChangeIntel

An IT change radar: releases, security, known issues, retirements, documentation changes, and service status from public sources. Every item links to supporting evidence; dates and statuses can change after they are read.

Sources read 28 Oct 09:38 UTC · 272 of 272 readable · 268 fully read · documentation 469/469 current