VYPR
Medium severity5.4GHSA Advisory· Published May 14, 2026· Updated May 15, 2026

CVE-2026-44429

CVE-2026-44429

Description

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.

Affected products

1

Patches

1
78b7bbde0794

fix(validators): reject HTML metacharacters and whitespace in websiteUrl (#1249)

https://github.com/modelcontextprotocol/registryRadoslav DimitrovMay 4, 2026via ghsa
2 files changed · +108 0
  • internal/validators/validators.go+14 0 modified
    @@ -195,6 +195,20 @@ func validateWebsiteURL(ctx *ValidationContext, websiteURL string) *ValidationRe
     		result.AddIssue(issue)
     	}
     
    +	// Reject characters that aren't valid in a URI per RFC 3986 and that have
    +	// caused rendering issues when websiteUrl flows into the catalogue UI's
    +	// href attributes. Publishers should percent-encode these in the source URL.
    +	if i := strings.IndexAny(websiteURL, "\"'<> \t\n\r"); i >= 0 {
    +		issue := NewValidationIssue(
    +			ValidationIssueTypeSemantic,
    +			ctx.String(),
    +			fmt.Sprintf("websiteUrl contains an invalid character %q at position %d: %s", websiteURL[i], i, websiteURL),
    +			ValidationIssueSeverityError,
    +			"website-url-invalid-characters",
    +		)
    +		result.AddIssue(issue)
    +	}
    +
     	return result
     }
     
    
  • internal/validators/validators_test.go+94 0 modified
    @@ -13,6 +13,8 @@ import (
     	"github.com/modelcontextprotocol/registry/pkg/model"
     )
     
    +const websiteURLInvalidCharErrSubstr = "websiteUrl contains an invalid character"
    +
     func TestValidate(t *testing.T) {
     	tests := []struct {
     		name          string
    @@ -486,6 +488,98 @@ func TestValidate(t *testing.T) {
     			},
     			expectedError: "invalid websiteUrl:",
     		},
    +		{
    +			name: "server with websiteUrl containing double quote",
    +			serverDetail: apiv0.ServerJSON{
    +				Schema:      model.CurrentSchemaURL,
    +				Name:        "com.example/test-server",
    +				Description: "A test server",
    +				Repository: &model.Repository{
    +					URL:    "https://github.com/owner/repo",
    +					Source: "github",
    +				},
    +				Version:    "1.0.0",
    +				WebsiteURL: `https://example.com/"oops`,
    +			},
    +			expectedError: websiteURLInvalidCharErrSubstr,
    +		},
    +		{
    +			name: "server with websiteUrl containing single quote",
    +			serverDetail: apiv0.ServerJSON{
    +				Schema:      model.CurrentSchemaURL,
    +				Name:        "com.example/test-server",
    +				Description: "A test server",
    +				Repository: &model.Repository{
    +					URL:    "https://github.com/owner/repo",
    +					Source: "github",
    +				},
    +				Version:    "1.0.0",
    +				WebsiteURL: "https://example.com/it's",
    +			},
    +			expectedError: websiteURLInvalidCharErrSubstr,
    +		},
    +		{
    +			name: "server with websiteUrl containing angle brackets",
    +			serverDetail: apiv0.ServerJSON{
    +				Schema:      model.CurrentSchemaURL,
    +				Name:        "com.example/test-server",
    +				Description: "A test server",
    +				Repository: &model.Repository{
    +					URL:    "https://github.com/owner/repo",
    +					Source: "github",
    +				},
    +				Version:    "1.0.0",
    +				WebsiteURL: "https://example.com/<x>",
    +			},
    +			expectedError: websiteURLInvalidCharErrSubstr,
    +		},
    +		{
    +			name: "server with websiteUrl containing space",
    +			serverDetail: apiv0.ServerJSON{
    +				Schema:      model.CurrentSchemaURL,
    +				Name:        "com.example/test-server",
    +				Description: "A test server",
    +				Repository: &model.Repository{
    +					URL:    "https://github.com/owner/repo",
    +					Source: "github",
    +				},
    +				Version:    "1.0.0",
    +				WebsiteURL: "https://example.com/has space",
    +			},
    +			expectedError: websiteURLInvalidCharErrSubstr,
    +		},
    +		{
    +			name: "server with websiteUrl containing newline",
    +			serverDetail: apiv0.ServerJSON{
    +				Schema:      model.CurrentSchemaURL,
    +				Name:        "com.example/test-server",
    +				Description: "A test server",
    +				Repository: &model.Repository{
    +					URL:    "https://github.com/owner/repo",
    +					Source: "github",
    +				},
    +				Version:    "1.0.0",
    +				WebsiteURL: "https://example.com/has\nnewline",
    +			},
    +			// url.Parse rejects ASCII control chars before our character-set
    +			// check runs; either path produces a validation error.
    +			expectedError: "invalid websiteUrl:",
    +		},
    +		{
    +			name: "server with websiteUrl with percent-encoded special chars is accepted",
    +			serverDetail: apiv0.ServerJSON{
    +				Schema:      model.CurrentSchemaURL,
    +				Name:        "com.example/test-server",
    +				Description: "A test server",
    +				Repository: &model.Repository{
    +					URL:    "https://github.com/owner/repo",
    +					Source: "github",
    +				},
    +				Version:    "1.0.0",
    +				WebsiteURL: "https://example.com/path/?q=hello%20world&r=a%22b",
    +			},
    +			expectedError: "",
    +		},
     		{
     			name: "server with websiteUrl that matches namespace domain",
     			serverDetail: apiv0.ServerJSON{
    

Vulnerability mechanics

AI mechanics synthesis has not run for this CVE yet.

References

6

News mentions

0

No linked articles in our index yet.