OCSB_DISPLAY: agent windows on the desktop through the Wayland socket

Off by default. With OCSB_DISPLAY=1 the sandbox gets only the Wayland socket and /dev/dri: the agent's windows (e.g. a Playwright browser) appear on the desktop, but a Wayland client cannot read other windows or inject input into them. X11 and the X cookie are never passed in.
This commit is contained in:
2026-10-30 01:14:56 -07:00
parent 6dec88641a
commit 5a7567849e
5 changed files with 36 additions and 12 deletions
+9 -4
View File
@@ -124,6 +124,7 @@ files are read, so you can use it in values. Relative paths are relative to the
| `OCSB_PLUGINS` | skill-compact-resurrect | plugin files from `plugins/` (or absolute paths) |
| `OCSB_PANEL` | `1` | "Tokens" panel in the web UI |
| `OCSB_NOTIFICATIONS` | `1` | desktop notifications through a filtered D-Bus proxy |
| `OCSB_DISPLAY` | `0` | `1`: the agent's windows (e.g. a Playwright browser) on your desktop through the Wayland socket |
| `OCSB_TMP` | `private` | `private`: the agent's own `/tmp` in the state directory; `shared`: the host's `/tmp` |
| `OCSB_SANDBOX` | `1` | `0` = filter and netlock only, no bubblewrap |
| `OCSB_WORKTREES_DIR` | `../<project>-worktrees` | where worktrees go |
@@ -243,9 +244,11 @@ Inside the sandbox:
- **Session bus:** replaced by `xdg-dbus-proxy` that talks only to
`org.freedesktop.Notifications`; the real bus would let the agent start processes outside
the sandbox with `systemd-run --user`.
- **No display:** `DISPLAY`, `WAYLAND_DISPLAY` and `XAUTHORITY` are empty and the X cookie is
hidden, so GUI programs cannot reach your desktop; run browsers (Playwright MCP, Chrome)
headless. `xdg-open` is disabled; the UI is opened by `run` from your normal session.
- **Display:** by default none — `DISPLAY`, `WAYLAND_DISPLAY` and `XAUTHORITY` are empty and the
X cookie is hidden; run browsers headless. With `OCSB_DISPLAY=1` the agent gets only the
Wayland socket (and `/dev/dri` for the GPU): its windows appear on your desktop, but unlike
X11 a Wayland client cannot read other windows or inject input into them. X11 is never
passed in. `xdg-open` is disabled; the UI is opened by `run` from your normal session.
- **No silent fallback:** with `OCSB_SANDBOX=1` and no working bubblewrap, `run` refuses to
start.
@@ -267,6 +270,8 @@ place, requests to production — not to hold a determined attacker.
- **The project is writable.** Mistakes inside it are real; cc-safety-net blocks the common
destructive commands, git keeps history — commit often.
- With `OCSB_TMP=shared` the host's `/tmp` and its sockets are reachable.
- With `OCSB_DISPLAY=1` the agent can open windows on your desktop and use the clipboard while
its window is focused.
## Troubleshooting
@@ -281,7 +286,7 @@ place, requests to production — not to hold a determined attacker.
| `bubblewrap cannot create a sandbox` | unprivileged user namespaces are disabled (`kernel.unprivileged_userns_clone`, AppArmor userns restrictions) |
| no "Tokens" panel | open port 4196, not 4197; see `<state>/data/opencode/log/context-panel.log` |
| no notifications | install `xdg-dbus-proxy` |
| browser tools fail (`Missing X server`, `Failed to connect to Wayland display`) | no display in the sandbox: run the browser headless (Playwright MCP: `--headless`) |
| browser tools fail (`Missing X server`, `Failed to connect to Wayland display`) | no display in the sandbox: set `OCSB_DISPLAY=1` (Wayland session) or run the browser headless (Playwright MCP: `--headless`) |
| can't find a file the agent put in `/tmp` | it is in `~/.local/share/opencode-sandbox/<name>/tmp` |
| `docker build` fails pulling images | the proxy reaches registries through squid: check `egress logs` |