Skip to content

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

Description

@jonathanlindsay

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions