#66375·Node.js

Windows AppContainer: realpath fails (native lookup refused with error 5; JS walk refused at `lstat 'C:\Users'`)

Author: jonathanlindsayCreated Sep 28, 2026Updated Sep 28, 2026

Problem

Inside a Windows AppContainer, node cannot resolve the real path of a file the process is allowed to open:

  • The native real-path lookup is refused with error 5.
  • The JavaScript fallback, fs.realpathSync / fs.realpath, walks every folder from the drive root with lstat and is refused at lstat 'C:\Users'.

(Measured in our Windows testing, 27 and 28 September 2026. Microsoft does not document this behaviour.)

With no workaround in place, the walk was first refused one step earlier, at lstat 'C:\'. With a preload that answers the drive root, it gets past that and is refused at lstat 'C:\Users'.

The CJS and ESM loaders use the JavaScript walk to resolve the main script and every module (toRealPath in lib/internal/modules/helpers.js; lib/internal/modules/run_main.js:38-41 on v24.x) unless --preserve-symlinks-main / --preserve-symlinks are given. An AppContainer is normally granted the folders it needs, not their ancestors, so node fails before any user code runs.

Minimal reproduction

  1. Put main.js in a folder under C:\Users\<user>\... and grant the AppContainer read access to that folder only.
  2. Inside the container, run node main.js. Observed: EPERM on lstat 'C:\Users'.
  3. Inside the container, call fs.realpathSync.native on the same path. Observed: error 5.

Expected behaviour

Resolving a path the process can open does not require read access to its ancestors, or it fails with a clear error that names the folder and the workaround.

Proposed fix

  • node: in fs.realpathSync / fs.realpath on Windows, when lstat of an ancestor fails with EPERM/EACCES, do not fail the whole resolution; for example, treat an unreadable ancestor as not a link. Node already special-cases the root (getRealpathRootLstatPath).
  • libuv (uv_fs_realpath, src/win/fs.c): we have not isolated whether error 5 comes from the CreateFileW open or from GetFinalPathNameByHandleW(VOLUME_NAME_DOS). We can run a probe if maintainers name the call they want checked.

Why it matters

Every node program run inside an AppContainer fails at startup unless it is launched with flags most users do not know about. Windows edge cases already shaped this code: v6.4.0 (#7899) restored the JavaScript walk, and fs.realpathSync.native was added in v9.2.0.