openai / openai/codex-plugin-cc
`thread/resume` sandbox is ignored while the thread is still live in the shared app-server, so `task --resume-last --write` cannot write after a read-only run
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 33.3k
- Forks
- 2.3k
- PR merge metrics
- No merged PRs in 30d
Description
What happens
task forwards the requested sandbox on thread/resume (buildResumeParams in plugins/codex/scripts/lib/codex.mjs). Codex applies it only when the app-server loads the thread again from its rollout. While the thread is still live in the app-server, the resumed turns keep the sandbox the thread already has. The plugin keeps one shared app-server per Claude Code session (the broker), so inside a session every resume hits the live case: a rescue thread that began read-only ("investigate") stays read-only when it is resumed with --write, and the write attempt is refused inside Codex with no error from the plugin. The reverse also holds: a thread started with write access keeps it when resumed without --write.
Observed with Codex CLI 0.153.2 and plugin 1.0.6 (main at db52e28).
Reproduction
In any git repository, inside one session (so the broker keeps the app-server):
node "$PLUGIN/scripts/codex-companion.mjs" task \
"Create a file named probe.txt containing ok in the current directory using a shell command. Reply WRITE DENIED if the write is refused, WRITE OK otherwise."
# -> WRITE DENIED (expected: the thread is read-only)
node "$PLUGIN/scripts/codex-companion.mjs" task --resume-last --write \
"Create a file named probe2.txt containing ok in the current directory using a shell command. Reply WRITE DENIED if the write is refused, WRITE OK otherwise."
# -> WRITE DENIED, probe2.txt does not exist (expected: WRITE OK)
The other direction, same session:
node "$PLUGIN/scripts/codex-companion.mjs" task --write "Create probe.txt ... (same prompt)"
# -> WRITE OK
node "$PLUGIN/scripts/codex-companion.mjs" task --resume-last "Append a line to probe.txt ... Reply WRITE DENIED / WRITE OK."
# -> WRITE OK (expected: WRITE DENIED, the resumed request asked for read-only)
Then stop the broker (broker/shutdown, or end the session) and resume the write-capable thread once more without --write: the write is now refused, and the thread/resume response echoes {"type":"readOnly","networkAccess":false}. Resuming a read-only thread with danger-full-access after a restart echoes {"type":"dangerFullAccess"}. So the override works on a cold load and is dropped on a live thread.
Why it matters
/codex:rescue defaults to --write, so most threads start writable, but the common sequence "investigate (read-only), then --resume apply the fix" silently cannot apply anything within the same session. The plugin reports a completed task. The opposite case keeps write access on a follow-up the user meant to be read-only.
Possible fix
Either send the requested policy on every turn/start (TurnStartParams.sandboxPolicy is documented as "Override the sandbox policy for this turn and subsequent turns"), which needs a full SandboxPolicy object rather than a mode string and touches the same ground as #575 and #613, or treat a sandbox change on --resume-last as "start a fresh thread" in the plugin. This is probably also worth a report against the app-server itself, since ThreadResumeParams.sandbox is documented as an override without the live-thread exception. Until one of those lands, the docs should say the sandbox is fixed for the life of the session's thread and --fresh is the way to change it; the --sandbox PR says that in the README.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with buildResumeParams in plugins/codex/scripts/lib/codex.mjs and the shared app-server broker path used by codex-companion.mjs task. Reproduce the read-only-then-write and write-then-read resumes in one session, then compare the requested sandbox with the live thread behavior. Done means sandbox changes on resume are honored or the supported fresh-thread behavior is clearly documented and tested.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, node.js
- Domain
- cli, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100