Skip to content

Unify session-scoped workspace permissions and add user approval notifications #166

Description

@mprealtrainingsys

Summary

Make session-scoped workspace permissions a first-class, observable contract across MCP Bridge, custom tools, and the UI. When an agent is blocked from an external path, surface a safe permission request through the existing notification UI so the user can explicitly approve or deny read access instead of receiving only a tool error.

This is a future design/implementation item. Do not weaken folder guards or automatically grant paths as part of this issue.

Incident / motivation

A Claude Code workflow-builder session had a valid read-only grant for /Users/<user>/Downloads, but execute_shell_command rejected the path.

RCA:

  1. MCP Bridge sent the correct session identity in X-Session-ID.
  2. The backend used the header to select the session-scoped custom-tool registry.
  3. The global custom-tool route did not copy that identity into the Go execution context.
  4. Workspace policy therefore fell back to the generic workflow guard and missed session-specific state such as host Downloads access, blocked-write paths, working directory, browser mode, and session shell environment.

The immediate regression is fixed in local commit 0fb9f2d4 by propagating the header into context and adding a trusted MCP_SESSION_ID fallback. This issue tracks the broader contract, E2E coverage, observability, and permission UX so the same class of bug cannot return elsewhere.

Proposed design

1. One authoritative session identity

  • Resolve session identity once at the HTTP/tool boundary.
  • Carry a typed runtime/session context through every tool call.
  • Use the same identity for registry lookup, folder guard, working directory, shell environment, browser mode, costs, logs, and notifications.
  • Reject conflicting session identities from URL, trusted header, request body, or client environment instead of silently choosing one.

2. Structured permission-denied event

When folder guard rejects access, emit a structured event rather than only a text error:

  • session, workflow, execution, tool, and request IDs
  • canonical requested path
  • requested operation: read, write, move, delete, or execute
  • denial reason and active policy scope
  • whether the request is eligible for user approval
  • safe suggested scope, such as one file or one folder read-only

Never include file contents, secrets, or raw authorization material in the event.

3. Notification UI integration

Show eligible denials in the existing notification surface as a permission request:

  • Allow once: one request only
  • Allow for this session: expires with the session
  • Always allow read-only on this device: optional durable local grant
  • Deny

The UI must clearly show the workflow, agent, operation, and canonical path. The safest scope should be selected by default. Initially, approval should not silently replay a potentially non-idempotent tool call; notify the agent/user that the operation can be retried. Automatic replay can be designed separately with request IDs and idempotency protection.

4. Permission model

  • External paths remain denied by default.
  • Host Downloads may be offered as read-only; writes, moves, and deletes remain blocked unless separately and explicitly designed.
  • Durable grants are device-local and must not sync through workflow JSON or backups.
  • Canonicalize paths and resolve symlinks before comparing scopes.
  • Provide a settings view to inspect and revoke grants.
  • Record an audit trail of approval, denial, expiry, and use.

5. Cross-provider E2E contract

Run the same tests for Claude Code, Codex, Cursor, and Pi through the real MCP Bridge path:

  • global /tools/custom/... with X-Session-ID
  • custom tools redirected through /tools/mcp/...
  • session-scoped /s/{session}/tools/...
  • direct in-process execution where still supported

Verify that every path resolves the same session, working directory, folder guard, blocked-write paths, shell environment, and notification owner.

Acceptance criteria

  • Session identity has one documented resolver and conflict behavior.
  • No custom or MCP tool route can select a session registry while executing with a different or empty policy session.
  • A real bridge E2E test reproduces the original host Downloads case.
  • Read-only approval cannot be used for writes, moves, deletes, symlink escapes, parent traversal, or command indirection.
  • Eligible denials appear once in the notification UI and can be approved or denied.
  • Grants expire/revoke correctly and are visible in an audit log.
  • Existing workflow, Pulse, Chief of Staff, background-agent, and scheduled-run folder guards remain fail-closed.

Security cases to test manually

  • symlink inside an approved folder pointing outside it
  • path replacement between approval and execution (TOCTOU)
  • quoted paths, spaces, globbing, pipes, redirects, heredocs, and subshells
  • one workflow attempting to reuse another workflow's grant
  • stale or forged session IDs
  • approval on one laptop appearing on another laptop
  • background agent requesting a broader scope than its parent
  • notification floods from repeated retries

Non-goals

  • Automatically allowing arbitrary external folders
  • Giving agents write access to host Downloads by default
  • Syncing local filesystem grants across devices
  • Implementing the approval UI in the current fix

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions