registry icon indicating copy to clipboard operation
registry copied to clipboard

GitHub namespace permissions are case-sensitive but GitHub usernames/orgs are case-insensitive

Open zzstoatzz opened this issue 2 months ago • 4 comments

Describe the bug When authenticating via GitHub OIDC, the registry creates permission patterns using the exact casing from the repository_owner claim (e.g., io.github.PrefectHQ/*). When attempting to publish a server with a lowercase namespace (e.g., io.github.prefecthq/prefect-mcp-server), the publish fails with a 403 error because the permission check at internal/auth/jwt.go:163 uses case-sensitive string matching.

Since GitHub usernames and organization names are case-insensitive, this creates an inconsistency where the registry treats them as case-sensitive.

To Reproduce

  1. Authenticate via GitHub OIDC from a repository owned by an organization with capital letters (e.g., PrefectHQ)
  2. Create a server.json with a lowercase namespace: io.github.prefecthq/my-server
  3. Attempt to publish using mcp-publisher publish
  4. Receive 403 error: "You have permission to publish: io.github.PrefectHQ/*. Attempting to publish: io.github.prefecthq/my-server"

Expected behavior Since GitHub usernames/orgs are case-insensitive, the registry should either:

  • Normalize GitHub namespaces to lowercase when creating permissions
  • Use case-insensitive matching for io.github.* namespaces
  • Accept the server name with either casing

Logs

Publishing to https://registry.modelcontextprotocol.io...
Error: publish failed: server returned status 403: {"title":"Forbidden","status":403,"detail":"You do not have permission to publish this server. You have permission to publish: io.github.PrefectHQ/*. Attempting to publish: io.github.prefecthq/prefect-mcp-server"}

Additional context The issue occurs in the isResourceMatch function at internal/auth/jwt.go:163 which uses case-sensitive strings.HasPrefix. The permission is created at internal/api/handlers/v0/auth/github_oidc.go:292 using the exact repository_owner value from the OIDC token.

zzstoatzz avatar Oct 17 '25 15:10 zzstoatzz

example

zzstoatzz avatar Oct 17 '25 15:10 zzstoatzz

@tadasant / @domdomegg Should I pick this up?

Avish34 avatar Oct 19 '25 19:10 Avish34

Hmm, I feel a bit icky having to implement this. Is there a strong reason you want your GitHub username and MCP registry namespace to have different casing?

Normalize GitHub namespaces to lowercase when creating permissions Use case-insensitive matching for io.github.* namespaces Accept the server name with either casing

If we do do this, accepting the server name with either casing is likely the best of the options: otherwise publishers likely to get confused why they have to use lowercase.

Also curious what Tadas thinks before jumping into this.

domdomegg avatar Oct 20 '25 18:10 domdomegg

+1 to Adam's question:

Is there a strong reason you want your GitHub username and MCP registry namespace to have different casing?

I don't feel super strongly either way, but in the name of simplicity my default would be to just users should use the same casing. Maybe our error messaging could be more elegant (e.g. display a hint that it failed because your casing does not match, in the case that it matches except for the casing).

If there's a practical reason to allow this though, I agree that accepting the server name with either casing is the best of the options (but it should be immutable for that server thereafter, and cannot collide with matching names of different cases).

tadasant avatar Oct 20 '25 22:10 tadasant