Skip to content

fix(auth): hold scoped keys and lower roles to what they were granted - #2562

Merged
Makisuo merged 3 commits into
mainfrom
sec/scoped-key-role-gates
Nov 13, 2026
Merged

Makisuo merged 3 commits into
mainfrom
sec/scoped-key-role-gates

Conversation

@Makisuo

@Makisuo Makisuo commented Nov 13, 2026 •

Copy link
Copy Markdown
Collaborator

What

Part of a pass over every API surface. Five places where a credential could do slightly more than it was granted. None crosses organizations.

  • Uptime monitors. Request header values and the heartbeat URL are shown only to a caller who may write monitors. The check now looks at the key's scope as well as its role.
  • AWS connection setup. The rendered setup holds the metric stream's access key, so a scoped API key needs integrations:write to fetch it. Sessions and unscoped keys are unchanged.
  • API keys. POST /v2/api_keys accepts standard and mcp only. Device credentials are issued to an installation by their own endpoints, and the MCP server now refuses one.
  • Security Center. The exposure and runtime tabs check security:manage on the server, as the findings already do. Until now only the web app hid them.
  • Demotion. A CLI or MCP approval made at the old role and not yet redeemed is removed along with the credentials already pinned above the new role.

Verification

  • New and extended tests, all passing locally: uptime-monitors.http.test.ts, integrations-aws.http.test.ts, api-keys.http.test.ts, security-tenant.test.ts, MembershipRevocationService.test.ts, resolve-tenant.scopes.test.ts.
  • widget-credentials.http.test.ts, the domain v2 contract tests and the provider contract test still pass.
  • Typecheck: @maple/api, @maple/ai, @maple/web, @maple/domain. Lint with the CI config on the touched directories.
  • ios:openapi:check is up to date.

🤖 Generated with Claude Code


Autofix with [code]smith
Open in [code]smith · Need help on this PR? Tag @codesmith-bot with what you need.

Summary by CodeRabbit

  • Security
    • Access to AWS integration setup details now requires the integrations:write scope for scoped API keys.
    • Uptime-monitor secrets are redacted unless callers have the required role and write scope.
    • Device credentials can’t be used with the MCP server, and device API keys can’t be created.
    • Demoting a user invalidates pending device and MCP approvals that require a higher role.
    • Security-related endpoints enforce role-based access checks.
  • Documentation
    • AWS setup requirements now clarify the permissions needed to retrieve setup details.

A read-scoped API key resolves with the default key role, so checks that looked at the role alone treated it as a writer.

- Uptime monitors: header values and the heartbeat URL are shown only to a caller who may write monitors, by role and by scope.
- AWS connection setup: the rendered setup holds the stream's access key, so a scoped key needs integrations:write to read it.
- API keys: a device credential can no longer be created by name, and the MCP server refuses one.
- Security Center: the exposure and runtime tabs check security:manage on the server, like the findings do.
- Demotion: approvals made at the old role and not yet redeemed are removed with the credentials already pinned above the new role.
@maple-review-bot

This comment has been minimized.

@coderabbitai

coderabbitai Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

Explain Change →

No actionable comments were generated in the recent review.

Walkthrough

The changes restrict device-key creation and MCP use, enforce role and scope checks on selected API routes and responses, and remove pending CLI and MCP OAuth approvals that exceed a demoted member’s role.

Changes: API key kind controls

Layer / File(s) Summary
Restrict API key creation kinds
packages/domain/src/api-keys.ts, packages/domain/src/http/api-keys.ts, packages/domain/src/http/v2/api-keys.ts, apps/web/src/page/settings/keys/*, apps/web/src/page/settings/kit/api-key-create-payload.ts, apps/api/src/routes/v2/api-keys.http.test.ts
The API key create schema and settings flow use CreatableApiKeyKind, which excludes device keys. An HTTP test expects device-kind creation to return a 400 invalid-request response.
Reject device credentials for MCP
apps/ai/src/mcp/lib/resolve-tenant.ts, apps/ai/src/mcp/lib/resolve-tenant.scopes.test.ts
MCP tenant resolution rejects device credentials with an invalid-target authentication error. A test covers a scope-free device key.

Endpoint authorization and secret visibility

Layer / File(s) Summary
Apply security role checks to internal endpoints
apps/api/src/routes/internal/security-tenant.ts, apps/api/src/routes/internal/security-tenant.test.ts, apps/api/src/routes/internal/dependency-scan.http.ts, apps/api/src/routes/internal/query-engine.http.ts, packages/domain/src/http/query-engine.ts
The Security Center endpoints use securityTenant, which checks for security:manage and maps denials to DependencyScanForbiddenError. The endpoint error contracts and role tests include that error.
Enforce v2 scopes for setup and secret reads
apps/api/src/routes/v2/integrations-aws.http.ts, apps/api/src/routes/v2/integrations-aws.http.test.ts, packages/domain/src/http/v2/integrations-aws.ts, apps/api/src/routes/v2/uptime-monitors.http.ts, apps/api/src/routes/v2/uptime-monitors.http.test.ts
AWS setup requires integrations:write after the role check. Uptime-monitor list and retrieve responses expose secrets only when the tenant has the manage role and write scope; tests cover scope errors and redaction.

Approval cleanup on membership demotion

Layer / File(s) Summary
Remove approvals above the demoted role
packages/backend/src/services/auth/MembershipRevocationService.ts, packages/backend/src/services/auth/MembershipRevocationService.test.ts
The demotion transaction deletes pending CLI and MCP OAuth approvals when their approved roles outrank the member’s current role. Tests cover CLI approval expiry and MCP authorization-code exchange after demotion.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Bug fix

Merge Risk: Minimal · up to c8926

The change tightens API key creation, MCP device-credential handling, and secret visibility for scoped keys. It also removes pending approvals above a demoted member's role. No merge-blocking issue was found after the review.

Pre-merge checks: Passed 4

Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title "fix(auth): hold scoped keys and lower roles to what they were granted" matches the main change. The PR adds scope and role checks for API keys and device/MCP approvals, and demotion removes…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Title check

Explanation

The title "fix(auth): hold scoped keys and lower roles to what they were granted" matches the main change. The PR adds scope and role checks for API keys and device/MCP approvals, and demotion removes approvals and credentials above the new role. The title names the auth fix and its core idea, so it is specific and accurate. It does not list every change (for example, the AWS setup gate, the uptime-monitor secret redaction, or the Security Center checks), which the title does not need to cover.

Finishing Touches

Generate unit tests (beta)

  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

Recent review info

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 1e563aff-24cd-4e8f-bb6c-e379b236c7ae
Commits

Reviewing files that changed from the base of the PR and between 6f66550 and c892660.

Files selected for processing: 21

  • apps/ai/src/mcp/lib/resolve-tenant.scopes.test.ts
  • apps/ai/src/mcp/lib/resolve-tenant.ts
  • apps/api/src/routes/internal/dependency-scan.http.ts
  • apps/api/src/routes/internal/query-engine.http.ts
  • apps/api/src/routes/internal/security-tenant.test.ts
  • apps/api/src/routes/internal/security-tenant.ts
  • apps/api/src/routes/v2/api-keys.http.test.ts
  • apps/api/src/routes/v2/integrations-aws.http.test.ts
  • apps/api/src/routes/v2/integrations-aws.http.ts
  • apps/api/src/routes/v2/uptime-monitors.http.test.ts
  • apps/api/src/routes/v2/uptime-monitors.http.ts
  • apps/web/src/page/settings/keys/create-dialog.ts
  • apps/web/src/page/settings/keys/update.ts
  • apps/web/src/page/settings/kit/api-key-create-payload.ts
  • packages/backend/src/services/auth/MembershipRevocationService.test.ts
  • packages/backend/src/services/auth/MembershipRevocationService.ts
  • packages/domain/src/api-keys.ts
  • packages/domain/src/http/api-keys.ts
  • packages/domain/src/http/query-engine.ts
  • packages/domain/src/http/v2/api-keys.ts
  • packages/domain/src/http/v2/integrations-aws.ts

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 2 remain after this review.

@maple-review-bot maple-review-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

1 inline note from Maple's review. The score and summary are in the review comment above.

@maple-review-bot

This comment has been minimized.

@maple-review-bot

maple-review-bot Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

Maple review

🟢 Confidence 10/10 · safe to merge. Scope and role plumbing is the risk here; each of the five gates is pinned by a test that fails without it.
no findings · tests covered · risk high

Five authorization narrowings: scoped keys must hold a write scope to read monitor secrets or AWS setup, device keys can no longer be minted or used via MCP, Security Center telemetry needs security:manage, and demotion expires pending CLI/MCP approvals made above the new role.

  • canWriteMonitors now also requires the key's uptime_monitors:write scope
  • AWS setup requires integrations:write for scoped keys
  • V2ApiKeyCreateParams.kind accepts only standard and mcp
  • securityTenant gates the exposure and runtime tabs on security:manage

c892660 · What was checked, coverage and telemetry details are on the Maple / review check. Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.

@Makisuo
Makisuo merged commit ad1786e into main Nov 13, 2026
43 checks passed
@Makisuo
Makisuo deleted the sec/scoped-key-role-gates branch November 13, 2026 16:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant