Repository navigation
feat(sandbox): make privileged supervisor independent of workload-image code #2750
Description
Problem Statement
The openshell-sandbox binary is supplied by OpenShell, but the privileged supervisor still runs tools from the workload image, including ip, nsenter, nft, and dmesg.
For example, consider an untrusted workload image that contains its own /usr/sbin/ip. During startup, the supervisor runs as root with SYS_ADMIN and NET_ADMIN and executes that path to create the sandbox network namespace. The path is absolute, so a PATH override cannot redirect it—but the file itself still belongs to the untrusted image. It could be a malicious binary or script, and a dynamically linked version also loads its interpreter and libraries from the image.
That code runs before the workload is sandboxed and can act with the supervisor's privileges. Even a non-malicious image can break startup by shipping an incompatible or missing helper.
The same problem exists for nsenter and nft. dmesg is worse because it is still resolved through PATH.
OpenShell should support arbitrary, untrusted workload images without executing any of their code as part of privileged supervisor setup.
Proposed Design
Establish this invariant:
A process retaining supervisor privileges must never execute or dynamically load code from the workload image. Workload entrypoints and SSH shells may execute only after privilege drop and sandbox hardening.
Deliver it in three phases:
-
Remove the immediate workload-image dependency
- Supply all privileged helpers from a trusted OpenShell image/location.
- Replace Podman's workload-image shell health check.
- Replace Kubernetes PVC seeding that currently runs workload-image
shas UID 0. - Add a hostile-image test with fake
ip,nsenter,nft,dmesg, loaders, and libraries.
-
Remove helper processes
- Replace
ipandnsenterwith direct namespace syscalls and route netlink. - Replace
nftwith direct nf_tables netlink operations. - Replace
dmesgbypass monitoring with NFLOG. - Use FD-owned network namespaces so
/run/netnsis no longer required.
- Replace
-
Enforce the boundary
- Keep privileged networking/control separate from workload execution.
- Route entrypoint and SSH execution through a permanently unprivileged process.
- Deny
execve/execveatin the privileged process after startup.
The certified self-contained artifact should be musl-static on Linux amd64 and arm64. Static glibc alone is insufficient because NSS/DNS paths may dynamically load modules.
Definition of Done
- A hostile workload image cannot supply any executable, interpreter, loader, shared library, NSS module, or helper used by the privileged supervisor.
- Docker, rootless Podman, Kubernetes combined/sidecar, and VM guest paths satisfy the same invariant.
- Network namespace and nftables setup no longer spawn external helpers.
- Bypass monitoring no longer uses
dmesgor requiresSYSLOG. - The privileged long-lived process cannot execute new programs after startup.
- Workload entrypoints and SSH shells run only through an unprivileged execution path.
- Hostile-image and cleanup tests cover normal startup, partial failure, shutdown, and crash recovery.
Why This Matters for Workspace Roots
The current OCI workdir guard forbids /bin, /sbin, /usr/bin, /usr/sbin, and library roots partly because the supervisor executes or loads code from them. Once this issue is complete, those paths no longer need to be reserved for supervisor safety. /proc, /sys, /dev, and OpenShell control paths remain protected for separate reasons.
Related Work
- Bug: PATH override can hijack privileged
ipandnsenterhelpers #1113 prevented simplePATHhijacking but did not make helper files independent of the workload image. - refactor: replace iptables with nftables for sandbox and VM networking #1335 migrated rules to nftables but retained privileged CLI execution.
- feat(sandbox): reserve namespaces for supervisor control state #2578 tracks reserved supervisor control namespaces and
/run/netnscleanup. - Proposal: Split Supervisor and Agent into Separate Pods with gVisor Isolation #981 explores supervisor/workload separation on Kubernetes; this issue applies the executable trust boundary across all runtimes.
Agent Investigation
Audited at commit c174ad7f from origin/codex/2526-podman-oci-workdir.
Relevant code:
crates/openshell-supervisor-process/src/netns/mod.rscrates/openshell-supervisor-process/src/bypass_monitor/mod.rscrates/openshell-supervisor-process/src/process.rscrates/openshell-supervisor-process/src/ssh.rscrates/openshell-driver-podman/src/container.rscrates/openshell-driver-kubernetes/src/driver.rscrates/openshell-driver-vm/scripts/openshell-vm-sandbox-init.sh
Activity
github-actions commentedon Aug 29, 2026
This issue has had no activity for 14 days and is now marked stale. It may be closed in 7 days if there is no further activity. Comment or remove the state:stale label to keep it open.