CVE-2026-45781: MCP Registry: OCI validator skips ownership check on upstream rate limits
internal/validators/registries/oci.go:104-119 fails open on http.StatusTooManyRequests: when the
registry’s anonymous fetch to the upstream OCI registry is rate-limited, ValidateOCI returns nil
and the publish is accepted without ever running the
io.modelcontextprotocol.server.name label-match check at lines 122-141. That label check is the
only cross-system ownership proof the registry applies to OCI packages — every other registry type
(NPM, PyPI, NuGet, MCPB) treats a non-200 upstream response as a hard error.
The fail-open trigger is attacker-controllable. The registry uses authn.Anonymous against Docker
Hub, which is rate-limited to 100 manifest pulls per 6 hours per egress IP, and the production
NGINX rate limit allows 180 publishes/minute (3 RPS, burst 540) per source IP. A single attacker
from a single IP can exhaust the registry’s shared anonymous quota in roughly 33 seconds, then
submit a final publish that points packages[].identifier at a Docker Hub image they do not own.
The validator hits the 429 fail-open branch, returns nil, and the registry stores a record under
the attacker’s namespace claiming the unrelated image as its package payload, with no label proof
in evidence.
The fail-open is also reached without an attacker present. Docker Hub routinely 429s busy egress IPs during organic traffic, so publishes during those windows skip OCI ownership validation silently.
References
Code Behaviors & Features
Detect and mitigate CVE-2026-45781 with GitLab Dependency Scanning
Secure your software supply chain by verifying that all open source dependencies used in your projects contain no disclosed vulnerabilities. Learn more about Dependency Scanning →