openai / openai/codex-plugin-cc
task --prompt-file: the file is re-read by the launcher, so a caller cannot prove which bytes were dispatched
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 33.3k
- Forks
- 2.3k
- PR merge metrics
- No merged PRs in 30d
Description
Version: plugin 1.0.6 (scripts/codex-companion.mjs), observed on Windows 11, Node 24.
Summary. task --prompt-file takes a PATH, and the launched process performs its own read of that path. A caller that verifies the file before launching cannot bind that verification to what is actually dispatched: between the caller's check and the launcher's readFileSync, the file can be rewritten and the dispatch proceeds normally on different content. There is no way for a caller to express either "dispatch exactly this content" or "dispatch this file only if it still hashes to X".
Where (scripts/codex-companion.mjs, v1.0.6):
readTaskPromptreads the file at line 645 (fs.readFileSync(path.resolve(cwd, options["prompt-file"]), "utf8")) whenoptions["prompt-file"]is set.- It is called from
handleTaskCommandat line 775, immediately after option parsing. - That call precedes
enqueueBackgroundTaskat line 802, which is what spawns the detached worker (spawnDetachedTaskWorker, lines 671-682). - For a background dispatch the resulting CONTENT is then persisted into the job record:
buildTaskRequest(lines 604-610) places it inrequest, andenqueueBackgroundTaskwrites that record (lines 695-697).
Measured scope, stated so this is not overclaimed. Because the read happens at line 775 — early in the launched process, before the worker spawns and before any turn begins — the exposed window is the caller's launch plus Node startup and argument parsing. A few hundred milliseconds, bounded by process startup rather than by the length of the run. This is therefore much more a cannot prove what was dispatched problem than a likely to be hit by accident one.
Impact. For any wrapper that dispatches on an operator's behalf and wants an auditable record of what it sent, the verification is defeatable and, more importantly, unprovable. Under --write the brief is what authorizes file modification, so a substituted brief is a write run the operator never approved. Without --write the correctness cost is smaller but the audit cost is the same: the operator cannot demonstrate after the fact which bytes Codex actually received.
The adversarial-review path does not share this: it takes its focus positionally, so the caller hands over already-read text and no second read can disagree with it. The asymmetry is what makes the task path worth fixing.
Suggested fixes (any one closes it; the first is smallest):
--prompt-file-sha256 <hex>— verify the digest inside the same read that consumes the file, and error on mismatch. This genuinely closes the race, because check and use become one operation. No caller-side guard can achieve that, since the caller's process has exited by the time the read happens.- Echo the digest — hash the buffer that was actually read and include it in the
--jsonpayload. This does not prevent substitution, but it makes it detectable and gives callers something to reconcile against. - Document stdin as a first-class verified transport —
readTaskPromptalready falls back toreadStdinIfPiped()at line 649, and content passed directly has no path to re-read. Worth noting that neither--prompt-filenor the stdin fallback currently appears in the--helpbanner, so callers have to read the source to discover either.
Filed alongside a companion report about the same flag's cleanup behaviour, and by the same reporter as #620.
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 in scripts/codex-companion.mjs with readTaskPrompt, then trace handleTaskCommand into buildTaskRequest and enqueueBackgroundTask. Compare the suggested prompt-file verification, digest reporting, and stdin documentation approaches, and add coverage for the selected behavior. Done means a caller can verify or detect the content actually dispatched without a second unchecked file read.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, node.js
- Domain
- cli, security
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 64/100