All documentation

Security model

What stops web pages, other accounts, and other programs from using OpenOrc's access, and what it cannot protect against.

What this covers

OpenOrc runs coding agents with your account's access to your computer. This page covers who else could try to use that access, and what stops them:

  • Agents do what the thread's mode allows. The rules are on Modes and permissions.
  • Web pages, in your browser or in the Preview, can't reach OpenOrc's local servers or the app's own interface.
  • Other accounts on the same computer can't read the secret addresses OpenOrc gives agents.
  • Other devices on your network can't use OpenOrc. Only phones you paired can connect, and only while you allow them.
  • A cloud thread's sandbox holds only that thread's work, and its agent's sign-in stays outside it where your Vercel plan allows. See Cloud sandboxes and the brain.
  • Other programs running as you can't start OpenOrc in a way that runs their code inside the app or drives its window, and release builds have no test switch that makes it start agents or approve requests on its own.

A program that already runs as you can read and change your files, including OpenOrc's, and can choose the environment OpenOrc starts with. What OpenOrc cannot protect against lists what follows from that.

Local servers

Agents reach OpenOrc's tools through its MCP server. It listens on 127.0.0.1 on a random port, so other computers can't connect to it. Each agent process gets its own address:

http://127.0.0.1:<port>/mcp/<random UUID without dashes>
  • The address is the only credential, and it belongs to one run. A call through it acts for that run and follows that run's mode.
  • It works only while the run is live. When the run ends, OpenOrc forgets it, so a copy left in a file or a log no longer works.
  • A request with an Origin header, or one that names any host other than 127.0.0.1:<port>, is refused. Agent CLIs send neither. A page that points its own domain at your computer sends that domain as the host, scripts on a page send an Origin header, and no page can guess the random path.
  • The address never appears on a command line. Claude Code reads it from a file only you can read, deleted when its process closes. Codex and OpenCode receive it over the process's standard input.

The same address checks Claude Code's file edits in Plan and Accept edits. Before each edit, a hook sends Claude's request to <address>/file-boundary with curl, and OpenOrc answers from the real path, following symlinks. Plan allows writing only in Claude's plans folder; Accept edits asks you about anything outside the project. If OpenOrc doesn't answer, the edit is blocked.

The other local servers have their own checks:

  • The MCP Apps sandbox has a port of its own, so apps run apart from the app window. It serves each app at its own random path, in a sandboxed frame, and answers only GET requests that name its own address as the host.
  • The Slack shared relay accepts only POST requests with a device key, and refuses any request with an Origin header. It keeps only a hash of each key.
  • The reviewer app's setup page runs only while you set the app up, for at most 15 minutes. It answers only requests that carry a random value from the link OpenOrc opened, and its form can post only to github.com.
  • On macOS, while a downloaded update waits to install, the update library serves it to the system installer behind a random password.
  • While device support is on, expo-device-hub listens on 127.0.0.1 and answers only requests that carry a random token, which only OpenOrc's core holds. agent-device's helper also needs its own token.

Phones

While Allow paired phones is on, OpenOrc listens for phones on your network, on port 47820 or a free port when that one is taken. It is the only server that accepts connections from other devices, and it checks each one in layers:

  • A connection that doesn't come from this computer, a private or link-local address, or a Tailscale address is dropped before anything is read.
  • Each connection is encrypted with the Noise protocol (IK, X25519, AES-GCM). The pairing code carries this computer's public key and a one-time secret that expires after five minutes. A phone that pairs keeps its own key pair, and afterwards only a paired phone's key completes the handshake.
  • A phone can call only the actions the phone app needs: reading projects, threads, and their work, sending messages, answering approvals, starting and organizing threads, committing, pushing, and opening pull requests, and driving the thread's Preview. It can't change settings, delete threads, read files outside a thread's changes, or open a terminal. It sees your Claude accounts' names, never their email addresses.
  • Removing a phone in Settings deletes this computer's record of its key, so it can't connect again without pairing.

Source: packages/mcp/src/index.ts, packages/agents/src/claude/file-boundary.ts, apps/desktop/src/main/mcp-app-sandbox.ts, packages/core/src/services/reviewer-app.ts, packages/core/src/remote/, packages/link/, packages/core/src/devices/hub.ts

The app window and the Preview

The interface runs in a sandboxed Chromium page with context isolation and no Node.js. It reaches the rest of OpenOrc only through a fixed set of functions and one channel to the core, where every request is checked against a schema.

  • The window loads only the files that ship with OpenOrc and never navigates away from them. Embedded <webview> tags are refused.
  • A web link opens in the Preview or in your browser, or in Chrome Incognito if you choose that from the link's menu. Files and other schemes don't open, and only the app's own page can ask to open a link.
  • The app's page may show notifications and copy text to the clipboard. Every other web permission, such as the camera, microphone, or location, is refused.
  • Visualizations that agents draw, and MCP Apps, run in sandboxed frames with an opaque origin, each in a process of its own. They can't reach the network, except an MCP App's connections to the https domains its server declares.

The Preview is a separate sandboxed page with a session of its own. It is refused every web permission, can't download files or open windows, and loads only http and https addresses without a user name or password in them. Its session keeps your sign-ins across restarts, so an agent's clicks and typing in it follow the thread's mode: blocked in Plan, and asked about unless the thread is Autonomous. Typing into a password field asks even in Autonomous. Opening pages, reading them, and taking screenshots are allowed in every mode, Plan included, in that same signed-in session.

Source: apps/desktop/src/main/index.ts, app-origin.ts, link-navigation.ts, browser-pane.ts, packages/core/src/services/app-actions.ts

What agents can do through OpenOrc

OpenOrc's own tools let an agent reach beyond its thread. Each follows the calling thread's mode:

  • Messaging another thread. A message to a thread in the same or a stricter mode is delivered at once. One to a more permissive thread asks you first, and from Plan an agent can message only Plan threads. After 50 agent messages in a row with nobody writing, sending stops until a person writes.
  • Starting a thread. An agent in Act can start a thread with thread_start without asking. The new thread works in the same folder, with the same mode and permissions. An agent can start one only while fewer than 3 of the threads it started are working, and a started thread can't start its own.
  • Subagents. An agent's own subagents follow that agent's permission rules, not OpenOrc's modes. Claude Code may run them only in Autonomous, and Codex none in Plan.
  • Devices. With device support on and Agents can use devices on, an agent may open, close, and drive your simulators and emulators in every mode except Plan.
  • Orclings can read every project, save tasks, and message any thread. Starting work in a project asks first unless the Orcling works in Autonomous, and is blocked in Plan.
  • Reviewing a pull request. The review runs in a copy of the pull request, and no agent loads settings, hooks, or MCP servers from that copy. Agents only add comments to your draft; you decide what to post.

The reviewer app asks GitHub only for write access to pull requests and has no active webhook, and OpenOrc uses it only to post reviews. Each access token covers one repository for one hour, and approving is off until you turn on Let it approve.

The installed app

Electron has switches that let another program run code as the app, which macOS then attributes to the app, with the access you gave it. OpenOrc turns them off with Electron's fuses, flags written into the app when it is built:

RunAsNode                              off
EnableNodeOptionsEnvironmentVariable   off
EnableNodeCliInspectArguments          off
EnableCookieEncryption                 on
EnableEmbeddedAsarIntegrityValidation  on
OnlyLoadAppFromAsar                    on
  • The app can't be started as plain Node.js, and ignores NODE_OPTIONS and --inspect.
  • It loads its code only from its app.asar archive. On macOS and Windows, Electron checks the archive's integrity before loading it. Linux has no such check: the rpm and deb install the archive where only root can change it, and an AppImage is as protected as the file you keep it in.
  • Cookies, including the Preview's sign-ins, are encrypted on disk with a key kept in the macOS Keychain or protected by Windows DPAPI. On Linux the key lives in the Secret Service or KWallet; without either, Chromium's fallback key only obscures them.
  • An installed app refuses to start with --remote-debugging-port or --remote-debugging-pipe, before it opens a window.
  • Release builds leave out every test hook: nothing that starts agents, approves requests, runs benchmarks, takes screenshots, or answers the folder picker, and no diagnostics screen.

On macOS the release runs with the hardened runtime and one entitlement, com.apple.security.cs.allow-jit, which JavaScript needs. Library validation stays on, so the app loads only native code signed by Apple or by the same developer.

Before a release is published, a check runs on the signed macOS app, the installed Windows app, and the installed Linux app. It reads the fuses, looks for native code inside the archive and, on macOS, for any executable not signed by the same Apple developer account, then starts the app and confirms that ELECTRON_RUN_AS_NODE, --inspect, and --remote-debugging-port do nothing.

Source: apps/desktop/electron-builder.yml, apps/desktop/build/entitlements.mac.plist, scripts/desktop-release.cjs, scripts/packaged-release-check.cjs

Cloud sandboxes and the brain

A cloud thread runs its agent on a machine of its own on your Vercel or Agent37 account. No two threads share a sandbox. The thread's mode still decides what the agent may do, but its commands run on that machine, not on your computer, and they can reach the internet without limit. Your computer reaches a sandbox only through the service, with your Vercel token, or with your Agent37 key at OpenOrc's own server in the instance. The agent reaches OpenOrc's tools through the same connection, as its own run.

Sign-ins in a sandbox

  • On Vercel, when your plan allows it, the sandbox's firewall adds the agent's sign-in to its requests on the way out. The sandbox holds a stand-in that says openorc-sign-in-kept-outside-this-sandbox and works nowhere, so nothing running there can read or take the real one.
  • Otherwise the sandbox holds the sign-in, and the agent and any command it runs can read it. That is always the case on Agent37. A turn gets only the sign-in it needs: its Claude account's token, the Codex login, or the key of its model's provider.
  • Your Claude Code login and a ChatGPT sign-in are never copied to the cloud. Each agent gets a sign-in made for the cloud instead. To offer copies of an OpenAI API key or OpenCode provider keys, OpenOrc reads Codex'sauth.json and the credentials OpenCode keeps, and saves a copy only after you approve it.

Your cloud account

  • A Vercel token can do everything its scope allows. Settings → Cloud asks for one scoped to one team and says when a token reaches more. The token stays in protected storage on your computer. A cloud brain on Vercel gets it in memory when it starts, never on its disk, and the brain's door keeps a copy in a sensitive environment variable so it can wake the brain.
  • The cloud brain seals its secrets under its own key, with AES-256-GCM. Your GitHub sign-in reaches it only if you switch it on, and then only its own git and gh get it. No agent and no sandbox does.
  • Phones reach the brain over the same end-to-end encrypted link they use with your computer, and only phones paired with the brain complete the handshake. When you remove a phone from the brain, the door on Vercel refuses that phone too.

Source: packages/core/src/services/cloud-agents.ts, cloud-agent-env.ts, cloud-codex.ts, cloud-opencode.ts, mac-agent-keys.ts, packages/cloud/src/vercel-sandbox.ts, brain/sealed-file.ts, brain/wire.ts, apps/brain/src/github.ts

Secrets and your data

  • Slack tokens, the optional Anthropic API key for memory, the reviewer app's private key, this computer's key for phone connections, the Apple push key, and the cloud connections and sign-ins are encrypted with your system's protected storage and written to files only you can read. They are never in the database. See Data and storage.
  • Each CLI keeps its own credentials, and OpenOrc doesn't store them. The only agent sign-ins OpenOrc keeps are the ones for the cloud.
  • Text that looks like a secret is replaced before it is stored. See Redaction.
  • The database is a plain SQLite file in your data folder, and it isn't encrypted. Your threads, plans, and memories are as private as the rest of your files.
  • Your messages reach every agent over standard input. So do background requests, such as titles and memory summaries.

Claude Code's brief is on its command line

OpenOrc gives Claude Code its brief for a thread with --append-system-prompt, and other accounts on the computer can list a process's command line. The brief can include the thread's title, the project's folder and branch, task titles and a task's description, the project's memory brief, an Orcling's instructions and its memories about you, and, after a switch of agent or a compaction, your last few requests and the previous agent's last reply. Codex and OpenCode receive the same brief over standard input.

What OpenOrc cannot protect against

  • Programs that run as you. They can read and change OpenOrc's database and logs, for example to add a schedule that starts an agent. They can read the files that hold running agents' addresses and call those addresses while the runs last. On macOS, the Keychain asks before another program reads the key that protects OpenOrc's secrets; on Windows and Linux, a program running as you can decrypt them.
  • Your shell's startup files. To find the agents, OpenOrc runs your login shell and keeps only its PATH and where each agent lives. Terminal panels run your shell, so its startup files run there. A program that changes those files changes what runs.
  • The environment OpenOrc starts with. At startup OpenOrc removes the variables that make shells, Node, Git, or the system loader run extra code: NODE_OPTIONS, BASH_ENV, ENV, ZDOTDIR, PROMPT_COMMAND, LD_PRELOAD, LD_AUDIT, LD_LIBRARY_PATH, and every variable starting with DYLD_ or GIT_. Others, such as proxy settings and extra PATH entries, still reach terminals and agents. OPENORC_USER_DATA picks the data folder in every build. OPENORC_CLAUDE_BIN and its siblings pick the agent programs on Windows, and on macOS and Linux when OpenOrc can't read your login shell.
  • Access you grant on macOS. Agents and terminals that OpenOrc starts share the privacy access you give OpenOrc, such as Documents, Desktop, or Full Disk Access. The fuses stop other programs from running code inside OpenOrc; they don't stop a request that asks an agent to use that access.
  • What agents are allowed to do. In Autonomous, an agent's commands run without asking, with your account's access. Choose the mode for the work.
  • Whoever controls your cloud account. Vercel or Agent37, and anyone with your token or key, can read what a sandbox or the cloud brain holds, including your code and any sign-in held inside. A sign-in removed in OpenOrc keeps working until you revoke it with its provider.

Reporting a vulnerability

Report suspected vulnerabilities privately through GitHub. On the repository page, open the Security and quality tab and click Report a vulnerability. Don't post details in a public issue. SECURITY.md lists what to include. OpenOrc is in beta, and fixes go to the current development branch.

Next steps

Checked against OpenOrc's source on November 9, 2026.