Skip to content

Bac à sable multiplateforme (sandbox)

源码版本rust-v0.145.0

codex isole l'exécution des commandes dans le sandbox natif de la plateforme : sandbox-exec (seatbelt) sur macOS, bubblewrap + seccomp sur Linux, restricted token sur Windows. Le crate sandboxing fournit l'abstraction unifiée ; linux-sandbox/, bwrap/, windows-sandbox-rs/, process-hardening/ sont les implémentations par plateforme. Avant chaque exec, core calcule un SandboxType puis le confie à SandboxManager::transform qui construit le véritable argv à spawner.

Responsabilités

  1. Selon PermissionProfile, décider d'activer le sandbox et quel backend : codex-rs/sandboxing/src/manager.rs:273-319
  2. Sur macOS, construire la policy seatbelt et l'argv de sandbox-exec : codex-rs/sandboxing/src/seatbelt.rs:21-30
  3. Sur Linux, passer par le helper codex-linux-sandbox : d'abord no_new_privs + seccomp, puis exec bubblewrap : codex-rs/linux-sandbox/src/lib.rs:1-30
  4. Sur Windows, isoler système de fichiers et réseau via restricted token / elevated backend : codex-rs/windows-sandbox-rs/src/lib.rs:13-50
  5. Appliquer un durcissement processus avant main (couper les core dump, refuser ptrace, nettoyer LD_PRELOAD/DYLD_*) : codex-rs/process-hardening/src/lib.rs:12-25

Motivations de conception

Pourquoi ne pas se contenter de faire confiance au blocage d'execpolicy ? Parce que le modèle peut construire un shell arbitraire, et qu'un moteur de règles aura toujours des cas aux limites. Forcer chaque commande dans un sandbox OS natif est le filet de sécurité « même si le modèle contourne, le kernel bloque ». SandboxablePreference::Auto permet aux profiles workspace-write / read-only d'activer le sandbox, tandis que le profile full-access dégénère directement en SandboxType::None, évitant un emballage de processus inutile.

Les backends diffèrent par plateforme parce qu'il n'existe pas de primitive de sandbox unique multiplateforme : seatbelt sur macOS est déclaratif .sbpl, bubblewrap sur Linux repose sur user namespace + bind mount, restricted token sur Windows est token + ACL. L'énum SandboxType unifie ces trois backends et None sous un même label ; core/exec-server ne voient que le label, indifférents aux détails de plateforme.

Fichiers clés

SandboxType unifie les trois backends plateforme et « pas de sandbox » en un seul label, core ne voit que le label.

rust
pub enum SandboxType {
    None,
    MacosSeatbelt,
    LinuxSeccomp,
    WindowsRestrictedToken,
}

Dans select_initial, on décide d'abord avec should_sandbox si sandbox il y a, puis on demande à la plateforme quel backend elle peut fournir :

rust
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
    }
}

Le launcher Linux choisit entre bwrap système et bwrap bundled, et panic si absent — sans bubblewrap, toute la chaîne sandbox Linux est cassée.

rust
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"
            )
        }
    }
}

Flux de données

Limites et échecs

Récapitulatif

SandboxManager est l'entrée unifiée du sandbox multiplateforme de codex : il traduit PermissionProfile en SandboxType puis en argv emballé. Les backends plateforme isolent chacun à leur manière, mais dérivent tous de la même FileSystemSandboxPolicy / NetworkSandboxPolicy. Pour remonter « pourquoi cette commande a été refusée », voir Classification execpolicy et Exécution exec-server.