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
+2 -1
View File
@@ -19,7 +19,7 @@ ocsb_info() { echo "→ $*"; }
OCSB_SCALARS=(
OCSB_NAME OCSB_WEB_PORT OCSB_EGRESS_PORT OCSB_NETLOCK_GROUP OCSB_SANDBOX OCSB_PANEL
OCSB_NOTIFICATIONS OCSB_TMP OCSB_OPENCODE_BIN OCSB_ENV_FILE OCSB_KUBECONFIG OCSB_PASSWORD_FILE
OCSB_NOTIFICATIONS OCSB_TMP OCSB_DISPLAY OCSB_OPENCODE_BIN OCSB_ENV_FILE OCSB_KUBECONFIG OCSB_PASSWORD_FILE
OCSB_WORKTREES_DIR OCSB_WT_PREFIX OCSB_WT_BASE OCSB_WT_SLUG_REGEX OCSB_DOCKER_GW
OCSB_STATE_DIR OCSB_OPENCODE_CONFIG OCSB_EGRESS_BASE
)
@@ -34,6 +34,7 @@ ocsb_defaults() {
OCSB_PANEL=1 # "Tokens" panel in the web UI (plugins/context-panel)
OCSB_NOTIFICATIONS=1 # desktop notifications through a filtered D-Bus proxy
OCSB_TMP=private # private: own /tmp in the state dir; shared: the host's /tmp
OCSB_DISPLAY=0 # 1: windows on your desktop through the Wayland socket (no X11)
OCSB_OPENCODE_BIN="" # default: `opencode` from PATH
OCSB_ENV_FILE="" # KEY=VALUE file with tokens, exported to OpenCode
OCSB_KUBECONFIG="" # kubeconfig for the agent (~/.kube/config stays hidden)
+15 -2
View File
@@ -177,6 +177,11 @@ ocsb_bwrap_args() {
if [[ -n ${OCSB_DBUS_PROXY_PID:-} && -S $(ocsb_dbus_sock) ]]; then
OCSB_BWRAP+=(--ro-bind "$(ocsb_dbus_sock)" "/run/user/${uid}/bus")
fi
if [[ ${OCSB_DISPLAY} == 1 && -n ${WAYLAND_DISPLAY:-} && -S ${XDG_RUNTIME_DIR:-/run/user/${uid}}/${WAYLAND_DISPLAY} ]]; then
OCSB_BWRAP+=(--ro-bind "${XDG_RUNTIME_DIR:-/run/user/${uid}}/${WAYLAND_DISPLAY}" "/run/user/${uid}/${WAYLAND_DISPLAY}")
# GPU for rendering; without it browsers fall back to software
[[ -d /dev/dri ]] && OCSB_BWRAP+=(--dev-bind /dev/dri /dev/dri)
fi
OCSB_BWRAP+=(--chdir "${OCSB_PROJECT_DIR}")
}
@@ -255,8 +260,16 @@ ocsb_run() {
# No permission prompts in the sandbox: permission rules from all configs form one
# list, the last match wins, and OPENCODE_CONFIG_CONTENT is the last document.
# Denies are repeated after "*" so they still win.
# No display: GUI programs fail fast; browsers must run headless
env+=("DISPLAY=" "WAYLAND_DISPLAY=" "XAUTHORITY=")
# Display: by default none (GUI programs fail fast, browsers run headless). With
# OCSB_DISPLAY=1 only the Wayland socket: unlike X11, a Wayland client cannot read other
# windows or inject input into them. X11 (and the X cookie) stays out either way.
env+=("DISPLAY=" "XAUTHORITY=")
if [[ ${OCSB_DISPLAY} == 1 && -n ${WAYLAND_DISPLAY:-} && -S ${XDG_RUNTIME_DIR:-/run/user/$(id -u)}/${WAYLAND_DISPLAY} ]]; then
env+=("WAYLAND_DISPLAY=${WAYLAND_DISPLAY}" "XDG_RUNTIME_DIR=/run/user/$(id -u)")
else
[[ ${OCSB_DISPLAY} == 1 ]] && ocsb_warn "OCSB_DISPLAY=1 but no Wayland session — no windows in the sandbox"
env+=("WAYLAND_DISPLAY=")
fi
env+=('OPENCODE_CONFIG_CONTENT={"permission":{"bash":{"*":"allow","systemd-run *":"deny","sudo *":"deny"},"external_directory":{"*":"allow"}}}')
echo " sandbox: writable ${OCSB_PROJECT_DIR}, ${OCSB_WORKTREES_DIR}${OCSB_RW[*]:+, ${OCSB_RW[*]}}; the rest of the system is read-only"
fi