Skip to content

fix(api): block API keys on account-level routes#6397

Merged
gustavosbarreto merged 1 commit into
masterfrom
fix/block-api-key-account-routes
Jun 1, 2026
Merged

fix(api): block API keys on account-level routes#6397
gustavosbarreto merged 1 commit into
masterfrom
fix/block-api-key-account-routes

Conversation

@geovannewashington
Copy link
Copy Markdown
Member

What

Added BlockAPIKey middleware to four routes that were missing it:
ListAPIKeys, GetNamespaceList, CreateNamespace, and
LeaveNamespace. Removed the x-internal overrides and api-key
security entries from the OpenAPI spec for the same operations.

Why

API keys are namespace-scoped and not tied to a user. These routes
are account-level actions that should never accept an API key.
ListAPIKeys was the real gap -- it actually succeeded, allowing an
API key to enumerate all other keys in the namespace. The other three
were safe by accident (the service layer rejected them) but returned
confusing 404s instead of a clean 403.

Closes #6390. Follow-up to #6392 .

Testing

  1. Start the environment with ./bin/docker-compose up
  2. Create a user and namespace via the CLI or UI
  3. Generate an API key via curl:
curl -X POST http://localhost/api/namespaces/api-key \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Tenant-ID: <tenant-id>" \
  -d '{"name": "testkey", "expires_at": 30}'
  1. Use the returned key -- all four requests below should return 403:

curl -v -H "X-API-Key: <key>" http://localhost/api/namespaces/api-key
curl -v -H "X-API-Key: <key>" http://localhost/api/namespaces
curl -v -H "X-API-Key: <key>" -X POST http://localhost/api/namespaces
curl -v -H "X-API-Key: <key>" -X DELETE http://localhost/api/namespaces/<tenant>/members

API keys are namespace-scoped tokens and should not be usable on
account-level routes. Four routes were missing the BlockAPIKey
middleware, allowing API keys to reach handlers they should never
reach.

The most concrete gap was ListAPIKeys: an API key could enumerate
all other API keys in the namespace. The remaining three routes
(GetNamespaceList, CreateNamespace, LeaveNamespace) were safe by
accident -- the service layer rejected them -- but returned
confusing 404s instead of a clean 403.

Added BlockAPIKey to all four routes, matching the pattern already
used by CreateAPIKey, UpdateAPIKey and DeleteAPIKey. Removed the
x-internal overrides and api-key security entries from the OpenAPI
spec for the same operations, since the spec now accurately reflects
what the code enforces.

Removed TestListNamespacesAPIKeyScope, which tested the old scoped
behavior that no longer applies.
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 1, 2026

Claude finished @geovannewashington's task in 31s —— View job


Code Review Complete

Reviewed 6 files across code quality, security, testing, language patterns, and architecture — no issues found. The code looks good as-is.

Highlights:

  • The four BlockAPIKey middleware additions in routes.go are consistent with existing patterns (CreateAPIKey, UpdateAPIKey, DeleteAPIKey, UpdateUser).
  • The BlockAPIKey middleware correctly uses Header.Get("X-API-Key"), which is case-insensitive via Go's MIME-canonical header matching — no bypass via casing.
  • Test coverage is solid: all four newly blocked routes have dedicated tests asserting 403 Forbidden when X-API-KEY is present.
  • OpenAPI spec changes are aligned with the backend — api-key: [] security entries removed from the same four operations, and x-internal removed to make them visible in external docs (correct, since they are legitimate public endpoints).
  • No cross-repo impact: the cloud admin panel routes under /admin/api are unaffected by BlockAPIKey on /api.

If you push additional changes and want a new review, tag @shellhub-io/admin and a team member can trigger it.

@gustavosbarreto gustavosbarreto merged commit 8306547 into master Jun 1, 2026
31 of 32 checks passed
@gustavosbarreto gustavosbarreto deleted the fix/block-api-key-account-routes branch June 1, 2026 21:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix: block API keys on account-level routes (list/create/leave namespaces, list API keys)

2 participants