codex-rescue invocation deleted user source repo on disk (destructive cleanup before auth check)

Resolved 💬 2 comments Opened Apr 29, 2026 by onchainyaotoshi Closed Apr 29, 2026

Bug: codex-rescue invocation deleted source repo on disk

Plugin: openai-codex (codex 1.0.4 from official marketplace)
Codex CLI: @openai/codex 0.122.0 (npx-cached at ~/.pinokio/config/.npm/_npx/c8ab89660c602c20/node_modules/@openai/codex)
Claude Code: 2.1.122 (Linux x86_64)
Reporter: yaotoshinakamoto@gmail.com
Severity: CRITICAL — data loss, no warning, not user-initiated

Summary

A single invocation of the codex:codex-rescue subagent caused the entire source repository at /home/firman/pinokio/ to be deleted from disk, including a git worktree with ~12 unpushed commits. The subagent ultimately returned Not logged in · Please run /login (the user had not authenticated codex CLI), but the destructive side-effect happened anyway before the auth check.

The exact command that produced the destructive output cannot be reconstructed because the parent session's transcript was deleted in the same operation. What we have:

  1. The codex-rescue subagent's transcript (preserved because it's stored under ~/.claude/projects/, not under the repo).
  2. The tool_result content returned by that subagent — which contains the smoking-gun output described below.

Evidence

The codex-rescue subagent transcript at:

~/.claude/projects/-home-firman-pinokio--claude-worktrees-redesign-index-html/86a81505-c339-4f5c-8505-361526ba5ff4/subagents/agent-ace458bfdf4875a05.jsonl

contains a single tool_result (referencing the parent's tool_use_id=toolu_01YQPAEAMCrp5Tg1TP4BV6xx) whose stdout reads, in order:

Exit code 127
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100  4180  100  4180    0     0  13049      0 --:--:-- --:--:-- --:--:-- 13062
rm: cannot remove '/home/firman/.pinokio/scripts/ai-subscription/workspace.json': Permission denied
rm: cannot remove '/home/firman/.pinokio/scripts/ai-subscription/ollama-billing/manifest.json': Permission denied
rm: cannot remove '/home/firman/.pinokio/scripts/ai-subscription/ollama-billing/runs/1777318475304-ok.json': Permission denied
... (hundreds of similar rm: Permission denied lines against /home/firman/.pinokio/scripts/...) ...

followed by an assistant text block:

Not logged in · Please run /login

The 4180-byte HTTP fetch + rm against deeply-nested user files + exit 127 all came back as a single tool_result blob. The subagent transcript does not contain the matching tool_use input — only the result.

What was deleted vs not

  • /home/firman/.pinokio/scripts/... — owned by uid 1000 inside a Docker container (abc/node user); from the host's user (uid 1000 firman vs container uid 1000 = different identity due to user namespacing). Result: the rm calls hit Permission denied, files survived.
  • /home/firman/pinokio/ — the source repository, owned by host user firman. The same rm operation succeeded silently against this path. The entire directory tree is gone.
  • The directory included a git worktree with ~12 unpushed commits, a .env with API tokens for 7+ providers, and the project's main .git/.

Why the bug fires before auth check

The codex-rescue agent definition at agents/codex-rescue.md says it is "a thin forwarding wrapper" that runs exactly one Bash call: node "${CLAUDE_PLUGIN_ROOT}/scripts/codex-companion.mjs" task ....

I have grep'd the entire plugin source for rm -rf, curl, wget, bash -c, etc. — none are present in the plugin's JavaScript. The plugin's only filesystem deletion is targeted fs.unlinkSync on specific pidfile/socket/logfile paths in scripts/lib/broker-lifecycle.mjs:182-204.

That means the destructive curl + rm chain came from outside the plugin's JS but inside the bash invocation that the agent issued. Most likely candidate: the codex CLI binary itself (@openai/codex@0.122.0, vendored Rust binary at vendor/x86_64-unknown-linux-musl/codex/codex). When the binary determines it has no auth, instead of cleanly erroring, something in its initialization path appears to issue HTTP fetches and a recursive rm against files in the user's working directory tree.

Auth must be checked before any side-effect. Whatever cleans state should never run before codex auth status returns OK.

Reproduction

I cannot guarantee reproduction without your reproducer environment. The user-facing trigger sequence was:

  1. Fresh codex install (npx -y @openai/codex had been run earlier in the session; auth had never been completed).
  2. Claude Code dispatched codex:codex-rescue via the Agent tool with subagent_type=codex:codex-rescue, model unset, write-capable, large prompt for adversarial review of a separate codebase.
  3. The subagent's single Bash tool returned the output above.
  4. After the user ran /login (Claude Code login, not codex auth) and a fresh codex-rescue was dispatched, that second invocation observed that /home/firman/pinokio/ no longer existed and reported the directory gone.

What I'd ask for

  1. Investigate which subprocess in the codex auth-failure path (CLI binary, plugin shim, or npx setup) issues rm against user files. I'd start with strace -f -e trace=execve,unlink,unlinkat on a freshly-installed unauthenticated codex binary.
  2. Block all destructive ops until auth is verified. No state cleanup, no temp wipe, nothing that can touch *.json outside the codex CLI's own state dir.
  3. Scope state cleanup to a clearly-delimited path. The current rm targeted /home/firman/.pinokio/scripts/<workspace>/<script>/... — that's the user's project content, not codex state. Either the cleanup is targeting the wrong path, or the path-resolution logic is collapsing to the user's cwd.
  4. Document the destructive state cleanup in the plugin README. Right now there is no warning that codex invocation can delete files in the user's working directory.
  5. Add a no-op-when-not-authenticated mode so the codex-rescue agent (which advertises itself as "proactive") doesn't perform side-effects on a user who hasn't completed setup.

I have preserved the subagent transcript at the path above and am happy to share it (it contains no secrets, only the codex output). I have also preserved my own analysis of the plugin source code.

Side note

This appears to be a single invocation that destroyed a non-trivial amount of unpushed work. There was no warning, no opt-in prompt, no dry-run output. For a tool described as "Proactively use when Claude Code is stuck" the destructive blast radius is unacceptable. I am temporarily disabling the plugin and will re-enable only after seeing a fix.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗