Repository navigation
fix(mothership): hold callerless runs' sim_cli to read API scopes - #9371
Conversation
An unattributed inbox message runs as the workspace owner with its tool permission capped to read, but sim_cli has no catalog permission and its commands authorize the delegated subject's live role, so the CLI could create, run, and delete with the owner's authority. A run with no caller of its own now executes the CLI inside a delegated API-scope grant of api:read, enforced in requireOAuthOperationScope the same way an OAuth token's scopes are, so every authorization path the CLI reaches refuses api:write operations.
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
There was a problem hiding this comment.
All reported issues were addressed across 5 files
Heads up: you’ve reached your flex budget. Increase your flex budget or wait for usage to reset.
Turn on auto-fix | Re-trigger cubic
[Medium impact] The PR appears safe to merge; no new blocking issues were found. SummaryCaps callerless
|
…oped CLI writes Mixed server tools reached through sim_cli services (settings, dashboards, tests, search_sources, workspaces) write through internal operations that declare no API scope, so the read grant never bound them. Each tool now declares which validated arguments write, and the router holds those to the current delegated grant. The grant also applies to callerless organization-scoped runs.
|
@cubic-dev-ai review this PR |
@waleedlatif1 I have started the AI code review. It will take a few minutes to complete. |
There was a problem hiding this comment.
All reported issues were addressed across 12 files
Heads up: you’ve reached your flex budget. Increase your flex budget or wait for usage to reset.
Turn on auto-fix | Re-trigger cubic
|
@cubic-dev-ai review this PR |
@waleedlatif1 I have started the AI code review. It will take a few minutes to complete. |
There was a problem hiding this comment.
No issues found across 12 files
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
Heads up: you’ve reached your flex budget. Increase your flex budget or wait for usage to reset.
Turn on auto-fix | Re-trigger cubic
Summary
read.sim_clihas no catalogrequiredPermission, soexecuteToolnever applied the cap, and every CLI command authorized the delegated subject's live role — the owner's. The CLI could create/edit/delete workflows, run workflows, write project files, and set the owner's personal secretssecretActorUserId: null) now execute the CLI inside a delegated API-scope grant ofapi:read(withDelegatedApiScopes)requireOAuthOperationScopeenforces that grant for delegated principals the same way it enforces an OAuth token's scopes. Every workspace, project-file, file-copy and org authorization path already calls it, so this covers v2 routes and the transports that call use cases directlyoauthScope, not HTTP method orminimumRole: v2 has read POSTs (table query, knowledge search, selectors) and write/execute ops atminimumRole: 'read'(workflows.execute,secrets.set, credential/skill ACL changes). Every Copilot-admitted v2 route declares a scope; operations with none are internal and keep their own policyBaseServerTool.writes), and the router holds those to the delegated grant (requireDelegatedApiScope)userPermission, so in-band (background subagent) calls — which carry nouserPermission— are capped too, and read-only members keep exactly their role's reachType of Change
Testing
project-file-read.integration.tsagainst real Postgres/Redis (bun run test:integration project-file-read), 17/17:workflows create,projects files create,secrets set --scope personalrefused withapi:write; nothing written;workflows liststill works; the same commands succeed when attributedsecrets setstill succeeds;workflows createrefused by role, not by scopesettings updateof the workspace inbox'ssecretScopethrough a CLI service: refused, row unchanged; succeeds when attributedrequireOAuthOperationScope, makes the capped writes succeed (vulnerability reproduced); a naive "permission below write" trigger fails the read-member checkChecklist
test-auditauthoring gate)