Sandbox breaks workdir on Windows

Open 💬 2 comments Opened May 7, 2026 by MartinKolarik
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

What version of Codex CLI is running?

0.129.0

What subscription do you have?

pro

Which model were you using?

gpt-5.5

What platform is your computer?

Microsoft Windows NT 10.0.26200.0 x64

What terminal emulator and version are you using (if applicable)?

Windows Terminal with PowerShell

What issue are you seeing?

Running with the default permissions mode, codex's CWD gets somehow messed up, and it runs commands directly in C:\ despite reporting the correct directory after starting. When the exact same session is repeated in --yolo mode, commands run in the correct directory.

Codex usually retries the commands by passing the directory as a parameter, but this also seems to mess up the permissions checks, so every single command invocation (git, npm, etc.) then requires approval despite staying in the original workdir.

Uploaded thread: 019e04a2-5458-7c41-98b4-2482fce3c544

What steps can reproduce the bug?

> list files in the current directory

• Ran Get-ChildItem
  └
        Directory: C:\
    … +27 lines (ctrl + t to view transcript)
• Get-ChildItem listed C:\, not C:\[...redacted...], despite the requested working directory.

What is the expected behavior?

It lists files in the project directory.

Additional information

_No response_

View original on GitHub ↗

2 Comments

github-actions[bot] contributor · 3 months ago

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

  • #20858

Powered by Codex Action

h3har · 1 month ago

I am seeing the same behavior with a newer Codex build and was able to narrow it down to a mismatch between the native process working directory and Windows PowerShell's filesystem-provider location.

Environment

  • Codex Desktop: 26.721.4979.0
  • Bundled Codex CLI: 0.146.0-alpha.3.1
  • Windows: Microsoft Windows NT 10.0.26200.0, x64
  • Windows PowerShell: 5.1.26100.8875
  • Workspace and repository are on C:
  • The repository is configured as trusted.
  • Windows sandbox configuration:

``toml
[windows]
sandbox = "elevated"
``

The native CWD is correct, but PowerShell's location is C:\

With the repository explicitly supplied as the command workdir, I ran:

Write-Output ('PowerShell location: ' + (Get-Location).Path)
Write-Output ('Process directory: ' + [Environment]::CurrentDirectory)

The result was (with directories renamed for privacy):

PowerShell location: C:\
Process directory: C:\parent\child\grandchild

For comparison:

| Execution path | Result |
|---|---|
| Sandboxed PowerShell: (Get-Location).Path | C:\ |
| Sandboxed PowerShell: [Environment]::CurrentDirectory | Correct repository |
| Sandboxed cmd.exe: cd | Correct repository |
| PowerShell outside the sandbox | Both values are the correct repository |

This indicates that Codex is not simply dropping the requested OS-level CWD. The divergence occurs when PowerShell initializes its filesystem-provider location.

Set-Location exposes an inaccessible ancestor

An explicit:

Set-Location -LiteralPath 'C:\parent\child\grandchild'

failed with UnauthorizedAccessException. The relevant stack was:

System.Management.Automation.Utils.NativeFileExists
Microsoft.PowerShell.Commands.FileSystemProvider.GetFileSystemInfo
Microsoft.PowerShell.Commands.FileSystemProvider.NormalizeThePath
Microsoft.PowerShell.Commands.FileSystemProvider.NormalizeRelativePath
Set-Location: Access is denied

Testing the individual components under the same sandbox token produced:

C:\parent                     OK
C:\parent\child               Access denied
C:\parent\child\grandchild    OK

Absolute-path reads and writes inside grandchild still worked. This is a valid Windows ACL arrangement: the sandbox can have an explicit allow ACE on the leaf workspace and use bypass-traverse semantics without being able to inspect an intermediate directory. PowerShell's path normalization is stricter because it probes the individual components.

This also explains why PowerShell can silently retain C:\ even though CreateProcessAsUserW received the correct working directory.

Relevant source path

At the matching source tag:

  1. Codex passes the selected CWD to CreateProcessAsUserW: process.rs.
  2. The workspace CWD is added as a read root, but its ancestors are not: setup.rs.
  3. Read ACLs are applied to each supplied root: setup_main/win.rs.
  4. The command runner uses a CWD junction only while the read-ACL helper mutex exists. After the helper exits, it returns to the requested path: command_runner/win.rs.
  5. The junction root is derived from the command runner's %USERPROFILE%: cwd_junction.rs.

The timing-dependent junction selection may also help explain why this is only noticed on some occasions or environments.

Existing commits appear related but incomplete

I found two existing unmerged commits associated with this issue:

  • 8679dff2ee changes the junction root from %USERPROFILE% to the provisioned sandbox home.
  • 2811530a96 launches the command runner itself from a stable sandbox directory instead of the workspace.

Both changes look useful, but neither appears to address the post-helper path above: once effective_cwd() stops using the junction, PowerShell can still reject the real workspace path while normalizing an inaccessible ancestor. The relevant code is also unchanged between this tag and current main.

A complete fix may need to keep using a junction when the real CWD is not PowerShell-provider-accessible, based on an accessibility probe rather than only the read-ACL-helper mutex. Using a junction under the provisioned sandbox home would avoid broadly granting directory-listing access to workspace ancestors. Alternatively, the ACL setup would need to grant the minimum ancestor access required by PowerShell normalization, with the security implications considered.

This appears to be the same underlying app-visible symptom as #20858.