Skip to content

fs.stat() and fs.lstat() cannot read the stats of a file with denied permissions on Windows #35853

Description

@aleksey-hoffman
  • Version: 14.5.0
  • Platform: Win10 x64
  • Subsystem: fs

What is the expected behavior?

A similar issue #22577 has been closed 2 years ago, but the issue hasn't been fixed.

Node.js cannot read the stats of immutable files (files with all permissions denied) on Windows. I'm not talking about the contents, just the stats.

Example:

After you deny all permissions to a file (to protect it from being deleted or modified), the default Windows File Explorer can still read the file's stats (name, size, etc) but Node.js throws EPERM: operation not permitted, lstat:

> icacls E:\test.txt /deny *S-1-1-0:(F)

This command effectively denies all modification permissions (delete, rename, write) for Everyone (*S-1-1-0).

What do you see instead?

Windows 10:

> icacls E:\test.txt /deny *S-1-1-0:(D)
> node
> fs.lstatSync('E:\\test.txt')
Uncaught Error: EPERM: operation not permitted, lstat 'E:/test.txt'
    at Object.lstatSync (fs.js:1033:3) {
  errno: -4048,
  syscall: 'lstat',
  code: 'EPERM',
  path: 'E:/test.txt'
}

Linux ubuntu 20.01:

> sudo chattr +i /home/user/Desktop/test.txt
> node
> fs.lstatSync('/home/user/Desktop/test.txt')
Stats {
  dev: 2053,
  mode: 33206,
  nlink: 1,
  uid: 1000,
  gid: 1000,
  rdev: 0,
  blksize: 4096,
  ino: 263860,
  size: 39881,
  blocks: 80,
  atimeMs: 1603884853571.3228,
  mtimeMs: 1602542159686.156,
  ctimeMs: 1603894615058.1975,
  birthtimeMs: 1603842167648.6978,
  atime: 2020-10-28T11:34:13.571Z,
  mtime: 2020-10-12T22:35:59.686Z,
  ctime: 2020-10-28T14:16:55.058Z,
  birthtime: 2020-10-27T23:42:47.649Z 
}

MacOS:

Haven't tested

Activity

  1. mmomtchev commented on Oct 29, 2020

    @mmomtchev
    Contributor

    I am not a Windows expert, but I just noticed that your command will also make a type E:\test.txt fail - which it shouldn't do according to what I understood from its inline help page. So maybe this questions belongs to a Windows forum.
    Otherwise, on Windows, libuv, which implements the lstat, will actually open the file (the infamous Windows CreateFileW call) and it will read the information from the file handle - which is not the only way to get the information on Windows, but it allows for a UNIX-like experience.

  2. peZhmanParsaee commented on Oct 29, 2020

    @peZhmanParsaee
    Contributor

    I succeeded in reading the read-only file stats in Windows 10.

    First, I unset all inherited file permissions, then set file to read-only using these commands:

    C:> icacls E:\test.txt /inheritance:r
    C:> icacls E:\test.txt /grant "everyone":R
    

    It makes our file only readable without any other inherited permissions.

    Then read the file stats using:

    C:> node
    > fs.lstatSync('E:\\test.txt')
    Stats {
      dev: 2553312950,
      mode: 33206,
      nlink: 1,
      uid: 0,
      gid: 0,
      rdev: 0,
      blksize: undefined,
      ino: 1125899909076950,
      size: 0,
      blocks: undefined,
      atimeMs: 1603975767956.215,
      mtimeMs: 1603975767956.215,
      ctimeMs: 1603975807848.567,
      birthtimeMs: 1603974615273.7944,
      atime: 2020-10-29T12:49:27.956Z,
      mtime: 2020-10-29T12:49:27.956Z,
      ctime: 2020-10-29T12:50:07.849Z,
      birthtime: 2020-10-29T12:30:15.274Z }
    
    
  3. aleksey-hoffman commented on Oct 29, 2020

    @aleksey-hoffman
    Author

    @mmomtchev hmm, for me the type /? (help) command says that it allows you to read the contents of a file, but that's not the problem, I only need the attributes (size, path, dates, etc). Even if all permissions are denied, Node.js should still be able to read the attributes (meta data) of the file.

    The default file managers (File Explorer on Windows and Files on Ubuntu) can still read the attributes of a file that has all permissions denied for Everyone (all users, even for the admin).

    I'm specifically trying to remove all permissions from a file for all users to protect it form editing / modification / renaming / deletion. But the problem is, when I do that, Node.js can no longer read the stats of the file on Windows specifically.

    On Ubuntu it works properly - even if all permissions denied for all users (even admin) - Node.js can still read the stats:

    > sudo chattr +i test.txt
    > sudo rm -f test.txt
    rm: cannot remove 'test.txt': Operation not permitted
    > node
    > fs.lstatSync('test.txt')
    Stats {
      dev: 932753616,
      mode: 33206,
      nlink: 1,
      uid: 0,
      gid: 0,
      rdev: 0,
      blksize: 4096,
      ino: 11821949022255224,
      size: 0,
      ...
    }
    
    
  4. aleksey-hoffman commented on Oct 29, 2020

    @aleksey-hoffman
    Author

    @peZhmanParsaee for some reason. your solution doesn't work for me - if I remove all permissions except READ, Node still cannot read the stats on Windows (even though, on Ubuntu it can):

    1. Protect file from modification:

    > icacls E:\test.txt /deny *S-1-1-0:(F)
    

    2. Try to read protected file's stats:

    > node
    > fs.lstatSync('E:\\test.txt')
    Uncaught Error: EPERM: operation not permitted, lstat 'E:/test.txt'
        at Object.lstatSync (fs.js:1033:3) {
      errno: -4048,
      syscall: 'lstat',
      code: 'EPERM',
      path: 'E:/test.txt'
    }
    
    • File Explorer can still read the attributes (size, path, etc.), but Node.js cannot.

    3. Grant read permissions and try to read stats again (same result):

    > icacls E:\test.txt /inheritance:r
    > icacls E:\test.txt /grant *S-1-1-0:R
    > node
    > fs.lstatSync('E:\\test.txt')
    Uncaught Error: EPERM: operation not permitted, lstat 'E:/test.txt'
        at Object.lstatSync (fs.js:1033:3) {
      errno: -4048,
      syscall: 'lstat',
      code: 'EPERM',
      path: 'E:/test.txt'
    }
    

    4. Give the file all permissions back and try to read stats again (only now it can read it):

    > icacls E:\test.txt /grant *S-1-1-0:(F)
    > node
    > fs.lstatSync('E:\\test.txt')
    Stats {
      dev: 932753616,
      mode: 33206,
      nlink: 1,
      uid: 0,
      gid: 0,
      rdev: 0,
      blksize: 4096,
      ino: 11821949022255224,
      size: 0,
      ...
    }
    
  5. added
    fsIssues and PRs related to file-system APIs and the fs module.
    windowsIssues and PRs related to the Windows platform.
    on Dec 27, 2020
  6. aleksey-hoffman commented on Aug 6, 2021

    @aleksey-hoffman
    Author

    @Trott @addaleax @targos Guys can this issue be solved, theoretically? This is a blocking issue in my file manager app.
    Languages like C#, C++ have no problems reading read-only files, surely there's got to be a way to do this in Node, right?

  7. Trott commented on Aug 6, 2021

    @Trott
    Member

    @Trott @addaleax @targos Guys can this issue be solved, theoretically? This is a blocking issue in my file manager app.

    (Not all of us are guys. Consider using everyone, people, friends, folks, or something like that.)

    I imagine this would need to be solved by in libuv.

    Languages like C#, C++ have no problems reading read-only files, surely there's got to be a way to do this in Node, right?

    Short of finding a fix for libuv and having them land it, maybe a native extension using https://nodejs.org/api/n-api.html?

  8. Trott commented on Aug 6, 2021

    @Trott
    Member

    @nodejs/platform-windows @nodejs/libuv

  9. aleksey-hoffman commented on Aug 6, 2021

    @aleksey-hoffman
    Author

    @Trott thanks for the reply. I will open an issue there.
    I might have to resort to creating a custom N-API plugin for this, indeed.

    Not all of us are guys. Consider using everyone, people, friends, folks, or something like that

    Sorry, I thought "guys" was a gender neutral word, I'm not a native English speaker.

  10. aminya commented on Nov 5, 2024

    @aminya

    Is there a workaround? I am hitting the same issue when using Shelljs's rm on Windows to delete some tmp files running on Node 20

    https://github.com/zeromq/zeromq.js/actions/runs/11680287554/job/32522968243

    > zeromq@6.1.1 clean.temp D:\a\zeromq.js\zeromq.js
    > shx rm -rf ./tmp && shx mkdir -p ./tmp
    
    D:\a\zeromq.js\zeromq.js\node_modules\.pnpm\shelljs@0.8.5\node_modules\shelljs\src\common.js:399
            throw e;
            ^
    
    Error [ShellJSInternalError]: EACCES: permission denied, lstat 'D:\a\zeromq.js\zeromq.js\tmp\ipc-5008'​
        at Object.lstatSync (node:fs:1641:25)
        at Object.statNoFollowLinks (D:\a\zeromq.js\zeromq.js\node_modules\.pnpm\shelljs@0.8.5\node_modules\shelljs\src\common.js:290:23)
        at rmdirSyncRecursive (D:\a\zeromq.js\zeromq.js\node_modules\.pnpm\shelljs@0.8.5\node_modules\shelljs\src\rm.js:28:27)
        at handleDirectory (D:\a\zeromq.js\zeromq.js\node_modules\.pnpm\shelljs@0.8.5\node_modules\shelljs\src\rm.js:110:5)
        at D:\a\zeromq.js\zeromq.js\node_modules\.pnpm\shelljs@0.8.5\node_modules\shelljs\src\rm.js:192:7
        at Array.forEach (<anonymous>)
        at _rm (D:\a\zeromq.js\zeromq.js\node_modules\.pnpm\shelljs@0.8.5\node_modules\shelljs\src\rm.js:1[73](https://github.com/zeromq/zeromq.js/actions/runs/11680287554/job/32522968243#step:20:74):9)
        at D:\a\zeromq.js\zeromq.js\node_modules\.pnpm\shelljs@0.8.5\node_modules\shelljs\src\common.js:384:25
        at shx (D:\a\zeromq.js\zeromq.js\node_modules\.pnpm\shx@0.3.4\node_modules\shx\lib\shx.js:132:37)
        at run (D:\a\zeromq.js\zeromq.js\node_modules\.pnpm\shx@0.3.4\node_modules\shx\lib\cli.js:20:31) {
      errno: -4092,
      code: 'EACCES',
      syscall: 'lstat',
      path: 'D:\\a\\zeromq.js\\zeromq.js\\tmp\\ipc-5008'​
    }
  11. huseyinacacak-janea commented on Dec 13, 2024

    @huseyinacacak-janea
    Contributor

    This PR with a fix for this issue landed in libuv. When a new version of libuv is released and merged into Node.js, this issue will be resolved.

  12. Amirali-Amirifar commented on May 4, 2025

    @Amirali-Amirifar

    I guess this must be closed now
    @targos

  13. github-actions commented on Jun 27, 2026

    @github-actions
    Contributor

    This issue has been marked as stale due to 210 days of inactivity.
    It will be automatically closed in 30 days if no further activity occurs. If this is still relevant, please leave a comment or update it to keep it open.

  14. added
    staleIssues and PRs marked stale due to inactivity and scheduled for automatic closure.
    on Jun 27, 2026
  15. github-actions commented on Jul 28, 2026

    @github-actions
    Contributor

    This issue has been automatically closed after 30 days of inactivity following its stale status (no activity for a total of 120 days).
    If this is still relevant, feel free to reopen it or leave a comment with additional details so we can continue the discussion.

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

    fsIssues and PRs related to file-system APIs and the fs module.staleIssues and PRs marked stale due to inactivity and scheduled for automatic closure.windowsIssues and PRs related to the Windows platform.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions