Skip to content

[Feat] Enforce per-tool approval policies at the integration proxy - #3072

Merged
daniel-lxs merged 5 commits into
developfrom
feat/tool-approvals-proxy-enforcement
Sep 21, 2026
Merged

daniel-lxs merged 5 commits into
developfrom
feat/tool-approvals-proxy-enforcement

Conversation

@daniel-lxs

Copy link
Copy Markdown
Member

Summary

Per-tool approval policies (the integrationToolApprovals experiment, #3001 and #3069) were enforced only inside Sessions. A task calling the same integration tool ran it ungated, and since a Session can launch a task, a call gated in the Session could be handed to a task and run with no approval.

A Session can enforce natively because its agent has no shell. A task's agent has a shell next to its MCP configuration, so nothing inside the sandbox can be the boundary there. The integration proxy is the one place every caller crosses, so enforcement goes there:

  • Reject is refused for every caller, Sessions and tasks alike.
  • Ask first is refused for task runs, which have no approval flow yet. Session calls pass: their native ask was already decided by the Session owner before the call reaches the proxy.
  • Blocked tools are hidden from tools/list and a call to one gets a specific error (for a task's Ask first tool: it needs approval and should be run from a Session), the same way disabled tools are handled.
  • The stricter of the deployment policy and the acting user's personal policy applies.
  • Unreadable policies fail the request closed. With the experiment off nothing is read and nothing is blocked; the acting user is only looked up while it is on.

The built-in integration proxy, the Linear proxy, and the custom server proxy all opt in through the shared createMcpProxy. The experiment's settings copy now says Reject applies to tasks and that Ask first tools are unavailable to them.

Not in this PR

  • An approval flow for tasks (native ask rules in the task's agent config plus a worker-side bridge to the task owner). Until then Ask first fails closed in tasks.
  • Custom servers that run over stdio inside the sandbox never cross the proxy, so they are not enforced here.

Testing

  • Unit tests for the enforcement rules (reject for all callers, ask for task runs only, stricter-of-both with personal policies, no human actor, experiment off) and proxy tests (policy keyed by server name, blocked call refused with the policy reason and no upstream contact, blocked tools hidden from the list, fail closed). The full MCP handler suite passes.
  • Live against a local stack with a task run token and a Session token on a server with an Ask first tool: the task token got a 403 with the approval message and a tool list without the gated tools; the Session token ran the same tool successfully.

@roomote-community

roomote-community Bot commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

No new code issues found. See task

  • Custom MCP approval policies use a non-unique server-name key across deployment and personal scopes.
  • Seeded development custom MCP server omits its deployment approval-policy scope for Fast sessions (packages/sdk/src/server/routers/mcp-connections.ts:422).

Reviewed e1c1396

Comment thread apps/api/src/handlers/mcp/custom-mcp.ts
Comment thread packages/sdk/src/server/routers/mcp-connections.ts Outdated
@daniel-lxs
daniel-lxs merged commit 99a9e95 into develop Sep 21, 2026
17 checks passed
@daniel-lxs
daniel-lxs deleted the feat/tool-approvals-proxy-enforcement branch September 21, 2026 22:19
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