Context
The documentation scopes sandbox blocking to inter-pip dependency enforcement, and DScript specs are authored by the build's owner, so I'm filing this as a consistency observation rather than a containment claim. In default Windows sandbox mode, the reparse-point policy check inspects only the final path component, so a write issued through a junction created inside a pip's own opaque output directory is policy-checked against the junction's literal path, not the target the bytes actually reach.
Observed behavior (current main, 842e92b)
- Full reparse-point resolving is off by default on Windows:
Public/Src/Utilities/Configuration/Mutable/UnsafeSandboxConfiguration.cs ~L21 (IgnoreFullReparsePointResolving = OperatingSystemHelper.IsWindowsOS) and Public/Src/Utilities/Configuration/UnsafeSandboxConfigurationDefaultExtensions.cs ~L20, ~L42.
- The detours fast path checks only the final component for a reparse attribute in default mode:
Public/Src/Sandbox/Windows/DetoursServices/DetouredFunctions.cpp, ShouldResolveReparsePointsInPath ~L495-512, with the final-component checks around ~L131-137 and ~L3406.
- Opaque output directories grant AllowAll, including write and symlink creation:
Public/Src/Engine/Processes/FileAccessPolicy.cs ~L126 and Public/Src/Engine/ProcessPipExecutor/SandboxedProcessPipExecutor.cs ~L2604-2623.
- Post-run enumeration hashes through junction outputs:
Public/Src/Engine/Scheduler/Artifacts/FileContentManager.cs ~L826-851.
Consequence: a pip can create a junction inside its own opaque output dir and write through it, e.g.
cmd /c mklink /J Out\obj\J <target> && echo x > Out\obj\J\f.txt
The write is checked as an ordinary opaque-scope write even though the bytes land at <target>\f.txt; reads and output hashing follow the junction the same way. A spec that genuinely needs this can already declare it via unsafe.untrackedScopes, so this is audit-clarity rather than new capability — but the Linux sandbox resolves intermediate symlinks by default (Windows opted out for performance; the JavaScript resolver is excepted per JavaScriptResolverSettings.cs ~L23), so the two platforms currently disagree, and on Windows the escape is invisible to spec review.
Suggested direction
- In default mode, resolve intermediate reparse points when the access desires write access under a writable scope.
ShouldResolveReparsePointsInPath already has the policy context, so adding a wants-write condition is a targeted change that avoids the full-resolution performance cost. Alternatively, flip DefaultEnableFullReparsePointResolving on for Windows with the performance caveat documented.
- Additionally or alternatively, treat an actionable reparse point discovered under an opaque output at post-run enumeration as a pip failure, and skip hashing through it.
- Add a default-mode detours test for an undeclared write through an intermediate junction inside an opaque scope. The existing default-mode tests (
Public/Src/Engine/UnitTests/Processes.Detours/PipExecutorDetoursTest.cs ~L7384, ~L7629) cover declared reads; the junction-output tests are currently Skipped (~L3552, ~L3594: "No support for directory junctions as outputs").
Context
The documentation scopes sandbox blocking to inter-pip dependency enforcement, and DScript specs are authored by the build's owner, so I'm filing this as a consistency observation rather than a containment claim. In default Windows sandbox mode, the reparse-point policy check inspects only the final path component, so a write issued through a junction created inside a pip's own opaque output directory is policy-checked against the junction's literal path, not the target the bytes actually reach.
Observed behavior (current main, 842e92b)
Public/Src/Utilities/Configuration/Mutable/UnsafeSandboxConfiguration.cs~L21 (IgnoreFullReparsePointResolving = OperatingSystemHelper.IsWindowsOS) andPublic/Src/Utilities/Configuration/UnsafeSandboxConfigurationDefaultExtensions.cs~L20, ~L42.Public/Src/Sandbox/Windows/DetoursServices/DetouredFunctions.cpp,ShouldResolveReparsePointsInPath~L495-512, with the final-component checks around ~L131-137 and ~L3406.Public/Src/Engine/Processes/FileAccessPolicy.cs~L126 andPublic/Src/Engine/ProcessPipExecutor/SandboxedProcessPipExecutor.cs~L2604-2623.Public/Src/Engine/Scheduler/Artifacts/FileContentManager.cs~L826-851.Consequence: a pip can create a junction inside its own opaque output dir and write through it, e.g.
The write is checked as an ordinary opaque-scope write even though the bytes land at
<target>\f.txt; reads and output hashing follow the junction the same way. A spec that genuinely needs this can already declare it viaunsafe.untrackedScopes, so this is audit-clarity rather than new capability — but the Linux sandbox resolves intermediate symlinks by default (Windows opted out for performance; the JavaScript resolver is excepted perJavaScriptResolverSettings.cs~L23), so the two platforms currently disagree, and on Windows the escape is invisible to spec review.Suggested direction
ShouldResolveReparsePointsInPathalready has the policy context, so adding a wants-write condition is a targeted change that avoids the full-resolution performance cost. Alternatively, flipDefaultEnableFullReparsePointResolvingon for Windows with the performance caveat documented.Public/Src/Engine/UnitTests/Processes.Detours/PipExecutorDetoursTest.cs~L7384, ~L7629) cover declared reads; the junction-output tests are currently Skipped (~L3552, ~L3594: "No support for directory junctions as outputs").