クロスプラットフォームサンドボックス (Sandbox)
codex はコマンド実行をプラットフォームネイティブの sandbox に隔離する:macOS は sandbox-exec (seatbelt)、Linux は bubblewrap + seccomp、Windows は restricted token。sandboxing crate が統一抽象を提供し、linux-sandbox/、bwrap/、windows-sandbox-rs/、process-hardening/ が各プラットフォームの実装だ。core は各 exec の前に SandboxType を算出し、SandboxManager::transform に渡して実際に spawn する argv を組み立てる。
責務
PermissionProfileに従い sandbox を有効にするか、どの backend を使うかを決める:codex-rs/sandboxing/src/manager.rs:273-319- macOS で
sandbox-execの seatbelt policy と argv を組み立てる:codex-rs/sandboxing/src/seatbelt.rs:21-30 - Linux で
codex-linux-sandboxhelper を使う:まず no_new_privs + seccomp を設定し、その後 bubblewrap を exec する:codex-rs/linux-sandbox/src/lib.rs:1-30 - Windows で restricted token / elevated backend によりファイルシステムとネットワークを隔離する:
codex-rs/windows-sandbox-rs/src/lib.rs:13-50 - main の前にプロセスレベルの hardening(core dump 無効化、ptrace 拒否、
LD_PRELOAD/DYLD_*のクリア)を行う:codex-rs/process-hardening/src/lib.rs:12-25
設計動機
なぜ execpolicy のブロックをそのまま信じないのか?モデルは任意の shell を構築でき、ルールエンジンには常に境界 case があるからだ。各コマンドを OS ネイティブの sandbox に強制的に閉じ込めるのは、「モデルがどう回避してもカーネル層で止める」最後の砦だ。SandboxablePreference::Auto は workspace-write / read-only などのポリシープロファイルで sandbox を有効にし、full-access プロファイルは SandboxType::None に退化し、無駄なプロセス包装を避ける。
各プラットフォームの backend が異なるのは、クロスプラットフォームで統一された sandbox プリミティブが存在しないからだ:macOS の seatbelt は宣言型 .sbpl、Linux の bubblewrap は user namespace + bind mount、Windows の restricted token は token + ACL。SandboxType enum がこの三つの backend と None を同じラベルに統一し、core/exec-server はラベルだけを見てプラットフォーム詳細を気にしない。
主要ファイル
codex-rs/sandboxing/src/lib.rs:1-46— モジュール入口。target_osでどの backend をコンパイルするかを決める。codex-rs/sandboxing/src/manager.rs:35-75—SandboxTypeenum とget_platform_sandbox。codex-rs/sandboxing/src/manager.rs:273-329—SandboxManagerとselect_initial/should_sandbox。codex-rs/sandboxing/src/manager.rs:321-413—transformが sandbox タイプに従い元の argv を wrapper 付き argv に変換。codex-rs/sandboxing/src/seatbelt.rs:21-30— macOS のsandbox-execパスは/usr/bin/sandbox-execに固定で、PATH injection を防ぐ。codex-rs/linux-sandbox/src/launcher.rs:36-67— Linux bubblewrap launcher:システム bwrap を優先し、bundled にフォールバック。codex-rs/process-hardening/src/lib.rs:43-61— Linux プロセス hardening:prctl(PR_SET_DUMPABLE, 0)+LD_*のクリア。codex-rs/core/src/exec.rs:117-130— core 側でselect_initialを呼ぶ入口。
SandboxType は三つのプラットフォーム backend と「sandbox なし」を一つのラベルに統一し、core はラベルだけを見る。
pub enum SandboxType {
None,
MacosSeatbelt,
LinuxSeccomp,
WindowsRestrictedToken,
}select_initial では、まず should_sandbox で sandbox が必要かを決め、その後にプラットフォームがどの backend を提供できるかを問う:
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
}
}Linux launcher はシステム bwrap と bundled bwrap のどちらかを選び、見つからなければ panic する——bubblewrap が使えないと Linux sandbox のリンク全体が切れる。
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"
)
}
}
}データフロー
境界と失敗
SandboxablePreference::Forbidは sandbox を強制無効化し、Requireは強制有効化する。Autoだけが policy を見る:codex-rs/sandboxing/src/manager.rs:303-319- macOS では
sandbox-execパスを/usr/bin/sandbox-execに固定し、PATH 攻撃を回避する:codex-rs/sandboxing/src/seatbelt.rs:26-30 - Linux では bubblewrap が見つからない場合、黙っての格下げではなく panic する——「sandbox があると思ったら実は無かった」という安全でない状態を避けるため:
codex-rs/linux-sandbox/src/launcher.rs:42-48 - MITM CA 信頼バンドルのパスは明示的に readable roots に追加される。さもないと sandbox 内プロセスが TLS を検証できない:
codex-rs/sandboxing/src/manager.rs:76-95 core::execのis_likely_sandbox_deniedは exec 完成後に stderr を見て sandbox にブロックされたかを判断し、モデルに読みやすいエラーを返す:codex-rs/core/src/exec.rs:768-810
まとめ
SandboxManager は codex のクロスプラットフォーム sandbox の統一入口で、PermissionProfile を SandboxType に翻訳し、さらに wrapper 付き argv に翻訳する。プラットフォーム backend はそれぞれ独立に隔離するが、すべて同じ FileSystemSandboxPolicy / NetworkSandboxPolicy から導出する。「なぜこのコマンドが拒否されたか」の現場を追うには コマンド分類 execpolicy と コマンド実行 exec-server の二ページを参照。