Windows legacy sandbox can delete files outside writable roots through parent FILE_DELETE_CHILD

Open 💬 0 comments Opened Jul 14, 2026 by jiangshengdev

What issue are you seeing?

The legacy unelevated Windows sandbox can delete files outside the configured writable roots when an existing host parent-directory ACL grants the normal user FILE_DELETE_CHILD.

The same authorization path can also bypass protection for the .git directory or other protected children inside a writable root. In the existing regression test, both the outside file and the protected, empty .git directory are deleted even though the sandbox configuration is intended to deny those operations.

This is a deletion-isolation boundary error. The legacy unelevated backend is still supported, although it is not the default Windows sandbox path.

What steps can reproduce the bug?

  1. Run the existing test in a GitHub Actions job on a free GitHub-hosted Windows x64 runner:

``yaml
runs-on: windows-2025
``

  1. Check out the Codex repository. In the affected fork run, the checkout path was:

``text
D:\a\codex\codex
``

The relevant reproduction precondition is that the checkout tree grants the runner user an inherited parent-directory authorization path that includes FILE_DELETE_CHILD.

  1. From the repository root, run the existing test:

``powershell
just test -p codex-windows-sandbox legacy_workspace_write_delete_is_limited_to_writable_roots
``

  1. Observe that the test fails because the file outside the writable root is deleted and the protected, empty .git directory is removed with rmdir.

The affected GitHub-hosted runner exposed the issue without requiring a custom ACL setup because the checkout tree inherited parent-directory permissions that include FILE_DELETE_CHILD for the runner user. The D: drive letter itself is not the cause; the relevant condition is the effective host ACL on the checkout tree and its parents.

What is the expected behavior?

The deletion boundary of the legacy unelevated Windows sandbox should be determined by the configured writable roots and protected paths, rather than by pre-existing host parent-directory ACLs.

  • An unprotected file inside a writable root should remain deletable.
  • A file outside all writable roots should not be deletable.
  • A protected .git directory should not be removable through a parent directory's FILE_DELETE_CHILD permission.
  • legacy_workspace_write_delete_is_limited_to_writable_roots should pass consistently on the GitHub-hosted windows-2025 x64 runner.

Additional information

Windows can authorize deletion through either of two paths: DELETE on the target object, or FILE_DELETE_CHILD on its parent directory.

The legacy unelevated sandbox restricts permissions associated with its capability SID, but an existing host ACL can independently authorize deletion through the normal user SID. In the affected GitHub-hosted runner checkout, the inherited parent-directory authorization path remained available to the runner user.

As a result:

  • The outside file can be deleted without a writable-root capability ACE because the normal user is authorized through its parent directory.
  • A deny ACE protecting the .git directory for the capability SID does not prevent directory removal authorized independently through the normal user SID and the parent directory.
  • The effective deletion boundary varies with the host ACL instead of being fully enforced by the configured writable roots.

The runner-specific ACL is the condition that exposes the problem; the checkout drive letter is incidental. The failing assertion reflects the intended sandbox boundary rather than a test error. There is currently no evidence from this reproduction that the same authorization path bypasses ordinary read or file-content write restrictions.

View original on GitHub ↗