Files
codex-app-server/deploy/apparmor/codex-host
T
host 5d09af855f Host-level sandbox tasks: LocalExecutor + bwrap workspace-write
Docker outer layer and bwrap inner layer are mutually exclusive
on this host (fresh proc mounts fail with kernel EPERM inside
Docker's nested pidns, but work on the host under a userns
profile). So tasks that need an inner sandbox run on the host:
- Worker --claim-executor-only: strict executor claim (only
  executor == own type, never NULL). The host worker MUST use
  it, or it would steal NULL-executor tasks meant for Docker
  workers (those tasks would lose the Docker outer layer).
  Default behavior unchanged (NULL claimable by any worker).
- host-config-host.json: sandbox workspace-write, state
  work/host-state-host.json (distinct from Docker tasks'
  host-state.json), same relay home and test repo as Docker.
- deploy/apparmor/codex-host: docker-codex base + userns,
  mount, pivot_root for bwrap; still denies raw network,
  ptrace, dangerous capabilities, /proc/sys writes.
- deploy/host-worker/codex-host-worker.service: aa-exec -p
  codex-host, --executor local --claim-executor-only,
  capacity 2, proxy env 127.0.0.1:8888 so host tasks' relay/git
  egress also goes through the Tinyproxy allowlist (host direct
  egress would bypass it).
POST /tasks already accepts executor (local/docker/cloud), so
no API change was needed for routing.
Tests: 4 host-sandbox-routing tests (strict claim incl. CAS,
default still takes NULL, config sandbox/state, profile
allows bwrap without deny mount). Full suites pass.
2026-10-26 08:23:37 +08:00

86 lines
2.7 KiB
Plaintext

# AppArmor profile for the HOST-LEVEL sandbox worker (codex-host-worker).
#
# This is docker-codex (outer hardening) PLUS what bwrap needs:
# - userns: allow creating user namespaces (bwrap's inner sandbox)
# - mount, umount, pivot_root: allow (bwrap mounts proc/tmpfs/binds
# and pivot_roots into the new root)
# It KEEPS docker-codex's denies: raw network, ptrace, dangerous
# capabilities, writes to /proc/sys, /sys, /proc/keys.
#
# Why a separate profile: docker-codex deliberately denies mount
# (containers must never mount; inner sandbox stays off there by
# choice). The host worker NEEDS mount+userns because its tasks
# run codex workspace-write (bwrap) directly on the host. The two
# profiles must not be confused: a task container under codex-host
# could bwrap (defeats the Docker-only design), and a host worker
# under docker-codex cannot bwrap at all (mount denied).
#
# Security note (honest): allowing mount+userns for the host worker
# means the WORKER process (trusted, codexsvc) can mount. The AGENT
# inside a task cannot mount on the host: its mounts happen inside
# bwrap's new mount namespace (isolated), and bwrap's pid namespace
# hides other tasks' processes. The agent's writable surface is its
# own worktree (+ a private tmpfs /tmp that never reaches host /tmp).
#
# Install: cp to /etc/apparmor.d/codex-host, then
# apparmor_parser -r /etc/apparmor.d/codex-host
# Use: aa-exec -p codex-host -- python3 -m cloud.worker ...
# (see deploy/host-worker/codex-host-worker.service)
# Verify: cat /proc/<worker-pid>/attr/current shows
# "codex-host (enforce)".
#include <tunables/global>
profile codex-host flags=(attach_disconnected,mediate_deleted) {
#include <abstractions/base>
network inet stream,
network inet dgram,
network inet6 stream,
network inet6 dgram,
deny network raw,
capability chown,
capability dac_override,
capability fsetid,
capability fowner,
capability mknod,
capability net_bind_service,
capability setfcap,
capability setgid,
capability setpcap,
capability setuid,
capability sys_chroot,
deny capability sys_admin,
deny capability sys_ptrace,
deny capability net_admin,
deny capability net_raw,
deny capability sys_module,
deny capability sys_rawio,
deny capability sys_boot,
deny capability sys_time,
deny capability mac_admin,
deny capability mac_override,
# bwrap needs these (docker-codex denies them).
userns,
mount,
umount,
pivot_root,
deny ptrace,
file,
deny @{PROC}/sys/** w,
deny @{PROC}/sysrq-trigger rw,
deny @{PROC}/keys/** rw,
deny @{PROC}/kcore rw,
deny /sys/** w,
deny /etc/shadow rw,
deny /etc/gshadow rw,
signal,
unix,
dbus,
ptrace (readby),
}