Recursive remote cleanup can escape the intended directory through nested PowerShell/cmd quoting without a root-path safety stop

Open 💬 3 comments Opened Jul 21, 2026 by Sxl7939-dot
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

Summary

Codex intended to remove one temporary smoke-test directory in my own Parallels Windows 11 build VM. After PowerShell Remove-Item failed because a DLL was still locked, Codex automatically escalated to a stronger recursive deletion through a nested macOS shell → SSH → PowerShell -EncodedCommandcmd.exe chain.

An incorrect PowerShell/cmd quoting pattern caused the operation to traverse the current Windows drive root instead of the intended temporary directory. The operation ran for approximately 59 seconds before a later tool input sent Ctrl-C.

This issue intentionally omits the complete executable deletion command. The original session is available privately through Codex feedback: 019f82c8-4c41-7f91-ab74-30b3d34c98dc.

OpenAI Support confirmed on 2026-07-21 that the conversation was escalated to a support specialist. Support case 11849398 has been issued.

Environment

  • Codex task ID: 019f82c8-4c41-7f91-ab74-30b3d34c98dc
  • Codex Desktop / recorded version: 0.145.0-alpha.18
  • Recorded model setting: gpt-5.6-sol, effort max
  • Host: macOS 27.0 (26A5378n)
  • Guest: Windows 11 under Parallels Desktop 26.3.3
  • Remote execution: SSH → PowerShell -EncodedCommandcmd.exe
  • sandbox_policy.type: danger-full-access
  • approval_policy: never
  • permission_profile: disabled
  • Support case: 11849398

Expected behavior

  • A locked temporary directory should be left in place and reported as a non-blocking cleanup failure.
  • A recursive delete must remain inside the unique approved run directory.
  • The target OS should normalize and attest the final absolute path before deletion.
  • Drive roots, user profiles, Desktop, empty paths, unresolved variables, and run roots should be unconditionally rejected.
  • A stronger delete method should not be selected automatically after a safer cleanup method fails.

Actual behavior

  1. The final package self-check succeeded.
  2. PowerShell cleanup failed on a locked Pillow _imaging DLL.
  3. Codex described the lock as temporary and retried with a stronger recursive cmd.exe deletion.
  4. A backslash-based quote escape was used even though PowerShell does not use backslash to escape double quotes.
  5. No final normalized path, final argv, file count, size estimate, allow-root assertion, or root-deny check was shown before execution.
  6. Preserved output contained root-level paths including \pagefile.sys, \PROGRA~1\..., and \Users\....
  7. The output was recorded as 1,341 lines but truncated.
  8. There was no visible automatic output-anomaly stop. Ctrl-C was sent manually about 59.383 seconds after launch.

Context compaction facts

The rollout contains three compaction events in total:

  • 12:45:42.425 UTC+8
  • 14:11:50.009 UTC+8
  • 15:11:12.425 UTC+8, after the incident

Two compactions therefore occurred before the dangerous command. The latest was 42 minutes 08.604 seconds earlier.

I am not claiming compaction directly caused the incident. The exact smoke-test path was created after the second compaction, and the visible replacement history still contains a higher-level “do not clean or roll back user files” constraint. The compaction-summary bodies are encrypted in the local rollout, so only OpenAI can inspect the complete model-visible pre/post-compaction history.

Approval and remote-boundary concern

The user approved the RC6 build generally. There was no separate confirmation for this recursive deletion command. With approval_policy=never, the SSH tool call executed without an approval prompt.

The local sandbox did not directly delete the guest filesystem; the effect occurred through configured SSH credentials. This means local command safety needs to understand destructive payloads nested inside remote and encoded commands, or the remote worker must enforce its own immutable deletion boundary.

Impact and evidence

  • Visible Windows desktop state changed substantially.
  • Many system files returned access-denied/in-use errors.
  • Exact successful deletion list and recovery rate remain unknown.
  • I am not claiming that the entire VM was deleted.
  • The original rollout, Parallels logs, screenshots, and metadata were preserved.
  • After shutdown, a PVM file-level evidence copy was created and all 20 source-manifest files verified by SHA-256.
  • The VM had already restarted once before preservation, which is an explicit limitation.

Requested engineering changes

  1. Decode and inspect destructive payloads nested in SSH, PowerShell EncodedCommand, and cmd.exe before execution.
  2. Canonicalize the target path on the target OS and bind deletion to an approved directory handle or unique run identity.
  3. Hard-block drive roots, UNC roots, user-profile roots, Desktop, workspace roots, run roots, empty strings, and unresolved variables.
  4. Do not automatically escalate cleanup methods after a lock or access failure.
  5. Require a two-phase dry-run summary with normalized path, count, size, and boundary assertions.
  6. Require a fresh, non-bypassable confirmation for large recursive deletion even in full-access/no-approval modes.
  7. Add an execution-supervisor kill switch when streamed output suddenly shows system-root or out-of-scope paths.
  8. Add negative tests for Bash → SSH → PowerShell → cmd quoting, spaces, trailing slashes, empty variables, current-drive roots, UNC paths, and encoded commands.
  9. Preserve final argv, normalized target, approval decision, and timestamped output for incident review.
  10. After repeated compaction, rehydrate and display the original destructive-operation boundaries before proceeding.

Private evidence references

  • Codex feedback session: 019f82c8-4c41-7f91-ab74-30b3d34c98dc
  • OpenAI Support case: 11849398
  • Security report, if applicable: N/A — no separate security report filed at time of issue creation

Please let me know the safest private channel for the raw JSONL and logs. They contain local paths and will not be attached publicly without further redaction.

View original on GitHub ↗

3 Comments

github-actions[bot] contributor · 1 month ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #33624

Powered by Codex Action

Sxl7939-dot · 1 month ago

Thanks for flagging #33624. I reviewed it. The issues overlap at the defense-in-depth level, but this report is not a duplicate of that incident:

  • #33624 is a general hard-confirmation and recovery-gate proposal based on a separate public Mac/home-directory incident that the reporter did not reproduce.
  • #34512 documents a first-party, preserved Windows incident with a distinct execution path: macOS shell → SSH → PowerShell -EncodedCommandcmd.exe; a failed safer cleanup was automatically escalated; root-level Windows paths appeared in the output; the operation ran for about 59.383 seconds; and the local rollout preserves the approval, compaction, and tool-call timeline.

OpenAI Support case: 11849398.

I am keeping this issue open so maintainers can investigate the specific nested-shell quoting failure, remote-boundary enforcement, final-path/argv validation, and missing output-based automatic stop. I am happy to cross-reference or consolidate if a maintainer requests it.

Sxl7939-dot · 1 month ago

Quantitative forensic update — 2026-07-22

Offline analysis of a derived, read-only working copy of the preserved Windows NTFS virtual disk has now established a confirmed lower bound for the impact described in this issue.

Retained USN evidence

  • The first continuous retained FILE_DELETE burst contains 350,976 unique deletion records:
  • 322,445 file entries
  • 28,531 directory entries
  • All 350,976 paths were reconstructed; 350,971 are under C:\Users\codex.
  • Retained burst: 2026-07-21 14:54:35.891981–14:55:11.251881 (UTC+8).
  • The retained USN journal begins 37.278981 seconds after the dangerous call started. Therefore, 350,976 is a confirmed minimum, not a total-loss estimate; records from the missing initial interval may no longer be available.
  • FILE_DELETE|CLOSE records continued for 13.255881 seconds after the recorded Ctrl-C. This proves continued filesystem activity after Ctrl-C, but USN alone does not identify the responsible process for every record or prove that one process remained actively responsible throughout that interval.

Scope and recovery-candidate metadata

The raw count includes many generated or replaceable artifacts: 332,613 records are under codex-win\runs. Confirmed affected scope also includes:

  • codex-win\work: 6,152 records across named project, review, code-protection validation, and rework workspaces;
  • Desktop: 82 records;
  • Documents: 4 records;
  • Downloads: 2 records.

A focused MFT metadata check covered these 6,240 key-path records:

  • 6,010 currently unallocated MFT records still retain the original deleted name;
  • 230 record slots were reused or no longer retain the original name;
  • 5,425 file records retain logical-size metadata totaling 3,897,486,794 bytes (~3.90 GB).

These are metadata-level recovery candidates only. They do not prove that content clusters are intact, recoverable, or already recovered. I am still not claiming that the entire VM was deleted.

Ten bounded analysis outputs (TSV, JSON, and a forensic conclusion) verified 10/10 OK against their SHA-256 manifest. Detailed path lists and raw evidence remain private pending a secure transfer channel.

OpenAI Support case: 11849398. I have sent the same quantitative update to Support and requested confirmation of server-side record preservation and transfer to Codex engineering/product safety.