feat(sandbox): resolve task sandbox from config.toml + add task --read-only (port openai#508)#33
Merged
Merged
Conversation
…d-only (port openai#508) Port of @cubicj's openai#508. The plugin hardcoded the sandbox ("read-only"/"workspace-write"), ignoring sandbox_mode in ~/.codex/config.toml. Now the task path sends sandbox: null when the caller does not pin one, letting the app-server resolve it from config — the same mechanism already used for model. Explicit --write still forces workspace-write; review paths keep their pinned read-only. - buildThreadParams/buildResumeParams: sandbox ?? null (config-driven default) - task --read-only flag: per-run read-only pin, mutually exclusive with --write - stop-review-gate hook's internal task passes --read-only explicitly so the gate stays read-only regardless of config - rescue command/agent/skill docs updated for --read-only Merged onto the fork (conflicts in codex.mjs, codex-companion.mjs, rescue.md, fake-codex-fixture, runtime.test): kept our reasoning-validation + turn-timeout-ms + model aliases + --cwd, layered cubicj's sandbox-null + --read-only on top. Our fake-codex fixture already recorded sandbox in lastThreadStart/lastThreadResume, so openai#508's assertions pass as-is. Verified: npm run build clean; npm test 174/171 pass / 3 pre-existing (was 4 — the background test that previously asserted a foreign model-luna value now passes). All 6 new sandbox tests green. Co-Authored-By: Claude <noreply@anthropic.com>
…me (cycle-review critical) Codex adversarial review of #33 flagged — and a real-codex smoke confirmed — that Codex 0.144.6 keeps a loaded thread's sandbox and ignores thread/resume overrides: `task --read-only --resume-last` on a write-capable thread ran with workspace-write access, violating the --read-only contract. Verified empirically (codex-cli 0.144.6): write-thread -> resume with --read-only returned resolved.sandbox = workspaceWrite. The code never compared the resolved sandbox to the explicit pin. Fix: assertExplicitSandboxHonored() in runAppServerTurn compares an explicit read-only pin to the app-server's resolved sandbox and throws on mismatch — fail closed instead of running write-capable under a read-only flag. Only the read-only pin is enforced (a write request on a read-only resolved sandbox is a downgrade, not a safety leak). TDD: a resume-ignores-sandbox fake-codex behavior reproduces the leak (RED), the assertion turns it green. Also confirms the port's cubicj claim: a plain task with sandbox:null resolves to read-only from config (smoke: resolved readOnly), so stock behavior is unchanged. Co-Authored-By: Claude <noreply@anthropic.com>
Owner
Author
📋 Review summary — all cycles
Totals: 1 critical (smoke-confirmed, resolved), 0 SKIP, 0 UNVERIFIED. |
axisrow
added a commit
that referenced
this pull request
Jul 21, 2026
Ships accumulated fixes since fork.4: - #29 broker-busy hang (PR #30): bound broker handshake - #31 spawned-app-server handshake (PR #32): bound request() primitive - openai#508 config-driven sandbox + --read-only (PR #33) + resume-sandbox fail-closed - #34 model/effort in /codex:rescue launch line (PR #35) - #28 turn-timeout gaps (already in fork.4 base) Co-Authored-By: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Port of @cubicj's openai#508. The plugin hardcoded the sandbox (
read-only/workspace-write), ignoringsandbox_modein~/.codex/config.toml. Now the task path sendssandbox: nullwhen the caller does not pin one, letting the app-server resolve it from config — the same mechanism already used formodel. An explicit--writestill forcesworkspace-write; review paths keep their pinnedread-only.Adds a
task --read-onlyflag for a per-run read-only pin, mutually exclusive with--write.Why
Users who set
sandbox_mode = "danger-full-access"(e.g. trusted delegation) had to hand-patch the installed plugin. Porting openai#508 lets config drive the default and gives an explicit per-run escalation/lockdown.Merge notes
openai#508 was written against an older base; merged onto the fork resolving conflicts in
codex.mjs,codex-companion.mjs,rescue.md,fake-codex-fixture.mjs,runtime.test.mjs. Kept our reasoning-validation,--turn-timeout-ms, model aliases (spark/sol/terra/luna), and--cwd/-C; layered cubicj'ssandbox: null+--read-onlyon top. Our fake-codex fixture already recordedsandboxinlastThreadStart/lastThreadResume, so openai#508's assertions pass as-is.Verification
npm run build: clean.npm test: 174 tests, 171 pass / 3 pre-existing failures (was 4 — thetask --backgroundtest that previously asserted a foreign model-luna value now passes). All 6 new sandbox tests green:--write→workspace-write, resuming--write,--background preserves --read-only,--read-only pins,--read-only pins resumed,--write --read-onlyrejected.sandbox: nullresolves fromconfig.tomlon real codex (as done for Capture resolved model/effort/sandbox in job records openai/codex-plugin-cc#506).Hat-tip to @cubicj — original PR openai#508.
🤖 Generated with Claude Code