Windows sandbox blocks MSBuild WriteLinesToFile temp *~ files with MSB3491 in elevated and unelevated modes

Open 💬 1 comment Opened Aug 21, 2026 by urnotmiller

What version of the Codex App are you using?

Codex Desktop for Windows 26.818.31338

Bundled CLI:

codex-cli 0.149.0-alpha.4

The CLI also emits:

WARNING: failed to clean up stale arg0 temp dirs: Access is denied. (os error 5)
WARNING: proceeding, even though we could not create PATH aliases: Access is denied. (os error 5)

What platform is your computer?

Microsoft Windows NT 10.0.26200.0 x64

Native Windows Codex Desktop sandbox. Reproduced in both:

[windows]
sandbox = "elevated"

and, after a full Desktop restart:

[windows]
sandbox = "unelevated"

Summary

After updating Codex Desktop, sandboxed MSBuild cannot execute a minimal WriteLinesToFile task against a declared writable workspace. MSBuild fails with MSB3491 while creating/writing its random *~ temporary file in the output directory.

The requested target .cache file is never created, so the failure occurs before replacement/overwrite of the target.

The same deterministic failure occurs under both the elevated and unelevated Windows sandbox implementations.

Minimal reproduction

Use any existing writable directory below the active workspace, represented below as:

D:\workspace\repo\obj\Debug\net10.0

Create a uniquely named project under the current user's system TEMP:

<Project>
  <Target Name="Probe">
    <WriteLinesToFile
      File="D:\workspace\repo\obj\Debug\net10.0\codex-writelines-target-<GUID>.cache"
      Lines="msbuild-probe-content"
      Overwrite="true"
      WriteOnlyWhenDifferent="true" />
  </Target>
</Project>

Run exactly once:

dotnet msbuild "$env:TEMP\codex-writelines-<GUID>.proj" /t:Probe /nologo

Actual behavior

error MSB3491: Failed to write lines to file
"D:\workspace\repo\obj\Debug\net10.0\codex-writelines-target-<GUID>.cache".
Access to the path
'D:\workspace\repo\obj\Debug\net10.0\<random-name>.<random-extension>~'
is denied.

dotnet msbuild ExitCode: 1
Target file: absent

Concrete redacted path shape:

...\obj\Debug\net10.0\ijvhd5q2.lpn~

No solution is loaded, no restore runs, and no source project is referenced.

Expected behavior

WriteLinesToFile should create its temporary file and atomically produce the target inside a declared writable workspace directory. The command should exit 0 in both supported sandbox modes.

Controls and diagnostics

  • The workspace is trusted and advertised as writable.
  • The output directory exists.
  • The directory ACL grants inherited Modify permission to the Codex sandbox group.
  • The existing real AssemblyInfoInputs.cache file is owned by the host user, has only the Archive attribute, and inherits Modify permission.
  • A basic uniquely named .tmp create/read/delete probe previously succeeded in the same directory.
  • The minimal MSBuild target still fails on the random *~ file.
  • At failure time, the requested target .cache file does not exist.
  • Under elevated mode, the process identity is the dedicated CodexSandboxOffline user.
  • Under unelevated mode after a full restart, the process identity is the host Windows user; the failure remains identical.
  • Shutting down MSBuild build servers does not help.
  • Disabling build servers and forcing -m:1 does not help.
  • No ACL modifications are needed for the same repository to build outside the Codex sandbox.

Impact

Normal .NET builds fail during CreateGeneratedAssemblyInfoInputsCacheFile:

Microsoft.NET.GenerateAssemblyInfo.targets(...): error MSB3491
...AssemblyInfoInputs.cache
Access to the path '...\<random>~' is denied.

This prevents Codex Desktop from validating .NET changes in native Windows sandbox mode.

Related issues

  • #34179 — unelevated sandbox starts commands but workspace writes fail
  • #32168 — unelevated sandbox and split writable roots
  • #32184 — Windows App sandbox child-process / Access denied regression

This report is narrower: it provides a standalone MSBuild WriteLinesToFile reproduction and demonstrates that the failure is on the random *~ temporary file before the target exists.

Privacy note

All user names, machine names, and project-specific paths have been redacted. No raw sandbox logs or project contents are attached.

View original on GitHub ↗

1 Comment

urnotmiller · 6 days ago

Update after installing Windows App 26.818.32112 (previously 26.818.31338):

Environment:

  • Windows sandbox: elevated
  • Identity: dedicated CodexSandboxOffline account
  • .NET SDK: 10.0.400

Results under the same elevated sandbox identity:

  1. A minimal MSBuild project containing only WriteLinesToFile succeeded when writing a new unique GUID .cache target.
  2. A second controlled probe also succeeded when the same sandbox identity first created a unique target containing old-content and then WriteLinesToFile replaced it with different content using Overwrite=true and WriteOnlyWhenDifferent=true. Exit code was 0 and the final content was correct.
  3. However, a real solution build still reproduced the original failure on the first and only attempt:

dotnet build .\Solution.sln --no-restore --configuration Debug --disable-build-servers -m:1

Result:

  • Exit code: 1
  • Warnings: 0
  • Errors: 2
  • Both production projects failed in Microsoft.NET.GenerateAssemblyInfo.targets(182,5)
  • Both errors were MSB3491 with Access denied on random *~ temporary files under <repo>\src\<project>\obj\Debug\net10.0
  • The test project did not complete because the solution build stopped on the two production-project errors.

No restore, test, server shutdown, ACL change, cache deletion, or build retry was performed. The worktree remained clean and the unique probe files were cleaned up.

Interpretation: 26.818.32112 appears to improve the isolated minimal cases, including replacement of an existing target created by the same sandbox identity, but it does not fix the real MSBuild solution build. This rules out a simple blanket restriction on new-file creation or existing-target replacement. The remaining difference may involve metadata or provenance of the real cache files, file occupancy/security software, or the full GenerateAssemblyInfo/MSBuild execution context. The issue should remain open.