11 min read

Cua: Sandboxed Desktops and Drivers for Computer-Use Agents (GitHub, Scanned)

Give AI agents their own desktops: local VMs, sandboxes and a driver that operates real apps.

Cua logo
✅
Scan: safe. Nothing malicious. Know that the installers are curl | sh scripts, telemetry to PostHog is on by default, and the Spaces app can register a login agent and move signed-in app sessions into a Space. Scanned Oct 26, 2026; the full report is below.

Cua is a toolkit for computer-use agents: AI agents that operate a desktop by looking at the screen and clicking and typing. The repository holds several products. Cua Driver lets an agent inspect and operate native apps and browsers on macOS, Windows and Linux through a CLI, MCP or SDKs, often in the background without moving your pointer. The cua CLI and SDK (Python, TypeScript, Rust) create local sandboxes, VMs and containers an agent can run in. Lume creates macOS and Linux VMs on Apple Silicon. Cua Bench builds tasks for evaluating agents, and Cua Spaces is a desktop app that gives agents full desktops on your Mac or machines you own.

It is on this list because running an agent against your real desktop is risky, and Cua's main idea is to give the agent its own machine instead. A disposable sandbox you can screenshot, script and throw away is a far safer place to let a model click around, and the driver works with Claude Code, Codex, Cursor and other MCP clients.

It is a large and fast-moving project, about 3.3 million lines across Rust, Python, TypeScript and Swift, with frequent releases. Licences are mixed: the libraries are MIT, but the Cua Spaces app is source-available under FSL-1.1-MIT, free for individuals with paid Pro and Teams plans. Spaces needs macOS 26 or later, and several older Python packages are marked deprecated, including cuabot, which the README says has known security issues and should be uninstalled.

  • Repository: github.com/trycua/cua
  • Licence: MIT (MIT License)
  • Language: Rust. Stars: 31K. Forks: 2,268. Last push: Oct 26, 2026.
  • Scan: safe, Oct 26, 2026, commit 4b84caa

Who it is for

Developers building or testing computer-use agents who want isolated desktops and sandboxes, and Claude Code or Codex users who want their agent to operate desktop apps through MCP.

Getting started

1. Install the cua CLI on macOS or Linux (Windows: irm https://cua.ai/install.ps1 | iex)

curl -fsSL https://cua.ai/install.sh | sh

2. Create a local Linux sandbox and run a command in it

cua sb create ubuntu --name dev && cua sb exec dev uname -a

3. Or install Cua Driver to let an agent operate your apps

/bin/bash -c "$(curl -fsSL https://cua.ai/driver/install.sh)"

All installers are shell or PowerShell scripts fetched from cua.ai and run as is; the repository holds their sources if you want to read them first. On macOS the main installer adds the Cua Spaces app by default; it asks first. A signed .dmg is also available from the GitHub releases.

Safety scan

We cloned trycua/cua at commit 4b84caa on Oct 26, 2026 and ran the checks described on the GitHub Tools page: credential patterns, decode-and-execute code, install-time scripts, committed binaries, risky CI workflows, every host the code talks to, known vulnerabilities in pinned dependencies, and project hygiene. A person read every hit. This is what we found.

  • The one secret hit, in scripts/cli-cast/record.py line 76, is the replacement string AKIAREDACTEDREDACTED in a function that scrubs AWS keys out of terminal recordings. It is not a key.
  • Of 222 pattern hits, 140 are persistence: the Cua Spaces Mac app and its helper registering a LaunchAgent so the Spaces host starts at login, plus test fixtures that reference it. 63 are curl | sh one-liners for Cua's own installers in docs, tests and generated SDK comments. The base64 exec in cua-bench's remote.py and the PowerShell -EncodedCommand in libs/images/windows-2022/guest-exec.py encode commands sent into a sandbox or VM, and the /dev/tcp hit is a 3-second connectivity check against 1.1.1.1.
  • Telemetry is on by default and sends usage events to PostHog's EU servers. Set CUA_TELEMETRY=0 or DO_NOT_TRACK=1, or turn it off in ~/.cua/config.toml; it is off automatically in CI.
  • Four workflows use pull_request_target, but none checks out the pull request's code: two only post comments (the CLA check and a release reminder) and the contributor-attribution job checks out the trusted base commit. 179 of 268 third-party action uses are pinned to commits. Dependabot, security policy and contributing guide present.
  • 644 known advisories across 63 lockfiles (38 critical). Most sit in examples, benchmark task apps, test fixtures and the docs site; the main Rust lockfiles (libs/cua and libs/cua-spacesd) carry 15 each, and 104 of the total have no severity rating. Two .ods spreadsheets in benchmark fixtures were flagged as archives; they are test documents.

What the scanner counted

CheckResult
Secrets1 candidate found and read; see the notes above.
Suspicious code222 pattern hits found and read; every one is listed under the raw findings.
Install-time code3 npm lifecycle scripts. 1 setup.py with custom install logic. 27 Cargo build scripts. 131 installer scripts (one fetches and runs a remote script; one edits your shell profile; one can call sudo)
Committed binaries2 executable or compiled objects committed; listed under the raw findings.
CI workflows200 workflows. 4 use pull_request_target, none check out the pull request head. 89 of 268 third-party actions pinned to a tag rather than a commit.
Network hosts40 distinct hosts referenced from source; most often github.com, cua.ai, app.cua.ai, cyclops.example. 2 URLs to a bare IP address, listed under the raw findings.
Known vulnerabilities644 advisories across 5,145 pinned packages: 38 critical, 213 high, 232 moderate, 57 low, 104 unrated. .github/scripts/cua-driver-mcp-compat/modern-client/package-lock.json: 19 packages, 10 advisories; .github/scripts/cua-driver-mcp-compat/package-lock.json: 109 packages, 24 advisories; apps/cua-spaces-desktop/pnpm-lock.yaml: 419 packages, 16 advisories; apps/cua-spaces-web/pnpm-lock.yaml: 257 packages, 10 advisories; apps/cua-spaces/core-wasm/Cargo.lock: 33 packages, 0 advisories; apps/cua-spaces/pnpm-lock.yaml: 236 packages, 11 advisories; apps/cua-spaces/src-tauri/Cargo.lock: 857 packages, 23 advisories; docs/pnpm-lock.yaml: 437 packages, 19 advisories; docs/scripts/docs-mcp-server/uv.lock: 143 packages, 10 advisories; examples/driver/jukebox/Cargo.lock: 122 packages, 0 advisories; examples/driver/multi-cursor/Cargo.lock: 45 packages, 0 advisories; examples/openkoalabot-example-tauri/pnpm-lock.yaml: 175 packages, 12 advisories; examples/openkoalabot-example-tauri/src-tauri/Cargo.lock: 830 packages, 20 advisories; examples/openkoalabot-example-ts/package-lock.json: 74 packages, 6 advisories; examples/streaming/rust/Cargo.lock: 586 packages, 9 advisories; examples/streaming/typescript-web/package-lock.json: 2 packages, 0 advisories; libs/cua-bench-rl/uv.lock: 147 packages, 63 advisories; libs/cua-bench/tasks/winarena_adapter/infra/vm/setup/server/requirements.txt: 3 packages, 52 advisories; libs/cua-bench/uv.lock: 169 packages, 75 advisories; libs/cua-driver-bench/taskpack/tasks/shared/cdb-s02/apps/lighthouse-desk/package-lock.json: 13 packages, 13 advisories; libs/cua-driver-bench/taskpack/tasks/shared/cdb-s03/apps/ledger-lantern-mail/package-lock.json: 13 packages, 13 advisories; libs/cua-driver-bench/taskpack/tasks/shared/cdb-s04/apps/margin-lantern-manual/package-lock.json: 13 packages, 13 advisories; libs/cua-driver-bench/taskpack/tasks/shared/cdb-s04/apps/rillwatch-cases/package-lock.json: 13 packages, 13 advisories; libs/cua-driver/examples/agent-sdks/package-lock.json: 168 packages, 14 advisories; libs/cua-driver/examples/agent-sdks/requirements.txt: 3 packages, 0 advisories; libs/cua-driver/examples/eve/package-lock.json: 67 packages, 7 advisories; libs/cua-driver/examples/jev-use/package-lock.json: 129 packages, 13 advisories; libs/cua-driver/examples/jev-use/uv.lock: 40 packages, 2 advisories; libs/cua-driver/rust/Cargo.lock: 642 packages, 22 advisories; libs/cua-driver/tests/fixtures/apps/cross-platform/electron/package-lock.json: 413 packages, 78 advisories; libs/cua-driver/typescript/package-lock.json: 27 packages, 0 advisories; libs/cua-s1/python/uv.lock: 98 packages, 53 advisories; libs/cua-spacesd/Cargo.lock: 784 packages, 15 advisories; libs/cua-spacesd/tests/spaces-e2e/Cargo.lock: 896 packages, 15 advisories; libs/cua-spacesd/tests/teleport-e2e/Cargo.lock: 743 packages, 14 advisories; libs/cua/Cargo.lock: 1,010 packages, 15 advisories; libs/cua/bench/streaming/Cargo.lock: 292 packages, 6 advisories; libs/cua/crates/cua-contrib/modal-helper/go.mod: 16 packages, 5 advisories; libs/cua/crates/cua-spacesd-html5/web/pnpm-lock.yaml: 139 packages, 8 advisories; libs/cua/python/uv.lock: 347 packages, 61 advisories; libs/cua/typescript/integrations/pi-durable/package-lock.json: 117 packages, 0 advisories; libs/cua/typescript/package-lock.json: 27 packages, 3 advisories; libs/cuabot/pnpm-lock.yaml: 372 packages, 15 advisories; libs/fleet/Cargo.lock: 247 packages, 13 advisories; libs/fleet/backend/go.mod: 108 packages, 61 advisories; libs/fleet/pnpm-lock.yaml: 385 packages, 77 advisories; libs/fleet/rbac-e2e/go.mod: 45 packages, 22 advisories; libs/fleet/sdk-bindings/ts-uniffi-browser/package-lock.json: 65 packages, 21 advisories; libs/fleet/terraform-provider-fleets/go.mod: 95 packages, 39 advisories; libs/images/tools/cua-image-pack/Cargo.lock: 358 packages, 5 advisories; libs/python/cua-sandbox-apps/uv.lock: 73 packages, 51 advisories; libs/python/cua-sandbox/uv.lock: 105 packages, 62 advisories; libs/typescript/pnpm-lock.yaml: 392 packages, 11 advisories; libs/xfce-cua/requirements.txt: 1 packages, 0 advisories; libs/xfce/requirements-cua-driver.txt: 1 packages, 0 advisories; pnpm-lock.yaml: 1 packages, 0 advisories; scripts/docs-generators/requirements.txt: 1 packages, 0 advisories; scripts/docs-generators/rustdoc-json/Cargo.lock: 13 packages, 0 advisories; tests/compat/daytona/ts/package-lock.json: 215 packages, 0 advisories; tests/compat/modal/go/go.mod: 16 packages, 5 advisories; tests/e2e/cua-sdk/rust/Cargo.lock: 586 packages, 9 advisories; tests/e2e/local-runtimes/Cargo.lock: 533 packages, 7 advisories; uv.lock: 386 packages, 96 advisories.
Project hygieneHas security policy, automated dependency updates, licence file, contributing guide. Missing CodeQL.
OpenSSF ScorecardNot scored: the project is not in Scorecard's weekly index.

The raw findings

Every hit the scanner wrote out, with a link to the exact line at the scanned commit. Secrets candidates are redacted.

Secret candidates (1, redacted)
WhereRuleMatch
scripts/cli-cast/record.py:76aws-access-keyAKIARE…TED (20 chars)
Pattern hits (222)
WhereRuleMatch
.github/scripts/tests/test_driver_script_encoding.py:7download-piped-to-shell (test/example)curl -fsSL https://cua.ai/driver/install.sh | sh
.github/scripts/tests/test_driver_script_encoding.py:76download-piped-to-shell (test/example)"`irm ... | iex` and `curl ... | sh` one-liners (see #3174)."
.github/scripts/validate_release_versions.py:65download-piped-to-shell# The installers run from `curl | bash` and `irm | iex` and cannot read repo
apps/cua-spaces-desktop/src/native/generated/cua_sdk.ts:13482download-piped-to-shell* `curl … | sh -s -- --pair <code>` (macOS, Linux): only when just made.
apps/cua-spaces-desktop/test/host-failure.test.ts:83persistence (test/example)'local runtime: service: "launchctl" "bootstrap" "gui/501" "/Users/u/Library/LaunchAgents/com.trycua.spacesd.host.plist" failed: Bootstrap failed: 5: Input/outp…
apps/cua-spaces-desktop/test/host-fixtures.ts:267download-piped-to-shell (test/example)installSh: `curl -fsSL https://cua.ai/install.sh | sh -s -- --pair ${code}`,
apps/cua-spaces-macos/Sources/CuaSpacesMac/ServiceLauncher.swift:9persistence// Contents/Library/LaunchAgents/
apps/cua-spaces-macos/Sources/CuaSpacesMac/main.swift:39persistence// (Contents/Library/LaunchAgents/<CuaHelperLabel>.plist, by default
apps/cua-spaces-macos/Sources/CuaSpacesMacKit/Models/DevicesModel.swift:209download-piped-to-shellinstallSh: "curl -fsSL https://cua.ai/install.sh | sh -s -- --pair \(code)",
apps/cua-spaces-macos/Sources/CuaSpacesMacKit/Models/LoginItem.swift:90persistence/// `SMAppService.agent` from Contents/Library/LaunchAgents/<label>.plist
apps/cua-spaces-macos/Tests/CuaSpacesMacTests/HostSetupFailureTests.swift:98persistence (test/example)"local runtime: service: \"launchctl\" \"bootstrap\" \"gui/501\" \"/Users/u/Library/LaunchAgents/com.trycua.spacesd.host.plist\" failed: Bootstrap failed: 5: In…
apps/cua-spaces-macos/scripts/build-app.sh:227persistencehelper_plist="$app/Contents/Library/LaunchAgents/$helper_label.plist"
apps/cua-spaces-macos/scripts/build-release.sh:178persistence[ -f "$app/Contents/Library/LaunchAgents/com.trycua.spaces.helper.plist" ] ||
apps/cua-spaces-macos/scripts/install-local.sh:253download-piped-to-shellhave cargo || missing "Rust (cargo and rustup): curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh (then open a new terminal)"
apps/cua-spaces-macos/scripts/install-local.sh:813persistencefor helper_plist in "$app"/Contents/Library/LaunchAgents/*.plist; do
apps/cua-spaces-macos/scripts/test-helper-upgrade.sh:104persistencecheck "the old plist is gone" '[ ! -e "$HOME/Library/LaunchAgents/$label_old.plist" ]'
apps/cua-spaces-macos/scripts/tests/install-local-test.sh:199persistence (test/example)cat > "$app/Contents/Library/LaunchAgents/$helper.plist" <<PLIST
apps/cua-spaces-macos/scripts/tests/install-local-test.sh:419persistence (test/example)"Library/LaunchAgents/com.trycua.spacesd.host.plist"
apps/cua-spaces-macos/scripts/tests/install-local-test.sh:420persistence (test/example)"Library/LaunchAgents/com.trycua.lume_daemon.plist"
apps/cua-spaces-macos/scripts/tests/install-local-test.sh:460persistence (test/example)echo '<plist/>' > "$FAKE_HOME/Library/LaunchAgents/com.trycua.spacesd.host.plist"
apps/cua-spaces-macos/scripts/tests/install-local-test.sh:461persistence (test/example)echo '<plist/>' > "$FAKE_HOME/Library/LaunchAgents/com.trycua.lume_daemon.plist"
apps/cua-spaces-macos/scripts/tests/install-local-test.sh:1324persistence (test/example)echo '<plist/>' > "$FAKE_HOME/Library/LaunchAgents/com.trycua.spacesd.host.local.plist"
apps/cua-spaces-macos/scripts/tests/install-local-test.sh:1365persistence (test/example)check "the Local host runner job file is gone" '[ ! -e "$FAKE_HOME/Library/LaunchAgents/com.trycua.spacesd.host.local.plist" ]'
apps/cua-spaces-macos/scripts/uninstall-local.sh:101persistenceHOST_JOB_PLIST="$HOME/Library/LaunchAgents/$LOCAL_HOST_LABEL.plist"
and 198 more
URLs to bare IP addresses (2)
WhereRuleMatch
libs/cua/crates/cua-cluster/src/link.rs:900ip-literal-url"http://100.64.0.7:3211"
libs/python/cua-e2b/tests/test_direct_machine.py:54ip-literal-urlmonkeypatch.setenv("CUA_E2B_ON", "direct:http://1.2.3.4:5")
npm lifecycle scripts (3)
  • docs/package.json postinstall: fumadocs-mdx
  • libs/cua-driver/typescript/package.json prepack: npm run build
  • libs/cua/typescript/package.json prepack: npm run build
Installer scripts (131)
Committed binaries (2)
  • libs/cua-driver-bench/taskpack/tasks/shared/cdb-s03/fixture/planning/kestrel-wharf-reconciliation.ods: JAR, 3 KB
  • libs/cua-driver-bench/taskpack/tasks/shared/cdb-s02/fixture/planning/lighthouse-replan.ods: JAR, 2 KB
Worst known vulnerabilities (24 of 644)
AdvisorySeverityPackageSummary
GHSA-jqcg-44mw-7w3hcriticalproxy-addr@2.0.7proxy-addr vulnerable to IP spoofing via IPv4-mapped IPv6 trust subnet
GHSA-5gmw-xhrv-c9v3criticaltinypool@1.1.1Tinypool: Prototype Pollution gadget in worker options leads to Remote Code Execution
GHSA-85c8-ppgw-ccprcriticaltinypool@1.1.1Tinypool: Prototype Pollution Gadget to RCE in run() options
GHSA-4684-h2q9-2vcpcriticalzip@4.6.1ZipStreamReader::extract() and ZipArchive::extract() apply Unix permissions through symlinks without confining the targe…
GHSA-2464-fhr4-w9xwcriticalnext@16.3.6Next.js: Unauthenticated Remote Code Execution in Image Optimization API when SVG files are used
GHSA-673q-mjm6-r5xrcriticalnext@16.3.6Next.js: Unauthenticated Remote Code Execution in `use cache` functions returning typed arrays
GHSA-23hp-3jrh-7fpwcriticaltar@7.5.16node-tar: Decompression/parse DoS via unlimited input
GHSA-332p-7hrc-92wfcriticalpillow@12.3.0Pillow: Heap buffer overflow in _tiffWriteProc when saving TIFF to BytesIO
GHSA-5x8w-8jj5-q52hcriticalpillow@12.3.0Pillow: Heap buffer overflow in FlashPix (FPX) JPEG decoding leads to code execution
GHSA-8g5g-8vmr-9782criticalpillow@12.3.0Pillow: Heap buffer overflow in ImagingJpegDecode
GHSA-v9pv-5gc8-w2m6criticalpillow@12.3.0Pillow multi-frame loaders can reuse stale native image storage after mode transitions
GHSA-w889-685w-c8fhcriticalpillow@12.3.0Pillow: Argument Injection in Ghostscript call, potentially leading into RCE
GHSA-332p-7hrc-92wfcriticalpillow@10.3.0Pillow: Heap buffer overflow in _tiffWriteProc when saving TIFF to BytesIO
GHSA-5x8w-8jj5-q52hcriticalpillow@10.3.0Pillow: Heap buffer overflow in FlashPix (FPX) JPEG decoding leads to code execution
GHSA-8g5g-8vmr-9782criticalpillow@10.3.0Pillow: Heap buffer overflow in ImagingJpegDecode
GHSA-w889-685w-c8fhcriticalpillow@10.3.0Pillow: Argument Injection in Ghostscript call, potentially leading into RCE
GHSA-4684-h2q9-2vcpcriticalzip@8.6.0ZipStreamReader::extract() and ZipArchive::extract() apply Unix permissions through symlinks without confining the targe…
GHSA-23hp-3jrh-7fpwcriticaltar@6.2.1node-tar: Decompression/parse DoS via unlimited input
GHSA-9v8h-qqgm-4m35criticalbrotli@1.2.0Brotli: Out-of-bounds write in the Brotli decoder ("Node2Shell") also affects the PyPI Brotli package
GHSA-9jj7-4m8r-rfcmcriticalgithub.com/jackc/pgx/v5@5.5.5Memory-safety vulnerability in github.com/jackc/pgx/v5.
GHSA-xgrm-4fwx-7qm8criticalgithub.com/jackc/pgx/v5@5.5.5pgx contains memory-safety vulnerability
GHSA-5cgq-3rg8-m6cvcriticalgolang.org/x/crypto@0.42.0golang.org/x/crypto vulnerable to auth bypass via unenforced @revoked status
GHSA-89gr-r52h-f8rxcriticalgolang.org/x/crypto@0.42.0golang.org/x/crypto: FIDO/U2F security key physical presence check can be bypassed
GHSA-f5wc-c3c7-36mccriticalgolang.org/x/crypto@0.42.0golang.org/x/crypto doesn't drop invoking agent constraints when forwarding keys
Workflows worth a look

By the numbers

Stars31K
Forks2,268
Contributors157
Commits5,987
Open issues684
Open pull requests614
Releases810
Latest releasecua-spaces-v0.16.0
LicenceMIT
Main languageRust
Project age1 year
Last pushOct 26, 2026
Tracked files10,416
Lines of code3.3M
Checkout size348 MB

Lines by language: Rust 1.3M, JSON 455K, Python 448.8K, TypeScript 396.8K, Swift 204.6K, Markdown 174.7K.

Questions

Is Cua free?

The libraries, CLI, Driver, Lume and Cua Bench are MIT-licensed and free. The Cua Spaces app is source-available under FSL-1.1-MIT and free for individuals, with Pro at $18 a month and Teams at $30 per seat a month.

Does Cua send data anywhere?

It sends usage telemetry to PostHog by default, which you can turn off with CUA_TELEMETRY=0 or DO_NOT_TRACK=1. Some features, such as reaching your own machines through the cua.ai relay, use Cua's servers by design. Local sandboxes and VMs run on your hardware.

Which AI agents can use Cua?

Cua Driver connects through MCP, a CLI or typed SDKs, and the docs cover Claude Code, Codex, Cursor and OpenClaw. You bring your own model; Cua provides the computer and the tools.

What do I need to run it?

The cua CLI and Driver run on macOS, Linux and Windows. Lume needs an Apple Silicon Mac, and the Cua Spaces app needs macOS 26 or later, or a Linux or Windows machine for its other builds.


This post is part of GitHub Tools, where every repository is cloned and scanned before it is written up. The scan is a snapshot of one commit on one day; the repository has moved on since, so check it before you install.