Skip to content

fix(api): RBAC follow-ups for PR #2403#2548

Open
riderx wants to merge 3 commits into
codex/rbac-apikey-management-hardeningfrom
fix/rbac-apikey-hardening-followups
Open

fix(api): RBAC follow-ups for PR #2403#2548
riderx wants to merge 3 commits into
codex/rbac-apikey-management-hardeningfrom
fix/rbac-apikey-hardening-followups

Conversation

@riderx

@riderx riderx commented Jun 19, 2026

Copy link
Copy Markdown
Member

Summary (AI generated)

  • Added org.manage_apikeys permission and assignable apikey_manager role; granted it to org_admin / org_super_admin so migrated legacy all keys keep sibling key management in CI.
  • Allowed POST /apikey via API key auth when the caller has org.manage_apikeys (bindings/global-permission updates remain JWT-only; self-update remains blocked).
  • Removed 2FA/password-policy enforcement from API-key branches of rbac_check_permission_direct.
  • Mapped legacy channel write/upload memberships to channel_admin instead of nonexistent channel_developer / channel_uploader.
  • Granted app_uploader channel promote/read without channel.update_settings.
  • Restored fast RLS for app_versions + manifest via app_versions_readable_app_ids() (bundle read permission).
  • Updated seed.sql so post-seed RBAC repopulation keeps the new permission/grants.
  • Added SQL + vitest coverage for API-key create/manage and 2FA bypass behavior.

Motivation (AI generated)

PR #2403 correctly hardened RBAC, but review follow-ups asked to preserve CI/API-key management for migrated broad keys, add a dedicated manage-keys permission, skip 2FA on API keys, fix channel legacy mapping, and reduce manifest RLS cost.

Business Impact (AI generated)

Customers with legacy broad API keys in GitHub Actions/Fastlane can keep provisioning and rotating sibling keys without JWT sessions, while scoped upload keys still cannot escalate privileges.

Test Plan (AI generated)

Generated with AI

Made with Cursor

Introduce org.manage_apikeys and apikey_manager so legacy broad keys and
dedicated CI keys can create and manage sibling keys without user-role
assignment rights. Skip 2FA enforcement on API-key auth paths, optimize
manifest/app_versions RLS with readable app id helpers, and align seed
data with app_uploader channel promote and channel_admin legacy mapping.

Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 5d2ca32e-4cbe-452b-adc8-8f42572bea63

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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

@codspeed-hq

codspeed-hq Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 43 untouched benchmarks
⏩ 2 skipped benchmarks1


Comparing fix/rbac-apikey-hardening-followups (08a0488) with codex/rbac-apikey-management-hardening (789881a)

Open in CodSpeed

Footnotes

  1. 2 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bf02583c3a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +60 to +64
ON permissions.key = public.rbac_perm_org_manage_apikeys()
WHERE roles.name IN (
public.rbac_role_apikey_manager(),
public.rbac_role_org_admin(),
public.rbac_role_org_super_admin()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Enforce org expiration policies for apikey_manager

Callers that only have the new apikey_manager role get org.manage_apikeys but not org.read, while POST /apikey validates expiration policies by selecting orgs through the caller's RLS client and silently skips enforcement when no org rows are visible. In an org with require_apikey_expiration or max_apikey_expiration_days, an apikey_manager user/API key can therefore create a non-expiring or over-long API key; either include the read permission needed for that policy lookup or perform the expiration-policy lookup through a server-side path before creating the key.

Useful? React with 👍 / 👎.

Seed API key 113 with the apikey_manager role and add vitest/SQL checks
that CI keys can manage siblings without role escalation privileges.

Co-authored-by: Cursor <cursoragent@cursor.com>

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 08a0488357

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

for (const bindingOrgId of allOrgIds) {
if (!(await checkPermission(c, 'org.update_user_roles', { orgId: bindingOrgId }))) {
throw quickError(403, 'forbidden_binding', `Forbidden - Admin rights required for org ${bindingOrgId}`)
if (!(await checkPermission(c, 'org.manage_apikeys', { orgId: bindingOrgId }))) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Prevent apikey managers from minting app admins

When the caller is an API key bound only to the new apikey_manager role, this org-level org.manage_apikeys check is the only authorization before arbitrary requested bindings are created. The later createRoleBindingForPrincipal guard only compares priority_rank, so apikey_manager (rank 78) can POST a lower-ranked app_admin or channel_admin binding and mint a key that can update apps/channels even though the caller itself only had API-key-management rights. Please also verify the caller can grant each requested role/scope, or restrict the roles this manager can assign.

Useful? React with 👍 / 👎.

Comment on lines +4396 to +4399
WHEN 'invite_write' THEN 'channel_admin'
WHEN 'write' THEN 'channel_admin'
WHEN 'invite_upload' THEN 'channel_admin'
WHEN 'upload' THEN 'channel_admin'

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Avoid upgrading legacy channel writers to admins

For existing org_users rows scoped to a specific channel, this migration now maps legacy write/upload rights to channel_admin. That role has full channel-control permissions such as channel.update_settings/delete, and the channel update RLS policy accepts channel.update_settings, so a legacy upload-only or writer collaborator is promoted to full channel admin during migration. Preserve the old distinction by adding/mapping to narrower channel developer/uploader roles instead of channel_admin.

Useful? React with 👍 / 👎.

Re-apply org-scoped RBAC bindings for the dedicated apikey management
seed keys after permissions are repopulated, and assert by key UUID in
the SQL test instead of a fixed apikeys.id.

Co-authored-by: Cursor <cursoragent@cursor.com>
@sonarqubecloud

Copy link
Copy Markdown

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