Skip to content

Gate the CLI-facing /api/* routes behind a local auth/origin check #265

Description

@germanescobar

Summary

The Controller server exposes its CLI-facing HTTP routes with global CORS and no authentication. server/index.ts does app.use(cors()) and binds with no token, so any web page the user visits can reach the Controller port and drive these endpoints. They trust a client-supplied cwd to scope work to a worktree, but nothing stops an arbitrary origin from POSTing to them.

Surfaced in review of #262 (PR for #261): the new POST /api/terminal/command run action is a local command-execution sink — a malicious page could enumerate projects/worktrees/open terminals via the existing read APIs, then inject arbitrary text into an open terminal tab. The same exposure already applies to the other CLI surfaces:

  • POST /api/terminal/command (action: "run") — inject into a terminal — server/routes/terminal.ts
  • POST /api/browser/command — drive the preview browser — server/routes/browser.ts
  • POST /api/integrations/gateway/* — call connected third-party services
  • POST /api/projects/:id/sessionsstart agent sessions
  • POST /api/projects/:id/schedules — schedule future agent runs

This is an app-wide architectural gap, not specific to the terminal route, which is why it's tracked separately rather than bolted onto #262.

Proposed direction

Add a single guard in front of the CLI-facing /api/* routes:

  • The server already installs the CLI and publishes a runtime file (controller-runtime.json) next to it. Publish an unguessable token there too and require it (e.g. X-Controller-Token) on the CLI routes; the CLI already reads that file to resolve the server URL, so it can attach the token transparently.
  • And/or tighten CORS to a strict allowlist and reject cross-origin requests on these routes.
  • Keep the renderer's existing access working (it runs same-origin / in-process).

Acceptance criteria

  • A request to a CLI-facing /api/* route without the token (or from a disallowed origin) is rejected.
  • The controller CLI continues to work unchanged for the agent (token attached automatically).
  • The renderer (Terminals/Preview tabs, project UI) continues to work.
  • Covers terminal, browser, integrations gateway, sessions, and schedules routes.

Refs

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