Skip to content

fix(copilot): enforce the chat's delegated workspace scope across model-steerable server tools - #6995

Merged
waleedlatif1 merged 5 commits into
stagingfrom
fix/copilot-workspace-scope
Aug 23, 2026
Merged

fix(copilot): enforce the chat's delegated workspace scope across model-steerable server tools#6995
waleedlatif1 merged 5 commits into
stagingfrom
fix/copilot-workspace-scope

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Summary

  • query_logs and set_environment_variables resolved their target workspace from a model-supplied workspaceId (or a workflowId in another workspace) before falling back to the chat's context, so a Copilot chat opened in one workspace could read execution logs from, and write environment secrets into, any other workspace the acting principal can reach — bypassing the asserted-vs-context comparison the rest of the Copilot tool surface enforces through the application adapter
  • both now resolve through requireCopilotWorkspace (moved from files/file-folder-application.ts to a shared tools/server/workspace-scope.ts): a model-supplied workspace may only re-assert the chat's execution workspace, and a missing scope fails closed
  • extended the same guard to the other tools that could be steered by model input: get_credentials (a workflowId could scope the credential listing to another workspace) and publish_custom_block (a workflowId could publish/unpublish a custom block from another workspace's workflow)
  • handlers already protected downstream by authorizeWorkspaceOperation (create workflow, generate API key, list/create workspace MCP servers) now use the same guard so a mismatch is rejected uniformly at the surface, and getDefaultWorkspaceId is deleted — no Copilot path picks a workspace for the model anymore
  • the guard accepts an undefined context and classifies both failure branches as OrchestrationError('validation'), so callers need no coercion boilerplate and one instanceof covers it

Type of Change

  • Bug fix

Testing

Added mismatch/re-assert/fail-closed tests for every guarded surface; full lib/copilot suite (1764 tests), type-check, bun run lint, and check:audits (32 audits) pass

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

…_environment_variables

A model-supplied workspaceId (or a workflowId in another workspace) could
steer both tools to any workspace the acting principal can reach, bypassing
the asserted-vs-context workspace comparison the rest of the Copilot tool
surface enforces. Both now resolve through requireCopilotWorkspace — moved
to a shared module — so an asserted workspace may only re-state the chat's
execution workspace, and the default-workspace fallback is removed so a
missing scope fails closed.
…rable copilot surface

Extends requireCopilotWorkspace to the remaining copilot tools that resolved
their target workspace from model-supplied arguments: get_credentials (a
workflowId could steer the credential listing to any workspace the user can
access) and publish_custom_block (a workflowId could deploy/undeploy custom
blocks from another workspace's workflow). The handlers already protected
downstream by the application adapter (create workflow, generate API key,
list/create workspace MCP servers) now use the same guard so a mismatch is
rejected uniformly at the surface, and the getDefaultWorkspaceId fallback is
deleted entirely — no copilot path picks a workspace for the model anymore.
…rop call-site boilerplate

requireCopilotWorkspace now accepts an undefined context and throws a
classified OrchestrationError for the missing-workspace branch too, so every
caller drops the 'context ?? {}' and '|| undefined' coercions and one
instanceof covers the guard. query_logs inlines its now-one-line wrapper,
get_credentials drops the workspace-less special case (a workflow with no
workspace asserts nothing), and publish_custom_block handles the guard
locally instead of widening its catch-all — keeping its deliberate
assume-not-published guidance for unrelated failures.
@vercel

vercel Bot commented Aug 22, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Aug 22, 2026 11:19pm

Request Review

@cursor

cursor Bot commented Aug 22, 2026

Copy link
Copy Markdown

PR Summary

High Risk
Authorization change for Copilot tools that read logs and write secrets/credentials. Tightens workspace isolation, but a bug in the new guard would still affect cross-workspace access.

Overview
Closes a Copilot workspace-scope bypass: model-supplied workspaceId/workflowId could previously target any workspace the user can access (logs, env secrets, credentials, custom-block publish), instead of the chat’s delegated workspace.

requireCopilotWorkspace is now a shared helper in workspace-scope.ts. A model id may only re-assert the execution workspace; missing scope fails closed. The same check is applied to query logs, set env vars, get credentials, custom-block deploy, workflow create, API keys, and MCP server list/create.

getDefaultWorkspaceId is removed so Copilot never picks a workspace for the model. Tests cover mismatch, re-assert, and fail-closed on each surface.

Reviewed by Cursor Bugbot for commit 2009fca. Configure here.

@greptile-apps

greptile-apps Bot commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR centralizes Copilot workspace-scope validation and applies it across model-steerable tools so model-provided workspace or workflow identifiers cannot escape the chat’s delegated workspace.

  • Adds a shared fail-closed requireCopilotWorkspace guard.
  • Applies the guard to logs, credentials, environment variables, custom-block deployment, workflow creation, API-key generation, and workspace MCP operations.
  • Adds mismatch, re-assertion, and missing-scope coverage and replaces the previously reported any casts in the three new query-log scope tests with typed fixtures.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
apps/sim/lib/copilot/tools/server/workspace-scope.ts Introduces the shared fail-closed workspace assertion guard used by Copilot server tools.
apps/sim/lib/copilot/tools/server/workflow/query-logs.ts Restricts log queries to the workspace carried by the trusted Copilot execution context.
apps/sim/lib/copilot/tools/server/user/set-environment-variables.ts Prevents workspace and workflow arguments from redirecting secret writes outside the delegated workspace.
apps/sim/lib/copilot/tools/server/user/get-credentials.ts Validates a workflow-derived credential scope against the chat’s execution workspace.
apps/sim/lib/copilot/tools/server/workflow/query-logs.test.ts Adds workspace-scope coverage and replaces the previously reported any casts in the new tests with typed arguments and context.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  Model[Model tool arguments] --> Guard[requireCopilotWorkspace]
  Context[Trusted chat workspace] --> Guard
  Guard -->|matching or omitted assertion| Workspace[Delegated workspace]
  Guard -->|mismatch or missing context| Reject[Validation error]
  Workspace --> Tools[Protected Copilot tools]
Loading

Reviews (2): Last reviewed commit: "test(copilot): type the new query-logs s..." | Re-trigger Greptile

Comment thread apps/sim/lib/copilot/tools/server/workflow/query-logs.test.ts Outdated
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor 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.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 2009fca. Configure here.

@waleedlatif1
waleedlatif1 merged commit 5a1602e into staging Aug 23, 2026
30 checks passed
@waleedlatif1
waleedlatif1 deleted the fix/copilot-workspace-scope branch August 23, 2026 04:00
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