Relevant area(s)
Windows
Brief description of your issue
Under the tier 1 BaseContainer runner, a sandboxed process cannot translate an NT path back to a drive-letter path. GetFinalPathNameByHandleW fails with ERROR_ACCESS_DENIED (5) for every VOLUME_NAME_DOS request, on a handle the process just opened successfully, while the same call with VOLUME_NAME_NT succeeds. GetVolumeNameForVolumeMountPointW("C:\\") is refused too. So the Mount Manager seems to be out of reach from the container, and the NT→DOS translation needs it.
No filesystem policy changes this: it fails with the working directory inside readwritePaths, and also with C:\ itself in readonlyPaths.
Ordinary developer tools depend on this call:
- Node.js:
fs.realpathSync.native / fs.promises.realpath (libuv uv_fs_realpath) fail with EPERM on any path, the cwd included. npm and many CLIs resolve paths this way.
- Git for Windows (native
mingw64\bin\git.exe): mingw_getcwd calls GetFinalPathNameByHandleW, then falls back to GetLongPathNameW. That fallback has to list every ancestor folder by name, so every command that needs the work tree (init, status, rev-parse, ...) dies with fatal: unable to get current working directory: Permission denied unless the drive root is readable. Making C:\ readable means falling back to a deny list of everything beside the project, which defeats an allow-only policy.
git --version, cmd, PowerShell and NUL all work under tier 1, so this looks like the last thing between tier 1 and a usable git-based workflow.
Environment:
- Windows 11 Home 24H2, build 26100.9457, x64
@microsoft/mxc-sdk 1.0.0, wxc-exec.exe (x64); --debug shows selected isolation tier: base-container, runner BaseContainer
- Node 26.4.0, Git for Windows 2.45.1
- Run from the interactive console session
Steps to reproduce
- Make a working folder, e.g.
C:\mxc-lab\app.
- Config (
ui.disable: false so that console tools start):
{
"version": "1.0.0",
"containment": "processcontainer",
"process": {
"commandLine": "node -e \"console.log(require('fs').realpathSync.native('.'))\"",
"cwd": "C:\\mxc-lab\\app",
"timeout": 30000
},
"filesystem": { "readwritePaths": ["C:\\mxc-lab\\app"] },
"ui": { "disable": false }
}
wxc-exec.exe config.json
- Same config with
"commandLine": "git init -q repo".
- To isolate the call, a small probe that calls
GetFinalPathNameByHandleW with each flag, GetLongPathNameW and GetVolumeNameForVolumeMountPointW on the cwd: https://github.com/laurentftech/pi-outpost/blob/feat/confined-terminal/scripts/probes/path-apis.cs (csc.exe from .NET Framework builds it; no SDK needed).
Expected behavior
realpathSync.native('.') prints C:\mxc-lab\app, git init creates the repository, and GetFinalPathNameByHandleW(h, ..., VOLUME_NAME_DOS) returns \\?\C:\mxc-lab\app, as it does outside the container. Resolving a path the process may already open should not need any extra grant.
Actual behavior
node realpath.native EPERM: operation not permitted, realpath 'C:\mxc-lab\app'
git init fatal: unable to get current working directory: Permission denied
(it leaves an empty `repo` folder behind)
path-apis.exe inside the container, cwd C:\mxc-lab\app:
GetVolumeNameForVolumeMountPointW(C:\) ERROR 5
GetLongPathNameW ERROR 5 (OK once C:\ is in readonlyPaths)
CreateFileW(access=0, BACKUP_SEMANTICS) OK
GetFinalPathNameByHandleW(normalized, DOS) ERROR 5
GetFinalPathNameByHandleW(opened, DOS) ERROR 5
GetFinalPathNameByHandleW(normalized, NT) OK \Device\HarddiskVolume3\mxc-lab\app
GetFinalPathNameByHandleW(opened, NT) OK \Device\HarddiskVolume3\mxc-lab\app
Outside the container, every line succeeds. With C:\ added to readonlyPaths, the DOS variants still fail. Only git starts working, through its GetLongPathNameW fallback.
Related: #1061 (MSYS2 runtimes); this one affects native, non-MSYS tools.
Relevant area(s)
Windows
Brief description of your issue
Under the tier 1
BaseContainerrunner, a sandboxed process cannot translate an NT path back to a drive-letter path.GetFinalPathNameByHandleWfails withERROR_ACCESS_DENIED(5) for everyVOLUME_NAME_DOSrequest, on a handle the process just opened successfully, while the same call withVOLUME_NAME_NTsucceeds.GetVolumeNameForVolumeMountPointW("C:\\")is refused too. So the Mount Manager seems to be out of reach from the container, and the NT→DOS translation needs it.No filesystem policy changes this: it fails with the working directory inside
readwritePaths, and also withC:\itself inreadonlyPaths.Ordinary developer tools depend on this call:
fs.realpathSync.native/fs.promises.realpath(libuvuv_fs_realpath) fail withEPERMon any path, the cwd included. npm and many CLIs resolve paths this way.mingw64\bin\git.exe):mingw_getcwdcallsGetFinalPathNameByHandleW, then falls back toGetLongPathNameW. That fallback has to list every ancestor folder by name, so every command that needs the work tree (init,status,rev-parse, ...) dies withfatal: unable to get current working directory: Permission deniedunless the drive root is readable. MakingC:\readable means falling back to a deny list of everything beside the project, which defeats an allow-only policy.git --version,cmd, PowerShell and NUL all work under tier 1, so this looks like the last thing between tier 1 and a usable git-based workflow.Environment:
@microsoft/mxc-sdk1.0.0,wxc-exec.exe(x64);--debugshowsselected isolation tier: base-container, runnerBaseContainerSteps to reproduce
C:\mxc-lab\app.ui.disable: falseso that console tools start):{ "version": "1.0.0", "containment": "processcontainer", "process": { "commandLine": "node -e \"console.log(require('fs').realpathSync.native('.'))\"", "cwd": "C:\\mxc-lab\\app", "timeout": 30000 }, "filesystem": { "readwritePaths": ["C:\\mxc-lab\\app"] }, "ui": { "disable": false } }wxc-exec.exe config.json"commandLine": "git init -q repo".GetFinalPathNameByHandleWwith each flag,GetLongPathNameWandGetVolumeNameForVolumeMountPointWon the cwd: https://github.com/laurentftech/pi-outpost/blob/feat/confined-terminal/scripts/probes/path-apis.cs (csc.exefrom .NET Framework builds it; no SDK needed).Expected behavior
realpathSync.native('.')printsC:\mxc-lab\app,git initcreates the repository, andGetFinalPathNameByHandleW(h, ..., VOLUME_NAME_DOS)returns\\?\C:\mxc-lab\app, as it does outside the container. Resolving a path the process may already open should not need any extra grant.Actual behavior
path-apis.exeinside the container, cwdC:\mxc-lab\app:Outside the container, every line succeeds. With
C:\added toreadonlyPaths, the DOS variants still fail. Only git starts working, through itsGetLongPathNameWfallback.Related: #1061 (MSYS2 runtimes); this one affects native, non-MSYS tools.