You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Summary
On the windows-acl sandbox backend (workspace-write mode), a confined process that creates a directory with Python's tempfile.mkdtemp() cannot write files inside that directory, even though the directory was created by the process itself. The same operation succeeds with os.makedirs(), and everything works under danger-full-access.
This breaks any test suite or tooling that relies on tempfile.TemporaryDirectory / mkdtemp (e.g. unittest's TemporaryDirectory) when running inside the DSH sandbox: every such test fails with PermissionError [WinError 5].
Environment
OS: Windows 10 (build 26200)
DSH: developer preview, latest master (apps/cli run via node --import tsx/esm apps/cli/src/bin.ts web)
Sandbox backend: windows-acl (ACL restricted-token runner), mode workspace-write
Python: 3.14
Shell: PowerShell 7.6 (via the pwsh tool)
Reproduction
Minimal repro inside a confined workspace-write pwsh:
import tempfile, os
d = tempfile.mkdtemp(prefix="probe-")
print("created:", d)
with open(os.path.join(d, "x.txt"), "w") as f:
f.write("hi")
Interesting details observed during the investigation:
os.makedirs(...) then writing into it succeeds in the same confined process.
On the failing mkdtemp directory, even icacls reports Access is denied — the confined process cannot read the ACL of a directory it just created.
The sandbox runner rewrites TMP/TEMP for the child to the private sandbox directory %TEMP%\dsh-* (sandbox-windows-acl/src/runner.ts), so any standard-library temp usage lands there.
Expected behavior
A confined workspace-write process should be able to create a directory (via mkdtemp or otherwise) under the granted temp area and write into it, since that is exactly the temp area the sandbox itself assigns.
Root cause (as far as I can tell)
The windows-acl backend grants write access through capability-SID ACEs that rely on DACL inheritance:
The workspace and the private temp dir carry an ACE like S-1-4-...:(OI)(CI)(W,D,DC) for a capability SID included in the restricted token's restricting list.
New objects created by the confined process must therefore inherit that ACE to be writable by the same process.
token.ts's setTokenDefaultDaclGrant merges a full-access ACE into the token's default DACL, but that only covers objects created without an explicit security descriptor (e.g. anonymous pipes). The comment in the code explicitly scopes it to "a new anonymous pipe (child stdio)".
Python's tempfile.mkdtemp() on Windows creates the directory with an explicit security descriptor, which means the new directory's DACL does not inherit the parent's capability-SID ACE. The result is a directory whose DACL names only the user's ambient SIDs — the confined process (whose token is restricted) cannot access it, not even to read its ACL.
Suggested fix
Option A (sandbox side): when materializing the temp grant, also make the capability ACE inheritable onto objects created with explicit security descriptors — e.g. by also merging an inheritable ACE into the token's default DACL with (OI)(CI) flags, or by re-applying the DACL on new child directories under the private temp root.
Option B (documentation): at minimum, document this limitation for the windows-acl backend and advise Python users to avoid mkdtemp inside the sandbox (or to re-DACL created temp dirs).
Workaround I'm currently using
A sitecustomize.py in the project that detects the DSH sandbox (via tempfile.gettempdir() containing dsh-) and replaces tempfile.mkdtemp with an os.makedirs-based implementation, which inherits the ACL correctly. Happy to share the full patch if useful.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Summary
On the windows-acl sandbox backend (workspace-write mode), a confined process that creates a directory with Python's tempfile.mkdtemp() cannot write files inside that directory, even though the directory was created by the process itself. The same operation succeeds with os.makedirs(), and everything works under danger-full-access.
This breaks any test suite or tooling that relies on tempfile.TemporaryDirectory / mkdtemp (e.g. unittest's TemporaryDirectory) when running inside the DSH sandbox: every such test fails with PermissionError [WinError 5].
Environment
OS: Windows 10 (build 26200)
DSH: developer preview, latest master (apps/cli run via node --import tsx/esm apps/cli/src/bin.ts web)
Sandbox backend: windows-acl (ACL restricted-token runner), mode workspace-write
Python: 3.14
Shell: PowerShell 7.6 (via the pwsh tool)
Reproduction
Minimal repro inside a confined workspace-write pwsh:
import tempfile, os
d = tempfile.mkdtemp(prefix="probe-")
print("created:", d)
with open(os.path.join(d, "x.txt"), "w") as f:
f.write("hi")
Result:
PermissionError: [Errno 13] Permission denied: 'D:\Temp\dsh-XXX\probe-....\x.txt'
Interesting details observed during the investigation:
Expected behavior
A confined workspace-write process should be able to create a directory (via mkdtemp or otherwise) under the granted temp area and write into it, since that is exactly the temp area the sandbox itself assigns.
Root cause (as far as I can tell)
The windows-acl backend grants write access through capability-SID ACEs that rely on DACL inheritance:
The workspace and the private temp dir carry an ACE like S-1-4-...:(OI)(CI)(W,D,DC) for a capability SID included in the restricted token's restricting list.
New objects created by the confined process must therefore inherit that ACE to be writable by the same process.
token.ts's setTokenDefaultDaclGrant merges a full-access ACE into the token's default DACL, but that only covers objects created without an explicit security descriptor (e.g. anonymous pipes). The comment in the code explicitly scopes it to "a new anonymous pipe (child stdio)".
Python's tempfile.mkdtemp() on Windows creates the directory with an explicit security descriptor, which means the new directory's DACL does not inherit the parent's capability-SID ACE. The result is a directory whose DACL names only the user's ambient SIDs — the confined process (whose token is restricted) cannot access it, not even to read its ACL.
Confirmed by ACL comparison:
makedirs-created dir: S-1-4-68446650-...:(I)(OI)(CI)(W,D,DC) <- capability SID inherited, writable
mkdtemp-created dir: icacls -> "Access is denied" <- capability SID lost, unwritable
Suggested fix
Option A (sandbox side): when materializing the temp grant, also make the capability ACE inheritable onto objects created with explicit security descriptors — e.g. by also merging an inheritable ACE into the token's default DACL with (OI)(CI) flags, or by re-applying the DACL on new child directories under the private temp root.
Option B (documentation): at minimum, document this limitation for the windows-acl backend and advise Python users to avoid mkdtemp inside the sandbox (or to re-DACL created temp dirs).
Workaround I'm currently using
A sitecustomize.py in the project that detects the DSH sandbox (via tempfile.gettempdir() containing dsh-) and replaces tempfile.mkdtemp with an os.makedirs-based implementation, which inherits the ACL correctly. Happy to share the full patch if useful.
All reactions