Skip to content

fix(api-keys): verify revoke ownership via the user's key list#2590

Merged
chelojimenez merged 2 commits into
mainfrom
fix/api-keys-revoke-ownership
Jun 11, 2026
Merged

fix(api-keys): verify revoke ownership via the user's key list#2590
chelojimenez merged 2 commits into
mainfrom
fix/api-keys-revoke-ownership

Conversation

@chelojimenez

@chelojimenez chelojimenez commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Problem

Revoking an API key always failed with 404 "API key not found", even for the user's own keys.

The DELETE route's defense-in-depth ownership check did GET /api_keys/{id} and compared owner.id to the session user — but WorkOS exposes no single-key GET for user API keys. Both /api_keys/{id} and the user-scoped /user_management/users/{userId}/api_keys/{id} return 404 even for ids that exist (verified directly against WorkOS). So the check 404'd before the delete ever ran. DELETE /api_keys/{id} itself works fine.

Fix

Replace the single-key lookup with userOwnsApiKey(): walk the session user's own key list (the documented, working endpoint — same one GET / uses) and require the id to appear there. Enumeration under the user is the ownership proof, so the cross-user guarantee is unchanged: a foreign or unknown key id still reads as 404 before WorkOS sees the delete. List walk is paginated (limit 100, capped at 10 pages as a runaway guard).

Follow-up to #2588.

Testing

  • Verified against WorkOS directly: both single-key GET variants 404 for an existing key; the user-scoped list returns it; DELETE removes it (confirmed gone from the list).
  • server/tsconfig.json typecheck clean for the touched file; bearer-auth + web/errors vitest suites pass (17/17).

🤖 Generated with Claude Code


Note

Medium Risk
Touches authorization on API key revoke (security-sensitive), but behavior preserves cross-user 404 semantics and only fixes a broken WorkOS lookup path.

Overview
Fixes API key revoke always returning 404 for valid keys by changing how DELETE proves ownership before calling WorkOS.

The route no longer uses GET /api_keys/{id} (WorkOS returns 404 for user keys even when they exist). It now walks the session user's /user_management/users/{userId}/api_keys list via new userOwnsApiKey, with pagination (limit 100, max 10 pages). Foreign or unknown ids still get 404 without DELETE; if the page cap is hit while more pages remain, the handler returns 500 so keys aren't silently treated as not owned.

Adds api-keys.test.ts covering successful revoke, foreign-key 404 without DELETE, multi-page lookup, and page-cap failure.

Reviewed by Cursor Bugbot for commit 8ae7bab. Bugbot is set up for automated code reviews on this repo. Configure here.

WorkOS exposes no single-key GET for user API keys — both
GET /api_keys/{id} and the user-scoped variant 404 even for existing
ids — so the DELETE route's owner check failed every revoke with
"API key not found". Replace the lookup with membership in the session
user's own key list (paginated), which is the same ownership proof:
a key enumerated under the user belongs to the user.

The actual DELETE /api_keys/{id} endpoint works and is unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@dosubot dosubot Bot added size:M This PR changes 30-99 lines, ignoring generated files. bug Something isn't working labels Jun 11, 2026
@chelojimenez

chelojimenez commented Jun 11, 2026

Copy link
Copy Markdown
Contributor Author

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 937d6f56-fe6c-4320-a4ef-fc8cda1a9114

📥 Commits

Reviewing files that changed from the base of the PR and between e27963f and 8ae7bab.

📒 Files selected for processing (2)
  • mcpjam-inspector/server/routes/web/__tests__/api-keys.test.ts
  • mcpjam-inspector/server/routes/web/api-keys.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • mcpjam-inspector/server/routes/web/api-keys.ts

Walkthrough

The PR refactors API key deletion ownership verification. Previously, the DELETE handler re-fetched the key and compared owner IDs. Now it calls a new userOwnsApiKey helper that paginates through the session user's own WorkOS API key list to confirm the target key ID exists there. The helper returns false for missing keys, causing the route to throw 404 before issuing the WorkOS delete. Documentation for the DELETE endpoint was updated to describe this membership-based check.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@mcpjam-inspector/server/routes/web/api-keys.ts`:
- Around line 225-252: The userOwnsApiKey helper currently returns false if the
10-page cap is hit, which can misreport owned keys as not found; instead detect
cap exhaustion and surface an internal error (or keep paging until the cursor
repeats). Modify userOwnsApiKey to (a) track the previous after cursor and stop
only if the cursor is null or unchanged, and (b) if the loop exits due to a page
cap while list_metadata.after is still present, throw an explicit error (or call
mapWorkOSError) indicating "paging limit exceeded while searching API keys"
rather than returning false; use the existing callWorkOS and list_metadata.after
handling and reference the function name userOwnsApiKey when making the change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 83158e29-c85b-4f43-91ad-fa6202c81501

📥 Commits

Reviewing files that changed from the base of the PR and between a4ce39c and e27963f.

📒 Files selected for processing (1)
  • mcpjam-inspector/server/routes/web/api-keys.ts

Comment thread mcpjam-inspector/server/routes/web/api-keys.ts Outdated
@github-actions

github-actions Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Internal preview

Preview URL: https://mcp-inspector-pr-2590.up.railway.app
Deployed commit: e8be27a
PR head commit: 8ae7bab
Backend target: staging fallback.
Health: ✅ Convex reachable
Access is employee-only in non-production environments.

…ests

Review feedback on #2590: if the ownership walk hits the 10-page runaway
guard while list_metadata.after still points onward, ownership is
unknown — returning false would read as a 404 and make keys beyond the
cap silently unrevokeable. Throw INTERNAL_ERROR (and log) instead.

Adds route tests with mocked WorkOS fetches: owned key revokes, foreign/
unknown id 404s without reaching DELETE, paginated match follows the
after cursor, and cap exhaustion errors rather than 404s.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@chelojimenez chelojimenez merged commit 6bd7261 into main Jun 11, 2026
12 checks passed
@chelojimenez chelojimenez deleted the fix/api-keys-revoke-ownership branch June 11, 2026 06:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant