Environment
- macOS 14.2 (23C64), Apple Silicon.
- Codex desktop 26.908.40834, bundle build 8881.
- Bundled CLI:
codex-cli 0.154.0-alpha.6.2.
- Also inspected current upstream
main at 70eb36203dbb8c75d006b39cdfae74bd04e18a65; it contains the same symbolic rule.
- No model request, account access, or project is needed to reproduce.
Reproduction
Run the desktop app's bundled executable from a terminal:
/Applications/Codex.app/Contents/Resources/codex sandbox -P :read-only -- /usr/bin/true
Actual result: exit 65, before /usr/bin/true starts:
sandbox-exec: unbound variable: TIOCSTI at <input string>, line 132, column 33
Backtrace:
<input string>:132:33:
TIOCSTI
Expected result: /usr/bin/true starts inside the sandbox and exits 0.
Both this installed build and current upstream use the following sandbox syntax (macos is not a subcommand in either):
codex sandbox -P :read-only -- /usr/bin/true
In the desktop app, browser-controller startup fails with the same error before its Node kernel starts. This prevents browser tasks from running; resetting the browser controller reproduces it.
Root cause
The guard added by #42590 in codex-rs/cli/src/debug_sandbox.rs appends:
(deny file-ioctl (ioctl-command TIOCSTI))
On this macOS version, the Seatbelt policy compiler does not define the bare TIOCSTI symbol. The ioctl itself exists: the platform constant is 0x80017472 (2147578994). A minimal policy using the symbolic name reproduces the compilation error; replacing it with the numeric value compiles.
The proposed correction formats the existing platform libc::TIOCSTI constant into that rule. It preserves the denial, rule order, and sandbox permissions; it does not disable terminal-injection protection.
Validation and reference patch
Tested the reference correction on this same macOS 14.2 host, using Rust 1.95.0:
just fmt and git diff --check: passed.
just test -p codex-cli --test sandbox_tty: 2 passed, 0 skipped.
just test -p codex-cli --success-output immediate: 451 passed, 0 skipped.
target/debug/codex sandbox -P :read-only -- /usr/bin/true: exit 0.
The two Seatbelt tests execute the startup regression and a disposable-PTY control/denial probe. The latter confirms that TIOCSTI succeeds on the unsandboxed control PTY but is denied with EPERM inside the sandbox, with no injected input left queued. Tests ran outside a parent Seatbelt sandbox; the availability check did not skip them.
Reference patch and regression tests: bibryam#1
This issue follows the repository's contribution policy: the code is provided in the reporter's fork as a reference, not as an external upstream PR. No installed app binaries or security settings were modified.
Environment
codex-cli 0.154.0-alpha.6.2.mainat70eb36203dbb8c75d006b39cdfae74bd04e18a65; it contains the same symbolic rule.Reproduction
Run the desktop app's bundled executable from a terminal:
Actual result: exit 65, before
/usr/bin/truestarts:Expected result:
/usr/bin/truestarts inside the sandbox and exits 0.Both this installed build and current upstream use the following sandbox syntax (
macosis not a subcommand in either):In the desktop app, browser-controller startup fails with the same error before its Node kernel starts. This prevents browser tasks from running; resetting the browser controller reproduces it.
Root cause
The guard added by #42590 in
codex-rs/cli/src/debug_sandbox.rsappends:On this macOS version, the Seatbelt policy compiler does not define the bare
TIOCSTIsymbol. The ioctl itself exists: the platform constant is0x80017472(2147578994). A minimal policy using the symbolic name reproduces the compilation error; replacing it with the numeric value compiles.The proposed correction formats the existing platform
libc::TIOCSTIconstant into that rule. It preserves the denial, rule order, and sandbox permissions; it does not disable terminal-injection protection.Validation and reference patch
Tested the reference correction on this same macOS 14.2 host, using Rust 1.95.0:
just fmtandgit diff --check: passed.just test -p codex-cli --test sandbox_tty: 2 passed, 0 skipped.just test -p codex-cli --success-output immediate: 451 passed, 0 skipped.target/debug/codex sandbox -P :read-only -- /usr/bin/true: exit 0.The two Seatbelt tests execute the startup regression and a disposable-PTY control/denial probe. The latter confirms that TIOCSTI succeeds on the unsandboxed control PTY but is denied with
EPERMinside the sandbox, with no injected input left queued. Tests ran outside a parent Seatbelt sandbox; the availability check did not skip them.Reference patch and regression tests: bibryam#1
This issue follows the repository's contribution policy: the code is provided in the reporter's fork as a reference, not as an external upstream PR. No installed app binaries or security settings were modified.