Computer-use threat model

Companion to docs/guides/computer-use.md. This document captures the assets, attack surfaces, mitigations, and the penetration-test runbook for the computer_use server tool.

Assets

  1. End-user identity and credentials that the agent may be asked to enter on a third-party site.
  2. Host application state (cookies, local storage, the DOM of the chat host page).
  3. Vendor session integrity — the hosted Chromium that runs the actual browsing.
  4. Audit trail — must be tamper-evident so a post-incident review can reconstruct what the agent did.
  5. The kill switch — must be reachable even when the rest of the system is degraded.

Trust boundaries

BoundaryDirectionNotes
Browser → customer proxyoutboundTLS + chat token (short-lived). Idempotency-Key required.
Customer proxy → vendoroutboundVendor API key, scoped to the configured project. Never reaches the browser.
Vendor Chromium → arbitrary internetoutboundRestricted by vendor allowlist + proxy's pre-flight allowlist check.
Vendor screenshots → proxy → browserinboundRe-hosted as signed URLs; never directly served by the vendor to the browser.
Iframe → host pageinboundBlocked by sandbox="" (no scripts, no same-origin, no top-nav).

Attack surfaces & mitigations

A1. Agent navigates to an off-allowlist host

  • Risk: Data exfiltration, phishing, privilege escalation on a target unrelated to the user's goal.
  • Mitigation: The proxy's ComputerUseSession.dispatch re-checks every URL against policy.allowlist before forwarding to the provider. The SDK's assertComputerUseAllowed fast-fails before the HTTP round-trip. Browserbase additionally honors the browserSettings.allowedUrls we pass. Three layers of defense.
  • Test: packages/gecx-chat/test/computerUseGovernance.test.ts includes a fuzz pass against javascript:, data:, file:, IDN homoglyphs, IPv6, and path-traversal-style inputs. The proxy-side apps/proxy-reference/test/computerUseSession.test.ts confirms an off-allowlist URL throws COMPUTER_USE_ALLOWLIST_VIOLATION and audits the violation.

A2. Compromised screenshot payload reaches the host page

  • Risk: A malicious page coerces the vendor into serving HTML that, if rendered in the host page, could exfiltrate auth cookies.
  • Mitigation: <ComputerUseSurface> renders the screenshot inside an iframe whose sandbox attribute is the empty string — no scripts, no same-origin, no top-navigation, no popups. The iframe srcDoc references only an <img> with the proxy-supplied URL; HTML special characters in the URL are entity-escaped. The action log is plain text built from the structured event stream, not from remote HTML.
  • Test: packages/gecx-chat/test/react/ComputerUseSurface.test.ts asserts the iframe is emitted with sandbox="".

A3. Stream URL leak

  • Risk: A leaked streamUrl (in browser history, logs, etc.) lets an attacker reconnect to a live or past session and replay screenshots.
  • Mitigation: The proxy signs every streamUrl with HMAC and a 60-second TTL. Tokens are verified before any session lookup so callers cannot probe for valid session ids by toggling tokens. The verification uses a constant-time compare.
  • Test: apps/proxy-reference/test/computerUseSession.test.ts asserts an invalid token returns 401 even when the session id is valid.

A4. Action-loop exhaustion / resource exhaustion

  • Risk: An agent that loops indefinitely could exhaust action budgets and pin a vendor session at $$$ cost.
  • Mitigation: maxActionsPerSession (default 30) and maxDurationMs (default 5 minutes) are hard caps enforced by ComputerUseSession. A duration timer fires terminate('duration_exceeded', ...) from a setTimeout. Crossing the action cap raises ComputerUseActionLimitExceeded and tears the session down.
  • Test: apps/proxy-reference/test/computerUseSession.test.ts exercises the action-limit path.

A5. Kill-switch failure under load

  • Risk: Operator flips the kill switch during an incident but in-flight sessions don't tear down.
  • Mitigation: setKillSwitch(true) calls session.kill(reason) on every active session synchronously. Every session has an AbortController whose signal is wired into the provider, so any in-flight act() aborts. The kill switch also blocks all new sessions with COMPUTER_USE_PROVIDER_UNAVAILABLE.
  • Test: apps/proxy-reference/test/computerUseSession.test.ts "stops the in-flight session when the kill switch flips".

A6. Audit-tampering or audit-loss

  • Risk: An audit sink that crashes or backpressures could silently drop events, undermining post-incident review.
  • Mitigation: ChatGovernance.emit wraps sink invocations in try/catch — a failing sink cannot break the SDK, but the SDK will not stop calling it. Hosts should plumb the sink into a durable queue (Pub/Sub, Kinesis, Kafka). The event includes requestId, computerUseSessionId, and details.actionId for full correlation.
  • Test: packages/gecx-chat/test/computerUseGovernance.test.ts asserts the audit sink fires for allowlist violations, action emits, and kill-switch activations.

A7. Vendor account compromise

  • Risk: Stolen Browserbase API key would let an attacker create vendor sessions on our account.
  • Mitigation: The key never reaches the browser bundle (server-only gecx-chat/server subpath). The proxy validates env at boot. Rotate per deployment. Vendor sessions are short-lived; even a stolen key gives an attacker minutes per session, not hours.

A8. Replay of completed tool calls

  • Risk: An attacker re-submits a completed computer_use tool call to redo the actions on the user's behalf.
  • Mitigation: defineServerTool requires Idempotency-Key; replays return the cached result rather than dispatching a new session. The TTL is 60 minutes; after that the request is treated as new but still subject to allowlist + consent.

Threat-model-aware deployment checklist

  • governance.computerUse.allowlist is set and reviewed.
  • Proxy env COMPUTER_USE_ALLOWLIST matches the SDK config.
  • COMPUTER_USE_STREAM_KEY is set to a value rotated per deployment.
  • Browserbase API key + project id are stored in a secret manager, not on disk.
  • Audit sink writes to a durable destination (Cloud Logging, SIEM).
  • Kill switch is reachable via at least one out-of-band channel (admin REST endpoint, env reload).
  • An end-to-end e2e test runs against the mock provider in CI.
  • A monthly drill verifies the kill switch tears down a live session within 1 second.

Penetration-test runbook

  1. Allowlist fuzz. Issue computer_use calls with URLs from the fuzz set: javascript:, data:, file:, ftp:, IDN homoglyphs (еxample.com), bare hostnames with trailing whitespace, mixed-case schemes, double-encoded paths, IPv6 literals, link-local addresses, fragment-only URLs. Every input must produce COMPUTER_USE_ALLOWLIST_VIOLATION and emit governance.computer_use.allowlist_violation.

  2. Stream-token replay. Capture a streamUrl from a live session, wait for the session to end, then replay the URL. Expect 401 / COMPUTER_USE_TOKEN_INVALID.

  3. Iframe escape. Inject a screenshot URL that is in fact an <html> payload with inline scripts. Confirm the iframe's sandbox="" policy prevents execution by inspecting the host page's console for any injected events.

  4. Kill-switch under load. Spin up 50 concurrent mock sessions, then POST /admin/computer-use/kill-switch { "on": true }. Within 1 second every session must emit governance.computer_use.killed and governance.computer_use.session_ended with status: 'aborted'. No orphaned Browserbase sessions remain (verify via the vendor dashboard).

  5. Action-budget loop. Use the deterministic mock provider and a planner that always returns the same action. Confirm the session terminates with action_limit_exceeded after maxActionsPerSession iterations, with one audit event per action plus a terminal session_ended.

  6. Audit-sink failure mode. Wire an audit sink that throws synchronously. Confirm the SDK and proxy continue to function; no exceptions bubble out; subsequent sink invocations are still attempted.

  7. Bundle inspection. Run pnpm build:packages && grep -r "BROWSERBASE_API_KEY\|playwright\|node:http" packages/gecx-chat/dist/index.js. Expect zero hits — server-only modules must not appear in the browser bundle.

Reporting

If you discover a vulnerability in the computer-use subsystem, follow SECURITY.md. Tag the report with computer_use so it is routed to the matching owner.

Source: docs/reference/computer-use-threat-model.md