Cua Docs

Permission modes

Choose standard, bounded, or unrestricted authorization for Cua Driver.

Cua Driver enforces authorization inside the native runtime, after transport arguments are sanitized and before a platform action runs. CLI, MCP, direct SDK, private-worker, and service-backed calls all reach the same enforcement boundary.

The three public names are authorization profiles over that shared engine. They select built-in capability and approval behavior; a capability manifest is a separate narrow-only ceiling.

Choose a mode#

ModeBest forRuntime behavior
standardNormal local CLI and MCP useRoutine operations follow the built-in profile. Residual boundaries still require a launch grant or trusted host decision. An optional capability manifest can narrow tools and resources.
boundedUnattended agents, gateways, and embedded applicationsA capability manifest is required. In-scope work is silent and undeclared scope is denied.
unrestrictedDisposable or fully trusted environmentsCua approval checks are bypassed after an explicit dangerous acknowledgement. An optional capability manifest limits that bypass to declared scope.
ProfileManifest absentManifest present
standardPreserve standard behaviorStandard behavior intersected with manifest scope; residual grants remain required
boundedStartup failsUnattended, deny-by-default bounded behavior with required lifetimes
unrestrictedPreserve the acknowledged approval bypass within existing ceilingsBypass approval only inside manifest scope

standard is the default:

cua-driver mcp

Use bounded with a reviewed manifest:

cua-driver serve \
  --permission-mode bounded \
  --capability-manifest ./cua-capabilities.yaml \
  --approve-capability-manifest

Use unrestricted only when full autonomous access is intentional:

cua-driver serve --dangerously-bypass-approvals

Add the same two capability-manifest flags to standard or unrestricted when that runtime should have a smaller tool and resource surface. A manifest can narrow a profile but never widen it.

Passing --permission-mode unrestricted without --dangerously-bypass-approvals fails closed.

Unrestricted mode does not defend against prompt injection or unintended model actions. Use it only where you accept the full effect of every capability allowed by the built-in, managed, and user policy ceilings.

autonomous remains a manifest compatibility alias for bounded. yolo remains a configuration alias for unrestricted. New integrations should use the canonical names.

Configure a mode without CLI flags#

The mode is read once, when the runtime that owns the driver starts. Only cua-driver serve takes the flags above. A launcher that cannot pass them — cua-driver mcp owning its own runtime on Windows and Linux, a Windows Scheduled Task registered by cua-driver autostart enable, or an embedding host — uses the equivalent environment variables:

FlagEnvironment variable
--permission-mode <mode>CUA_DRIVER_PERMISSION_MODE=<mode>
--capability-manifest <path>CUA_DRIVER_CAPABILITY_MANIFEST_FILE=<path>
--approve-capability-manifestCUA_DRIVER_CAPABILITY_MANIFEST_APPROVED=1
--dangerously-bypass-approvalsCUA_DRIVER_DANGEROUSLY_BYPASS_APPROVALS=1

The variables accept 1, true, yes, or on for their boolean form. The CLI flag normalizes mode plus acknowledgement in one step; the environment form does not, so unrestricted requires CUA_DRIVER_PERMISSION_MODE=unrestricted and CUA_DRIVER_DANGEROUSLY_BYPASS_APPROVALS=1, and bounded requires both the capability manifest and its approval. Missing halves fail startup instead of downgrading to standard.

CUA_DRIVER_SESSION_POLICY_FILE, CUA_DRIVER_SESSION_POLICY_APPROVED, --session-policy, and --approve-session-policy remain deprecated aliases for one compatibility window. New integrations should use the capability manifest names. Conflicting old and new paths fail closed.

These variables are trusted launch configuration on the same footing as the flags. Whoever can write them for the daemon's environment sets its mode, so treat them like the plist, unit file, or Scheduled Task that carries them. An agent tool call can never set them.

A running daemon's mode cannot be changed. Stop it and start it again with the configuration you want.

What standard allows#

Standard mode is designed to preserve practical autonomous workflows. It does not open a Cua confirmation card for routine actions.

OperationStandard behavior
Observe windows, applications, and the desktopAllow
Click, type, scroll, drag, and focusAllow
Create and use a driver-owned isolated browserAllow
Read visible page content through typed browser toolsAllow
Upload, download, screenshot, record, and replay validated pathsAllow
Change agent-adjustable cursor and image settingsAllow and audit
Terminate a process proven to have been launched by this runtimeAllow after process fingerprint revalidation
Terminate a foreign processDeny
Run unbounded legacy page mutation scriptsDeny
Raise an operating-system permission prompt from an agent tool callDeny
Attach to an existing logged-in Chromium profileRequire an explicit launch grant or trusted host authorization
Invoke an unknown risk-bearing operationDeny

Path canonicalization, browser-origin validation, process identity checks, and managed or user policy still apply when standard permits an operation.

Driver-owned isolated browser preparation follows the selected mode and any optional capability manifest. Standard allows it as a routine operation, bounded requires it to match the manifest, and unrestricted relies on the launcher's dangerous acknowledgement.

Existing logged-in Chromium profiles#

An existing profile can contain live cookies and authenticated sites. Standard mode therefore keeps attachment as an explicit boundary.

Authorize it for a newly launched MCP runtime:

cua-driver mcp --grant existing-profile

Authorize it for a daemon:

cua-driver serve --grant existing-profile

--grant is repeatable and is trusted launch configuration. It cannot modify an already-running daemon. Restart that daemon with the same grant when needed.

Other valid authorization paths are:

  • A capability manifest containing the exact profile scope, combined with the profile's normal approval behavior. In bounded it is unattended; in standard a launch grant or trusted host decision is still required.
  • A DriverAuthorizationHost callback installed by an embedding application.
  • unrestricted mode with its dangerous acknowledgement.

An MCP transport marker, model-supplied Boolean, environment variable, or ordinary tool argument is never an attachment grant.

One approved attachment covers the resulting browser binding. Tab changes and reconnection do not create repeated Cua authorization requests. Any configured origin scope still applies to live navigation and input.

See Browser Profile Attachment for the platform and CDP boundary.

Capability manifests#

A configured capability manifest is deny by default in every profile. A tool must appear in allow.tools, and every resource crossed by that call must match the manifest. Approval is considered only after those checks pass.

Manifest version 3 removes profile behavior from the file. It supports the same application identities, browser profile kinds, and directory roots as version 2:

version: 3
expires_after: 8h
idle_timeout: 30m
 
allow:
  tools:
    - start_session
    - end_session
    - launch_app
    - list_windows
    - browser_prepare
    - get_browser_state
    - browser_navigate
    - browser_click
    - browser_type
    - browser_download
    - kill_app
 
resources:
  apps:
    - executable: /usr/bin/example-editor
      launch: true
      windows: all
      terminate: driver_launched
 
  browser:
    profiles:
      - kind: isolated
      - kind: existing_profile
    origins:
      - https://app.example.com
 
  files:
    read:
      - dir: /data/input
        recursive: true
    write:
      - dir: /data/output
        recursive: true
 
  desktop:
    display: false

On macOS, use bundle_id for an application identity. On Windows and Linux, use a canonical absolute executable path. windows: all allows windows owned by the matching application. terminate: driver_launched permits termination only when Cua proved that the current runtime launched that exact process instance.

Browser origins match exact scheme, host, and port. File roots are canonicalized and compared by path component, so a shared string prefix or a symlink escape does not grant access.

Origin scope excludes generic input#

resources.browser.origins binds the typed browser adapter only. A manifest that declares origins therefore cannot also allow a tool that reaches a page around that adapter, and the runtime refuses to start if it does:

authorization startup error: origin-scoped capability manifests cannot allow
'click' because it bypasses the typed browser origin adapter

The excluded tools are click, double_click, right_click, drag, scroll, type_text, press_key, hotkey, set_value, mouse_button_down, mouse_button_up, mouse_drag, parallel_mouse_drag, get_accessibility_tree, get_window_state, verify_state, get_desktop_state, and page.

The exclusion covers observation as well as input. A window screenshot or accessibility tree of a browser window exposes whichever tab is open, regardless of the origin allow-list, so where a browser window is in reach these tools bound neither what an agent may change nor what it may read.

The check is evaluated at load time against allow.tools alone. It does not analyze whether the manifest's application scope actually puts a browser window in reach, so a manifest that names only a non-browser application is refused on the same terms. This is deliberate: deciding reachability would require the runtime to keep a list of browser identities, and a stale list would void the origin boundary silently instead of refusing loudly.

Every navigation is checked against the origin set, so a manifest that allows browser_navigate with no origins refuses every navigation. Browser access and generic desktop input consequently belong to separate manifests and separate runtimes. Use list_windows for the window_id a browser call needs.

An origin scope binds one runtime's tool surface. It is not a property of the browser, the profile, or the machine. A second runtime that can deliver generic input to a browser window — including a standard-mode runtime without a capability manifest, which allows input against every application — voids the first runtime's origin scope without violating it. Scope a companion runtime to non-browser applications with desktop.display: false, and treat same-user processes outside Cua Driver as outside the boundary entirely.

Version 1 and 2 manifests remain loadable. Their mode field is retained for compatibility, and legacy ask.tools entries are treated as deny. Version 3 removes mode and ask.tools. expires_after and idle_timeout are optional in version 3, but any declared lifetime is enforced in every profile. Bounded mode requires both fields.

For a complete tested example, see Write a capability manifest.

Authorization stack#

Every call must pass all applicable layers:

  1. Hard invariants, including self-targeting and protected-host checks.
  2. The reviewed built-in tool and risk map.
  3. Administrator policy from CUA_DRIVER_MANAGED_POLICY_FILE, when set.
  4. User policy from CUA_DRIVER_POLICY_FILE, when set.
  5. The selected profile's capability and approval behavior.
  6. The capability manifest, when configured.
  7. A launch grant or trusted host authorization for a residual standard-mode boundary.

Each layer can narrow access. No manifest, grant, approval bypass, or permission profile can widen a hard invariant or managed/user policy.

The tools/list, manifest, and status surfaces expose content-free enforcement descriptors. Each descriptor states its adapter ID, risk class, resource scope, mode behavior, authorization source, revocation triggers, and stable refusal code.

Host authorization and activity#

An embedding application may install DriverAuthorizationHost when it wants to decide a residual standard-mode request itself. Cua supplies an attested, request-bound resource and digest. The host returns allow, deny, or cancel with that exact digest.

Cua does not render or prescribe the host's consent experience. The host may use product UI, administrator policy, a second device, or another trusted decision source.

An optional DriverActivityObserver receives content-free action, authorization, grant, and session events. Events never contain page text, typed input, file contents, screenshots, or raw resource identities.

When no launch grant or host callback exists, a residual boundary returns a structured authorization_required refusal. It does not open a Cua-owned modal.

Revocation#

End one public session:

cua-driver revoke --session research-1

Suspend the complete runtime generation:

cua-driver revoke --all

Session end removes its grants, browser bindings, launch provenance, recording state, and cursor. The ended session label remains tombstoned until an explicit start_session re-declares it.

revoke --all is terminal for that runtime generation. Later calls, including anonymous calls, return authorization_suspended. Restart the runtime to create a fresh authorization generation.

Cursor and session badge#

The semantic cursor is optional activity feedback. It initializes on the first cursor-bearing action even when the transport uses an implicit session. A publicly named session displays its sanitized label in a badge below the cursor. The badge uses the session color, strips control characters, collapses whitespace, and truncates long labels.

The cursor and badge are not authorization signals. Hiding the cursor also hides the badge. Headless sessions do not require either.

Security boundary#

The host owns the permission profile, capability manifest, launch grants, and any human consent UX. Agent tools cannot change them.

Same-user native code, malware, and automation with control of the same desktop are outside Cua Driver's security boundary. Cua can prevent an agent from forging its own tool arguments, but it cannot turn an ordinary desktop window into a secure desktop.