Support user-provided Seatbelt sandbox rules via config or drop-in file
What variant of Codex are you using?
CLI (also applies to Desktop app on macOS)
What feature would you like to see?
Allow users to provide additional Seatbelt sandbox rules that get appended to the assembled policy at runtime, without recompiling Codex.
Motivation: Codex's Seatbelt base policy (seatbelt_base_policy.sbpl + restricted_read_only_platform_defaults.sbpl) covers common OS interactions but inevitably misses niche-but-legitimate ones. The current workarounds — per-command escalation or :danger-full-access — are either tedious or overly broad.
A concrete example: Chromium/Playwright headless (#21292) requires (allow mach-register (global-name-regex #"^org\.chromium\.")) for its multi-process IPC. Today, users must escalate every Playwright invocation or disable the sandbox entirely. A one-line user rule would fix it permanently and precisely.
Other cases that benefit from user-provided rules:
- CLI tools that write config to non-standard
~/Library/Application Support/<tool>/paths (e.g.,glab-cli) - Language toolchain telemetry paths (e.g., Go writes to
~/Library/Application Support/go/telemetry/) - Platform-specific
sysctl-readentries for ARM feature detection (hw.optional.neon_fp16, etc.) - Mach service lookups required by domain-specific frameworks
Proposed approach (one of):
- Drop-in file: Read
~/.codex/sandbox-extra.sb(or~/.codex/sandbox.d/*.sb) if it exists, and append its contents to the assembled Seatbelt policy after all built-in sections.
- Config key: Add a
sandbox_extra_ruleskey toconfig.tomlunder the permission profile:
``toml``
[permissions.my-profile]
sandbox_extra_rules = """
(allow mach-register (global-name-regex #"^org\\.chromium\\."))
(allow mach-lookup (global-name "com.apple.CARenderServer"))
"""
- Config file reference: A
sandbox_extra_rules_filekey pointing to an external.sbfile.
The drop-in file approach is simplest and follows established patterns (conf.d/ in nginx, systemd, etc.). It also keeps sandbox customization separate from the TOML config, which feels appropriate given that Seatbelt rules are a different language (TinyScheme S-expressions).
Implementation sketch (in codex-rs/sandboxing/src/seatbelt.rs):
// After assembling policy_sections from built-in .sbpl files + dynamic rules:
let extra_path = dirs::home_dir()
.map(|h| h.join(".codex/sandbox-extra.sb"));
if let Some(path) = extra_path {
if let Ok(extra) = std::fs::read_to_string(&path) {
policy_sections.push(extra);
}
}
let full_policy = policy_sections.join("\n");
This is ~5 lines of Rust with zero breaking changes. Users who don't create the file get identical behavior to today.
Security consideration: Users who can write ~/.codex/sandbox-extra.sb already have full access to their own machine — they could just run commands outside the sandbox. User-provided rules only _relax_ the sandbox (Seatbelt rules are additive on top of (deny default)), and the current permission profile system already trusts user-authored TOML config for filesystem and network policy. This is consistent with that trust model.
Additional information
I maintain a macOS Seatbelt sandbox wrapper (ccbox) for Claude Code that reuses Codex's base .sbpl policies. The wrapper uses a text-file-based approach for user rules (extra-allow.txt + editable sandbox-base.sb), and being able to add the Chromium mach-register rule without recompilation has been essential for Playwright/browser-based verification workflows.
Related: #21292 (Playwright Chromium fails in sandbox with MachPortRendezvousServer permission denied) — I posted a root-cause analysis and the specific fix there. That issue would be fully resolved by either upstreaming the rule into seatbelt_base_policy.sbpl or by this feature allowing users to add it themselves.
2 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Not a duplicate of #23505. That issue requests a specific missing
mach-lookup(com.apple.sysmond.system) forps/pgrepprocess listing. This issue proposes a general mechanism for user-provided Seatbelt rules covering all rule types —mach-register,mach-lookup,sysctl-read,file-write*, etc.That said, #23505 is a great related example: its "Option 2" (a
config.tomlkey for mach-lookup allowlists) is effectively a subset of what this feature request proposes. A drop-in.sbfile would solve #23505's use case as well — users could add(allow mach-lookup (global-name "com.apple.sysmond.system"))without waiting for an upstream policy update.Related issues that would benefit from this feature:
mach-registerblocked (MachPortRendezvousServer)ps/pgrepmach-lookupblocked (sysmond)