# 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),
}
