Repository navigation
Replies: 1 comment 1 reply
|
@yoobi will ask you start a dicussion here Have folks ask for this but I think I need to hear that our users really care about this. For instance, many users already run in sandboxes so this is sorta a moot point. Doing this right is decent work so we'll hold of on changes here without getting community input |
1 reply
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Problem or use case
Orca launches every agent with its permission-bypass flag by default (
--dangerously-skip-permissions,--dangerously-bypass-approvals-and-sandbox,--yolo). The docs say "the worktree itself is the sandbox" (docs/site/content/docs/model/agents-sessions.mdx), but also: "A worktree is an isolated checkout, not a security sandbox: the agent can still access files and network resources available to its process" (docs/site/content/docs/agents/supported.mdx).So one wrong command from one agent damages the whole machine. Examples:
rm -rf ~,rm -rf /,sudo apt remove …, an edit to~/.sshor~/.bashrc, reading~/.aws, killing other processes. On a headless Orca Server shared by many workspaces, that also takes down every other workspace and the server itself.The vendors of the agents Orca launches all say the same: bypass mode belongs inside an external boundary.
--dangerously-skip-permissionssessions inside a container, a VM, or the sandbox runtime" (https://code.claude.com/docs/en/sandbox-environments).Orca currently provides no such boundary. The experimental Cloud VM recipes come closest, but they run only on the desktop ("Ephemeral VM recipes run on the local desktop host in v1",
src/main/ipc/ephemeral-vm-recipe-context.ts). They need a hand-written sshd image per provider, and no recipe ships with Orca.Summary: I want to tick "Run in an isolated container" when I create a worktree, on Desktop or on Orca Server, so that whatever the agent breaks stays inside that container.
Wording: below, "workspace" means an Orca workspace backed by a git worktree. Each worktree gets its own container, and two worktrees of the same repo never share one.
Proposed solution
0. Start from what already works: orca-docker
A community recipe, orca-docker (https://github.com/talayolabs/orca-docker), already runs one container per Orca worktree with nothing mounted from the host on today's recipe API (
checkoutMode: provisioned-root):It is the best starting point. Compared with this request (checked at commit
5331cdb):-e NAME(name only) forORCA_*,CLAUDE_*,ANTHROPIC_*,GIT_AUTHOR_*…; no project or container-only layer (§4)--cap-drop ALL,no-new-privileges, limits)ORCA_DOCKER_ARGScan add flags)~/.claude(including.credentials.json),~/.claude.jsonand~/.gitconfiginto the container, which Anthropic advises against (§3)Suggested path:
DockerOrcadHostTransportdescribed in §5. It removes the sshd/key/port per container and the desktop-only limit, and brings the checkbox, the default setting, CLI and Orca Server support, and the environment layers.1. User experience
experimentalContainerWorkspaces, off by default), next toexperimentalEphemeralVms(src/shared/default-global-settings.ts,src/renderer/src/components/settings/EphemeralVmsExperimentalSetting.tsx).SettingsSwitchrows inNewWorkspaceComposerAdvancedSection.tsx, or under "Run on".orca worktree create --container[=volume|mounted] [--container-image <ref>] [--container-template small|medium|large]and--no-container. Flags go insrc/cli/specs/core.ts; params extend theWorktreeCreatezod schema insrc/shared/rpc-contract/worktree-create-params.ts. CLI, mobile and Orca Server then all get it (cf. #15587, #20613, #17292).orca.yamlblock (below). Precedence: dialog > repo settings >orca.yaml> global default.--container-env KEY=VALUE/--container-env-file <path>. See §4.2. Two storage modes
volume), recommended defaultmounted)orca-ws-<id>); nothing on the hostrm -rf ~/rm -rf /by the agentdocker rm -f+docker volume rm: everything gonedocker rm -f; the worktree is removed as todaygit pushof the workspace branch (Orca's Source Control runs inside the container)package.jsonscripts can run on your host… Git hooks sit in.git/and don't appear ingit diff" (https://docs.docker.com/ai/sandboxes/security/)3. Security defaults (all from vendor or standards guidance)
--cap-drop ALL,--security-opt no-new-privileges, the default seccomp/AppArmor profile, and never--privileged. Source: OWASP Docker Security Cheat Sheet (https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html), Anthropic secure deployment (https://code.claude.com/docs/en/agent-sdk/secure-deployment).devcontainer.json(runArgs,mounts,privileged,capAdd). These keys are repo-controlled, andinitializeCommandruns on the host (https://containers.dev/implementors/json_reference/). Ignore them or allowlist them.--memory(=--memory-swap),--cpus,--pids-limit,--init, and labelsorca.workspace=<id>so orphans can be swept at startup.~/.claude,~/.codex,~/.ssh,~/.awsor~/.config. Anthropic warns that dev containers "do not prevent a malicious project from exfiltrating anything accessible inside the container, including the Claude Code credentials" (https://code.claude.com/docs/en/devcontainer).bridgeby default, withnoneavailable. Published ports bind to127.0.0.1.init-firewall.sh. Enforce it outside the container soNET_ADMINisn't needed inside, and note that every vendor admits domain allowlists can be bypassed..gitso git works. A linked worktree's.gitis a file pointing to<repo>/.git/worktrees/<name>, andconfigandhooksare read from the common dir (https://git-scm.com/docs/gitrepository-layout)..git/hooksand.git/configread-only; Codex and Anthropic's sandbox-runtime protect the same paths (https://learn.chatgpt.com/docs/agent-approvals-security)..husky/and so on) never run on the host.--runtime runsc(gVisor, https://gvisor.dev/docs/) or Kata on Linux servers. On macOS, Applecontainerruns one lightweight VM per container (https://github.com/apple/container). Prefer rootless Docker/Podman on Linux servers (https://docs.docker.com/engine/security/rootless/).4. Environment variables: forward the project's, add container-only ones
A container does not inherit the host's environment. A
docker execprocess sees only what was set when the container was created, plus what-e/--env-filepasses to that one process (https://docs.docker.com/reference/cli/docker/container/exec/). Orca therefore has to forward variables explicitly. Proposed layers, lowest precedence first:ENV, or devcontainercontainerEnvORCA_*(terminal handle, worktree id, agent hook port/token…)addOrcaWslInteropEnv(src/main/pty/wsl-orca-env.ts, called fromsrc/main/daemon/pty-subprocess/shell-launch-plan.ts), with path-valued entries translatedagentDefaultEnv(Settings → Agents;src/shared/global-settings-types.ts, resolved insrc/shared/agent-startup-plan-inputs.ts)agent.envinorca.yaml+ repo settings); per-projectghaccount, where Orca mints a short-lived token and "injects it into that child env only" (Repo.ghAccount,src/main/git/command-runner/gh-bound-account-env.ts)GH_TOKEN.env,.env.local, Androidlocal.properties…).worktreeincludealready copies the listed gitignored files into new worktrees (src/main/git/worktree-include-file.ts)git clonedoesn't bring them, so Orca copies the.worktreeincludefiles from the host project into the volume after cloning (opt-in,copyIgnoredFiles, listed in the dialog)nativeChatShellEnvironment(src/shared/native-chat-shell-environment.ts)forwardHostEnv). Never inherit everything, because the host env often holds cloud credentialsSecretStore,src/shared/secret-store.ts, keychain-sealed)Container-only variables exist only inside that container, never on the host:
worktree.container.envinorca.yamlfor non-secret values (committed). The same field in repo settings holds local or secret values (not committed), using the shared/local splitcommandSourcePolicyalready uses for scripts.--container-env KEY=VALUE(repeatable) and--container-env-file <path>.docker exec, so a change applies to every new terminal or agent immediately, and running ones keep their old env (the UI should say so). Variables needed at container start (for the entrypoint) form a separate "requires recreate" list.Rules:
ORCA_*and the Orca-owned keys [Feature]: Per-account environment variables (e.g. proxy) for managed Claude/Codex accounts #25873 already lists (CLAUDE_CONFIG_DIR,CODEX_HOME,ANTHROPIC_API_KEY, …) are rejected with a clear message.-e NAME=valueis visible in the host'sps, and values given todocker run -eare stored in the container config and shown bydocker inspect. Usedocker exec -e NAME(the value comes from the launching process's own environment, see https://docs.docker.com/reference/cli/docker/container/run/), or--env-filefrom a 0600 temp file deleted right after. PR Add Project from a Devcontainer (docker exec, GUI source) #6426 already buildsdocker execarguments with-e NAMEonly.SecretStore: never inorca.yaml,WorktreeMeta, logs ordocker run -e, and masked in the UI.printenv). Only proxy injection keeps a value away from the model ([Feature]: Project-scoped secret store, injected into agent processes without putting the value in front of the model #24182; Docker Sandboxes' credential proxy, https://docs.docker.com/ai/sandboxes/security/).OrcadHostTransport.orcadLaunchEnv("host facts only the client can read, passed to orcad at launch",src/main/ssh/orcad-host-transport.ts). Per-terminal values need a field on the terminal create request if it doesn't carry one yet.5. Implementation: Orca already has the seam
Container only (volume) = a new orcad host transport.
OrcadHostTransport(src/main/ssh/orcad-host-transport.ts, built onRemoteInstallTransportinsrc/main/ssh/remote-install-transport.ts).deployOrcad(src/main/ssh/orcad-remote-deploy.ts) accepts any transport.createWslOrcadHostTransport(src/main/wsl/wsl-orcad-host-transport.ts) runswsl.exe --exec sh -c, andsrc/main/wsl/wsl-orcad-deploy.tsreuses the SSH install/activation.src/main/ssh/orcad-stdio-bridge-provider.ts).DockerOrcadHostTransport(docker|podman exec -i <container> sh -c …), modelled on the WSL one.dockertarget toOrcadHostTargetand a docker variant toOrcadDeploymentLinkSchema(src/shared/runtime-environments.ts, ssh|wsl today).docker volume create→docker run -d(flags from §3, volume at/workspace) →deployOrcad→ register as a runtime environment →repo.cloneinto/workspace(src/main/runtime/rpc/methods/repo.ts) → create the worktree on that runtime.src/main/orcad/orcad-managed-agent-hooks.ts), so the container never needs to reach the host.src/renderer/src/lib/ephemeral-vm-worktree-creation.ts). It should live in main so the CLI, mobile and a headless Orca Server can trigger it.src/main/runtime/rpc/methods/ssh.ts).Shared folder (mounted) = a spawn wrapper.
docker exec -it -w <path> -e … <container>inside the local PTY launch plan, where WSL is already special-cased (src/main/providers/local-pty-launch-plan.ts). Alternatively, rebase PR Add Project from a Devcontainer (docker exec, GUI source) #6426'sDockerPtyProvider.127.0.0.1only (ORCA_AGENT_HOOK_PORT/ORCA_AGENT_HOOK_TOKEN/ORCA_AGENT_HOOK_ENDPOINT). Either relay it likesrc/main/agent-hooks/wsl-hook-relay-manager.ts, or pass it through--add-host host.docker.internal:host-gatewaywith-evariables.Shared by both modes:
container: { engine, id, mode, image, volume? }inWorktreeMeta(src/shared/worktree/meta-types.ts), or in a side store likeorca-ephemeral-vm-runtimes.json(src/shared/ephemeral-vm-runtime-store.ts) so orphan sweeps survive metadata garbage collection.executeWorktreeRemoval(src/main/ipc/worktrees/removal/execute-worktree-removal.ts) andremoveManagedWorktree(src/main/runtime/workspaces/workspace-removal.ts). Add a startup sweep oflabel=orca.workspacecontainers whose workspace no longer exists.docker-command-runner.ts(execFile, contexts,DOCKER_HOST=ssh://).orca.yamlimage, ordevcontainer.json(with the restrictions in §3), or an Orca base image containingsh,tarandgit. orcad brings its own Node (src/main/ssh/orcad-remote-node-runtime.ts).6. Suggested PR slices
experimentalContainerWorkspaces, the global default, theworktree.containeryaml parser with tests,WorktreeCreate.container, and docker/podman detection.DockerOrcadHostTransport+ "Attach to an existing container" as a host, like WSL hosts. This is testable on its own.--container, cleanup on delete, and the orphan sweep.--container-env/--container-env-file), name-only-einjection, and the "Effective environment" view;.worktreeincludefiles into the volume..git/hooks/config, hook relay, and git actions inside the container.none/allowlist.7. Tests
src/main/wsl/wsl-orcad-host-transport.test.ts,wsl-orcad-deploy.test.ts.src/main/ssh/ssh-hostile-hosts.docker.test.ts.tests/e2e/wsl-host-fake-transport.spec.ts(ORCA_E2E_FAKE_WSL_HOSTS→ORCA_E2E_FAKE_CONTAINER_HOSTS).config/docker/, usingheadless-pairingas the template.rm -rf "$HOME" /tmp/*(or similar) as the agent user inside a container workspace, then assert that the host home directory and the other workspaces are intact and the workspace can be recreated.ORCA_*and other reserved keys;dockerargv contains variable names only, anddocker inspectshows no injected values;.worktreeincludefiles land in the volume in container-only mode.8. Open questions for maintainers
Alternatives or additional context
Workarounds today, and why they fall short:
Cloud VM recipes with a local Docker image (
skill-guides/orca-per-workspace-env/references/docker-ssh.md): desktop only, an sshd plus key plus port per container, no built-in recipe, and not available from the CLI or mobile.orca-docker (https://github.com/talayolabs/orca-docker), a community
provisioned-rootrecipe and the closest thing to this request today:known_hostsoverdocker exec;docker stop/start, and destroy removes the container and its key.It proves the volume mode works with today's API. It also shows what core support would remove: the sshd, key and published port per container, the desktop-only limit ("Recipes run on the local Docker daemon"), and copying a recipe script into every repo. See §0 for a full comparison.
Docker Sandboxes as an SSH target ([Feature]: Support for Docker Sandboxes to Run Agents #13665, docs PR docs(ssh): document connecting to a Docker Sandbox #25892) and the
orca-sbx-recipesplugin: microVM isolation, but one VM per project shared by every worktree. They need sbx and a Docker account, and are driven from the desktop.Agent-level sandboxes (Claude Code sandbox, Codex
workspace-write): configured per CLI, and they only cover some tools. The flag Orca launches Codex with by default turns Codex's sandbox off.Running the whole
orca servein one container or VM: protects the host, but workspaces can still destroy each other.Related issues and PRs:
docker exec,DockerPtyProvider)MachineProvidercontract and cites therm -rfblast radius.worktreeinclude(src/main/git/worktree-include-file.ts), the existing way to carry.envfiles into new worktreesPrior art:
I'm happy to test preview builds against a headless Orca Server setup.
All reactions