Plattformübergreifende Sandbox (sandbox)
codex isoliert die Befehlsausführung in eine plattformspezifische native Sandbox: macOS nutzt sandbox-exec (seatbelt), Linux bubblewrap + seccomp, Windows restricted token. Der sandboxing-Crate abstrahiert einheitlich; linux-sandbox/, bwrap/, windows-sandbox-rs/, process-hardening/ sind die Plattformimplementierungen. core berechnet vor jedem exec den SandboxType und übergibt ihn an SandboxManager::transform, das das tatsächlich zu spawnende argv zusammenstellt.
Verantwortlichkeiten
- Nach
PermissionProfileentscheiden, ob Sandbox aktiviert wird und welcher Backend-Typ:codex-rs/sandboxing/src/manager.rs:273-319 - Auf macOS seatbelt-Policy und argv für
sandbox-execzusammenstellen:codex-rs/sandboxing/src/seatbelt.rs:21-30 - Auf Linux den
codex-linux-sandbox-Helper aufrufen: erst no_new_privs + seccomp, dann bubblewrap exec:codex-rs/linux-sandbox/src/lib.rs:1-30 - Auf Windows per restricted token / elevated backend Dateisystem und Netzwerk isolieren:
codex-rs/windows-sandbox-rs/src/lib.rs:13-50 - Vor main prozessweite Hardening vornehmen (core dumps aus, ptrace verweigern,
LD_PRELOAD/DYLD_*entfernen):codex-rs/process-hardening/src/lib.rs:12-25
Entwurfsbeweggründe
Warum nicht einfach den Block von execpolicy vertrauen? Weil das Modell beliebige Shell konstruieren kann und eine Regelengine immer Randfälle hat. Jeden Befehl in die OS-native Sandbox zu zwingen, ist der Rückfall „selbst wenn das Modell ausbricht, hält der Kernel". SandboxablePreference::Auto lässt policy-basierte Profile wie workspace-write / read-only die Sandbox aktivieren; das full-access-Profil fällt direkt auf SandboxType::None zurück, um unnötige Prozessverpackung zu vermeiden.
Die Backends unterscheiden sich pro Plattform, weil es keinen plattformübergreifend einheitlichen Sandbox-Primitiv gibt: macOS' seatbelt ist eine deklarative .sbpl, Linux' bubblewrap basiert auf user namespace + bind mount, Windows' restricted token auf token + ACL. Die SandboxType-Enum vereinheitlicht diese drei Backends plus None in einem einzigen Label; core/exec-server sehen nur das Label, nicht die Plattformdetails.
Wichtige Dateien
codex-rs/sandboxing/src/lib.rs:1-46— Moduleinstieg; nachtarget_osausgewählter Backend zur Kompilierzeit.codex-rs/sandboxing/src/manager.rs:35-75—SandboxType-Enum undget_platform_sandbox.codex-rs/sandboxing/src/manager.rs:273-329—SandboxManagermitselect_initial/should_sandbox.codex-rs/sandboxing/src/manager.rs:321-413—transformformt das rohe argv je Sandbox-Typ in ein argv mit Wrapper um.codex-rs/sandboxing/src/seatbelt.rs:21-30— macOS:sandbox-exec-Pfad ist hart auf/usr/bin/sandbox-execgesetzt; schützt vor PATH-Injektion.codex-rs/linux-sandbox/src/launcher.rs:36-67— Linux bubblewrap launcher: bevorzugt System-bwrap, Fallback auf bundled.codex-rs/process-hardening/src/lib.rs:43-61— Linux-Prozess-Hardening:prctl(PR_SET_DUMPABLE, 0)+LD_*entfernen.codex-rs/core/src/exec.rs:117-130— Einstieg auf core-Seite beim Aufruf vonselect_initial.
SandboxType vereinheitlicht die drei Plattform-Backends und „keine Sandbox" in einem Label; core sieht nur das Label.
pub enum SandboxType {
None,
MacosSeatbelt,
LinuxSeccomp,
WindowsRestrictedToken,
}In select_initial entscheidet erst should_sandbox, ob überhaupt eine Sandbox aktiv sein soll; dann wird die Plattform nach dem Backend gefragt:
pub fn select_initial(
&self,
file_system_policy: &FileSystemSandboxPolicy,
network_policy: NetworkSandboxPolicy,
pref: SandboxablePreference,
windows_sandbox_level: WindowsSandboxLevel,
has_managed_network_requirements: bool,
) -> SandboxType {
if self.should_sandbox(
file_system_policy,
network_policy,
pref,
has_managed_network_requirements,
) {
get_platform_sandbox(windows_sandbox_level != WindowsSandboxLevel::Disabled)
.unwrap_or(SandboxType::None)
} else {
SandboxType::None
}
}Der Linux-Launcher wählt zwischen System-bwrap und bundled bwrap; findet er nichts, panic — ohne bubblewrap ist die gesamte Linux-Sandbox-Kette unterbrochen.
pub(crate) fn exec_bwrap(argv: Vec<String>, preserved_files: Vec<File>) -> ! {
match preferred_bwrap_launcher() {
BubblewrapLauncher::System(launcher) => {
exec_system_bwrap(&launcher.program, argv, preserved_files)
}
BubblewrapLauncher::Bundled(launcher) => launcher.exec(argv, preserved_files),
BubblewrapLauncher::Unavailable => {
panic!(
"bubblewrap is unavailable: no system bwrap was found on PATH and no bundled \
codex-resources/bwrap binary was found next to the Codex executable"
)
}
}
}Datenfluss
Grenzen und Fehler
SandboxablePreference::Forbidschaltet die Sandbox erzwungen aus,Requireerzwungen ein; nurAutorichtet sich nach der Policy:codex-rs/sandboxing/src/manager.rs:303-319- Auf macOS ist der
sandbox-exec-Pfad hart auf/usr/bin/sandbox-execgesetzt und umgeht PATH-Angriffe:codex-rs/sandboxing/src/seatbelt.rs:26-30 - Auf Linux löst ein fehlendes bubblewrap in panic aus statt stiller degradation — vermeidet den unsicheren Zustand „glaubt, Sandbox aktiv, ist sie aber nicht":
codex-rs/linux-sandbox/src/launcher.rs:42-48 - Der Pfad des MITM-CA-Trust-Bundles wird explizit zu den readable roots hinzugefügt, damit der Prozess in der Sandbox TLS validieren kann:
codex-rs/sandboxing/src/manager.rs:76-95 - In
core::execliestis_likely_sandbox_deniednach dem exec die stderr, um festzustellen, ob die Sandbox den Aufruf blockiert hat, und gibt dem Modell eine lesbare Fehlermeldung:codex-rs/core/src/exec.rs:768-810
Zusammenfassung
SandboxManager ist der einheitliche Einstieg der plattformübergreifenden Sandbox von codex; er übersetzt PermissionProfile in SandboxType und in ein argv mit Wrapper. Die Plattform-Backends isolieren je einzeln, leiten sich aber alle aus derselben FileSystemSandboxPolicy / NetworkSandboxPolicy ab. Um „warum wurde dieser Befehl abgelehnt" zu verfolgen, siehe Befehlsklassifikation execpolicy und Befehlsausführung exec-server.