fix(codex): trust extended-length resume paths - #10337
Conversation
📝 WalkthroughWalkthroughThe change adds trusted normalization for Windows extended-length and device-style paths before Codex rollout containment checks. Tests cover accepted extended-length paths, unsafe namespace paths, missing or non-regular files, compressed rollouts, scan filtering, and prevention of fallback session scanning. The PTY connection persistence test now includes a Windows extended-length transcript path in stored provider session data and the expected resume request. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Taking a look! |
|
Reviewed on real Windows 11 + WSL. The approach is right and I didn't change it: folding only the strict Why it's safe: the relative path is slash-folded before (Correcting an earlier version of this comment: I first argued the safety came from Verified by executing it on Windows, not by reading it
What I pushed
I also checked the four tests this PR already added: the positive one fails on revert, and each of the three rejection tests is caught by a distinct plausible mis-implementation of the helper. None are vacuous. Deliberately left alone
Known gaps / suggested follow-ups
Nice fix — the containment reasoning and the fail-closed handling of the other namespaces were already right, which made this easy to verify. Ready to merge from my side — scope unchanged (3 files, production change still the one helper), CI green on |
Greptile SummaryThis PR fixes Codex cold resume on Windows when a persisted rollout uses the extended-length path spelling
Confidence Score: 5/5Safe to merge — the change is narrowly scoped to path comparison logic in the Codex resume provenance check, does not touch file I/O paths or returned values, and all rejection invariants are preserved and tested. The production change is a single, well-contained helper that strips the Win32 extended-drive prefix only for the containment comparison, with no effect on POSIX paths. The regex correctly rejects every non-drive \?\ form and the \. device namespace. ADS blocking is sound via the [^/:] character class in the trusted tail regex. File probing and the returned transcript path continue to use the original spelling. The test suite covers every relevant rejection and acceptance branch, including the scan code path and fail-closed provenance behaviour. Files Needing Attention: No files require special attention.
|
| Filename | Overview |
|---|---|
| src/main/codex/codex-session-resume-home.ts | Adds toCodexTrustedPathComparisonCopy to strip the extended-length prefix from drive paths for comparison only; correctly rejects device namespaces and non-drive extended paths; splits rollout tail regex into claimed vs trusted variants to block ADS paths in provenance checks while preserving the original path for file I/O and the returned transcript value. |
| src/main/codex/codex-session-resume-home.test.ts | Adds comprehensive regression coverage for extended-length path acceptance, original path preservation, ADS/namespace/traversal rejection before file probing, fail-closed provenance, and the scan path. |
| src/main/codex/codex-session-resume-windows.test.ts | New Windows-native integration test exercising the full prepareCodexSessionResume path with a real filesystem and toNamespacedPath; gated behind process.platform === 'win32' so it is a no-op on POSIX CI. |
| src/renderer/src/components/terminal-pane/pty-connection.test.ts | Updates the sleeping-Codex cold-resume test to carry an extended-length transcriptPath in the providerSession, verifying the path is forwarded intact through the resume flow to transport.connect. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[persistedPath from sleeping session] --> B{toCodexTrustedPathComparisonCopy}
B -->|starts with device namespace| C[return null - reject]
B -->|starts with extended prefix| D{matches drive-letter regex?}
D -->|No - GLOBALROOT / Volume / UNC| E[return null - reject]
D -->|Yes| F[strip prefix to ordinary drive path]
B -->|ordinary path| G[return unchanged]
F --> H[relativePathInsideRoot on comparison copies]
G --> H
H -->|not inside sessions root| I[reject - no file probe]
H -->|inside sessions root| J{ROLLOUT_RELATIVE_PATH regex}
J -->|fails - ADS colon / traversal / wrong layout| I
J -->|passes| K[resolveExistingRolloutPath on ORIGINAL path]
K -->|file missing or non-regular| I
K -->|file exists| L[return homePath + original transcriptPath]
Reviews (2): Last reviewed commit: "fix(codex): preserve resume provenance g..." | Re-trigger Greptile
The provenance fix folds the extended drive spelling on the rollout path and the trusted sessions root, and runs per entry in the legacy id scan. Only the rollout-path side had coverage, so pin the rest: - normal-form rollout under an extended-length trusted home (root side) - compressed .zst sibling derived from an extended-length persisted path, where a folded comparison copy could leak into the returned path - legacy id-scan entries: extended-length accepted, device namespace refused All three fail with the production change reverted.
The helper's comment called the rejected spellings "arbitrary device namespaces", but \?\UNC\ is the extended-length form of \server\share\ — a network share, not a device. Reading it as a security decision hides that UNC is simply not folded yet, so say what is actually excluded. Also trim the two new test comments to one line to match the file.
0bdaa79 to
b03c967
Compare
Summary
Fix Codex cold resume on Windows when a persisted rollout uses the extended-length spelling
\\?\C:\...but its trusted Codex home uses the equivalentC:\...spelling.The provenance check now creates a comparison-only copy for strict extended drive paths. File probing and the returned transcript path still use the original path. Other Win32 device namespaces remain rejected.
The final factory stack also preserves the newer fail-closed provenance guard: broad Codex-layout recognition remains separate from the stricter trusted-rollout grammar, so ADS-shaped rollout paths are reported as rejected Codex provenance but cannot become trusted resume sources.
Screenshots
No visual change.
Testing
pnpm lint(full-repository lint not run; changed-file oxlint and max-lines passed)pnpm typecheck(full multi-target typecheck not run; node typecheck passed)pnpm test(full suite not run; decisive focused suites and headed E2E passed)pnpm build(production build not run; both headed lanes rebuilt in E2E mode)pnpm typecheck:nodeoxfmt --checkandoxlintnode config/scripts/check-max-lines-ratchet.mjsgit diff --check\\?\C:\...rollout resumed after daemon death/restart and the provider session ID was visible in the terminalThe broader resolver/preparation run still has 11 native-Windows failures from inherited POSIX-path fixtures; the same failures reproduce unchanged on pristine
main. All decisive extended-path, ADS/device rejection, real-file, argv-drop, IPC fail-closed, and renderer resume cases pass.AI Review Report
Reviewed the complete four-file diff for ownership, security, performance, cleanup, native Windows behavior, SSH and folder-workspace neutrality, provider scope, and Git 2.25 compatibility. The Codex provenance resolver is the authoritative owner: the comparison fold belongs at the trust boundary, not in global path normalization or renderer/session transport.
The change adds no scanning, commands, IPC, network access, dependencies, or production file mutation. Non-namespace paths are returned unchanged, so macOS/Linux, SSH, remote runtimes, folder workspaces, and Git worktrees keep their existing behavior. No Git command or provider-review behavior changes.
Security Audit
Only strict
\\?\<drive>:\...paths can lose the prefix for containment comparison.\\.\...,\\?\GLOBALROOT\..., UNC/volume/device namespaces, different roots, traversal, invalid rollout layouts, ADS-shaped filenames, and missing/non-regular files remain rejected. Rejected originating provenance cannot fall back to scanning another home, and the original transcript path is retained for the regular-file check and resume result.No workflow, action, package manifest, lockfile, dependency, download, credential, or permission surface changed.
Notes
Windows-specific fix; no behavior change is intended on macOS or Linux.
\\?\UNC\...remains intentionally unsupported at this boundary. The headed test uses a hermetic command stub rather than an authenticated Codex CLI, while exercising the real Electron persistence, daemon termination, restart, trust, and user-visible terminal path.X (Twitter) handle: N/A
ELI5
Windows can spell the same local file as both
C:\...and\\?\C:\.... Orca now compares those spellings as the same trusted Codex rollout without weakening the checks that reject device paths, network namespaces, or alternate data streams.