Repository navigation
fs.copyFile on Mac OS does not respect permissions #26936
Description
Activity
I'm able to replicate this bug on Mojave. Seems like libuv is somehow running
copyfile()withCOPYFILE_UNLINKset or else there's a bug in macOS? @nodejs/fs @nodejs/libuv @nodejs/platform-macos- addedconfirmed-bugIssues and PRs for confirmed bugs.Issues and PRs for confirmed bugs.fsIssues and PRs related to file-system APIs and the fs module.Issues and PRs related to file-system APIs and the fs module.libuvIssues and PRs related to the libuv dependency or the uv binding.Issues and PRs related to the libuv dependency or the uv binding.macosIssues and PRs related to the macOS platform.Issues and PRs related to the macOS platform.
on Mar 27, 2019 Confirmed with Node.js 8.x, 10.x, 11.x, and current master branch. (
fs.copyFile()does not exist in Node.js 6.x.)I tried adding this to libuv's
fs.cfile and recompiling but it didn't change anything...// Turn off unlinking of the destination file. // Refs: https://github.com/nodejs/node/issues/26936 flags &= ~(1 << 21); /* COPYFILE_UNLINK */
(Of course, it's entirely likely I'm doing the bit math wrong or something simple like that.....)
I'm able to replicate this bug on Mojave. Seems like libuv is somehow running
copyfile()withCOPYFILE_UNLINKset or else there's a bug in macOS? @nodejs/fs @nodejs/libuv @nodejs/platform-macosI'm not a macOS person, but being able to bypass file permissions sounds like an OS bug.
This seems to be related to permissions and probably not a bug we can control. I'm also seeing no error by default, but if I run with
sudo -u nobodythen I get anEPERMerror.I'm not a macOS person, but being able to bypass file permissions sounds like an OS bug.
Yeah, definitely agree after playing around with different
copyfile()flags inside libuv. Astonishingly, it seems thatcopyfile(3)on macOS does not respect file permissions. We can't be the first people to ever experience this, though... 🤔libuv'sfs.chas Apple-specific code foruv__fs_copyfile()added by @cjihrig in libuv/libuv#1465. Do you know if there was a reason other than "use analogous native functionality when you can" for using different code for macOS? Removing it all and using the code used by other UNIX-like operating systems fixes this problem.nodecontinues to pass all tests too. So maybe that's the way to go?Reacted by Sakthipriyan Vairamani and Ruben Bridgewater- added a commit that references this issue
on Mar 27, 2019 - Reacted by Aziz Khoury
- added a commit that references this issue
on Mar 27, 2019 I had recently noticed this behavior divergence also, as it can occur in the context of symlinks (hard or soft): libuv/libuv#2199 (comment). Turning that into an issue has been on my TODO list (and providing analysis on what it seems like it should do), but I think this should already address it.
I was actually a bit surprised by that the proposed behavior here is the desired choice, since it means that a
copymay end up with different attributes from the original file, and it uses either the permissions of the hardlink or of the containing directory, if the destination didn't exist at the time. The result is not necessarily more nor less restrictive, just different.But it seems that what libuv does on unix is the explicit choice for the C++17 standard for
std::filesystem::copy_fileand is also what unixcpappears to do. So that seems like a good track record to follow. By contrast,cp -fbehaves either like "unix" (if the dest file could be opened for write) or like "macos" (if the dest file could not).Shell test script:
echo 1 > file1 echo 2 > file2 ln file1 file_link # optional: chmod a-w file1 cp file2 file_link # or cp -f cat file1 # prints 2- added a commit that references this issue
on Mar 30, 2019 - added 2 commits that reference this issue
on Apr 5, 2019 - added a commit that references this issue
on Apr 11, 2019 This was fixed by #27241.
- added 2 commits that reference this issue
on May 16, 2019 - added a commit that references this issue
on Jul 23, 2025 - added a commit that references this issue
on Dec 16, 2025
v11.2.0Darwin iMac.local 18.2.0 Darwin Kernel Version 18.2.0: Thu Dec 20 20:46:53 PST 2018; root:xnu-4903.241.1~1/RELEASE_X86_64 x86_64When setting a file mode to
444usingchmodSync, then trying to copy another file over it, on Windows and on Linux,copyFilewill throw an error, but on a Mac it does not, and it will override the filei even check the
stat.modeusingparseInt(fs.statSync(dest).mode.toString(8), 10)and it does in fact say100444This is a sample when everything is working well
https://repl.it/repls/CylindricalGlisteningCondition
However, when i run it on my mac, I get this
Thanks