openai / openai/codex-plugin-cc

task --prompt-file: the prompt path is discarded after reading, so no plugin cleanup can ever remove the caller's file

Open
#622 0 comments 0 reactions 0 assignees View on GitHub

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, scripts/session-lifecycle-hook.mjs), observed on Windows 11, Node 24.

Summary. When a prompt is supplied with --prompt-file, the companion converts the path into content and never retains the path. As a result no plugin lifecycle can ever remove that file — not the 50-job prune, not the SessionEnd cleanup. The caller is the only party able to delete it, and any cleanup the caller schedules runs in the very process that may die. An abrupt shell, session, or host termination between file creation and the caller's own cleanup step leaves the prompt on disk indefinitely, with nothing to scavenge it.

Where:

  • readTaskPrompt (codex-companion.mjs:643-645) returns the file's contents as a string. The path is used for the read and then discarded; it is not stored on the job or anywhere else.
  • buildTaskRequest (codex-companion.mjs:604-610) puts that CONTENT into request.prompt.
  • enqueueBackgroundTask (codex-companion.mjs:695-697) writes that request into the job record.
  • cleanupSessionJobs (session-lifecycle-hook.mjs:42-75) filters state.jobs by sessionId (line 54), terminates process trees for still-queued/running jobs (lines 59-69), and rewrites state without them (lines 71-74). Job records and their logs only — it has no prompt path to act on, so it cannot touch the caller's file.

Impact. Prompt files routinely carry sensitive material: repository excerpts, client content, internal notes. The plugin's own copies of that text have a retention story a user can reason about — pruned past 50 jobs, and wiped for the whole session at SessionEnd. The caller's file has no lifecycle at all. This is the part most likely to surprise: a user who sees the session-end cleanup reasonably assumes the dispatch was cleaned up, when the file the plugin told them to create is precisely what survives.

Note the asymmetry with the review path — adversarial-review takes its focus positionally and requires no file. Only the task path obliges the caller to materialize prompt text on disk, which is what creates the residue.

We currently document this to our own operators as best-effort cleanup that cannot survive abrupt termination, because no caller-side fix exists: cleanup code cannot run after its own process is gone.

Suggested fixes (the first is smallest and opt-in, so it cannot surprise existing callers):

  1. --prompt-file-consume — unlink the file immediately after a successful read. Opt-in, one line at the read site, and it collapses the exposure window from "until the caller gets around to it" to "the moment the content is in memory".
  2. Record the resolved prompt path on the job record and delete it in the same SessionEnd sweep that already removes the job, so an abrupt death is covered by the existing cleanup rather than by the caller.
  3. At minimum, document it — state explicitly that the caller owns the file's lifetime and that no plugin cleanup will ever touch it. That alone would correct the reasonable assumption described above.

Options 1 and 2 are complementary: 1 covers the normal path, 2 covers a death between file creation and the read.

Filed alongside a companion report about the same flag's verification behaviour, and by the same reporter as #620.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with readTaskPrompt, buildTaskRequest, and enqueueBackgroundTask in scripts/codex-companion.mjs, then trace cleanupSessionJobs in scripts/session-lifecycle-hook.mjs. Determine which proposed prompt-file lifecycle behavior is selected and verify that normal and SessionEnd cleanup handle the caller's file, with documentation updated if ownership remains caller-side.

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
Quiet
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.