CVE-2026-44428: MCP Registry: GitHub OIDC tokens replayable across registry deployments due to shared audience
# [SECURITY] registry_001 Vulnerability Report While analyzing the code logic, an area that may lead to unintended behavior under specific conditions was discovered. ## Overview - Verified Version: `c5c4b9e8890dd5754bee889b2f1417f4fe3b5ce5` - Vulnerability Type: Authentication bypass via cross-registry OIDC token replay - Affected Location: `cmd/publisher/commands/login.go:67-105,130-135,199-224`; `cmd/publisher/auth/github-oidc.go:24-38,58-75,108-165`; `internal/api/handlers/v0/auth/github_oidc.go:75-135,229-277,280-296` - Trigger Scenario: a workflow invokes `mcp-publisher login github-oidc --registry <other-registry>` (or equivalent publish flow) and the publisher still requests a GitHub Actions ID token with the shared audience `mcp-registry`; any other registry deployment running this code can replay that token to its own `/v0/auth/github-oidc` endpoint and mint a publish-capable registry JWT for the same GitHub owner namespace. ## Root Cause The client-side and server-side GitHub OIDC flow is bound only to a global audience string, not to the specific registry instance being targeted. On the client side, the publisher always appends `audience=mcp-registry` when requesting the GitHub Actions ID token, regardless of the selected `--registry` URL. On the server side, the exchange endpoint validates only that same fixed audience and then derives publish permissions directly from `repository_owner`. As a result, a token legitimately obtained while interacting with one registry deployment remains acceptable to any other deployment that shares the same code and audience string. ## Source-to-Sink Chain 1. Source `cmd/publisher/commands/login.go:67-105,130-135,199-224` parses the user-controlled `--registry` flag into `flags.RegistryURL`, creates a `GitHubOIDCProvider`, and calls `authProvider.GetToken(ctx)` for the chosen authentication method. 2. Propagation `cmd/publisher/auth/github-oidc.go:24-38` obtains an OIDC token and immediately exchanges it against the selected registry URL. `cmd/publisher/auth/github-oidc.go:58-75` builds `exchangeURL := o.registryURL + "/v0/auth/github-oidc"` and posts the GitHub token to whichever registry instance was selected. `cmd/publisher/auth/github-oidc.go:108-165` constructs `fullURL := requestURL + "&audience=mcp-registry"` and therefore requests the same audience for every registry deployment. 3. Sink `internal/api/handlers/v0/auth/github_oidc.go:75-135` validates only the shared audience value passed into `ValidateToken`. `internal/api/handlers/v0/auth/github_oidc.go:254-277` calls `h.validator.ValidateToken(ctx, oidcToken, "mcp-registry")` and, on success, signs a new registry JWT. `internal/api/handlers/v0/auth/github_oidc.go:280-296` converts `claims.RepositoryOwner` into the publish permission pattern `io.github.<owner>/*`, which is then embedded into the new registry JWT. ## Exploitation Preconditions 1. The victim uses the GitHub Actions OIDC publishing path. 2. The victim workflow targets another registry deployment first, such as staging, self-hosted infrastructure, or an attacker-controlled registry URL. 3. The receiving registry deployment can observe the posted OIDC token and replay it before expiry to another registry deployment running the same shared audience configuration. ## Risk This breaks deployment isolation between registry instances. A token issued for one registry interaction can be replayed across trust boundaries, allowing one deployment to impersonate the same GitHub owner identity on another deployment. ## Impact An attacker-controlled or compromised registry deployment can mint a valid registry JWT on another deployment and inherit publish permissions for the victim GitHub owner namespace. In practical terms, this enables unauthorized publication or update actions for names such as `io.github.<owner>/*` on the victim registry instance. ## Remediation 1. Replace the shared audience string with a registry-specific audience, such as a deployment-specific client ID or origin-derived identifier. 2. Ensure the publisher requests the audience that matches the exact registry instance it is targeting, and ensure the server validates that same instance-specific value. 3. Consider binding the exchange to additional deployment-specific claims so that a token captured by one registry cannot be replayed on another. 4. Add regression tests that cover cross-deployment replay attempts between different registry URLs.
Affected Software
Event History
Frequently Asked Questions
What is the severity of CVE-2026-44428?
The severity of CVE-2026-44428 is classified as high due to its ability to allow authentication bypass.
How do I fix CVE-2026-44428?
To fix CVE-2026-44428, upgrade to version 1.7.6 or later of the affected software.
What types of software are impacted by CVE-2026-44428?
CVE-2026-44428 affects software versions prior to 1.7.6 of the github.com/modelcontextprotocol/registry package.
What is the vulnerability type of CVE-2026-44428?
CVE-2026-44428 is an authentication bypass vulnerability that may lead to unintended behavior.
Is there a confirmed version that is vulnerable for CVE-2026-44428?
Yes, any version of the affected software prior to 1.7.6 is confirmed to be vulnerable to CVE-2026-44428.