Nixpkgs version
Describe the bug
On Darwin, gavin-bc 7.1.0 installs the bin/dc symlink with mode 0700.
For a package installed in the Nix store, the resulting symlink is owned by root:wheel:
lrwx------ root wheel ... /nix/store/...-gavin-bc-7.1.0/bin/dc -> bc
As a result, non-root users cannot read the symlink:
$ readlink /nix/store/...-gavin-bc-7.1.0/bin/dc
readlink: /nix/store/...-gavin-bc-7.1.0/bin/dc: Permission denied
while reading it as root works correctly:
$ sudo readlink /nix/store/...-gavin-bc-7.1.0/bin/dc
bc
This also breaks Nix operations that need to serialize the store path. For example, nix copy fails when it reaches gavin-bc:
error: reading symbolic link "/nix/store/...-gavin-bc-7.1.0/bin/dc": Permission denied
Other store paths in the same closure can be serialized and copied normally.
The dc -> bc symlink itself is correct. The problem is specifically its mode on Darwin.
Steps to reproduce
-
On macOS, build gavin-bc:
nix build nixpkgs#gavin-bc
-
Inspect the dc symlink:
The symlink is created with permissions equivalent to:
-
Obtain the actual store path and try reading the symlink as an ordinary user:
p="$(nix path-info nixpkgs#gavin-bc)"
readlink "$p/bin/dc"
When the store path is owned by root, this fails with Permission denied.
-
Reading the same link as root succeeds:
$ sudo readlink "$p/bin/dc"
bc
-
The problem can also be reproduced by trying to serialize the store path:
nix-store --dump "$p" >/dev/null
This fails for an ordinary user when Nix attempts to read bin/dc.
-
Similarly, if a closure containing gavin-bc is copied to another Nix store:
nix copy --to ssh://user@host ./result
the operation eventually fails with:
error: reading symbolic link "/nix/store/...-gavin-bc-7.1.0/bin/dc": Permission denied
Expected behaviour
bin/dc should be readable by ordinary users, like other symlinks in Nix store paths.
For example, it could have mode 0555 or 0755 on Darwin:
An ordinary user should be able to run:
$ readlink /nix/store/...-gavin-bc-7.1.0/bin/dc
bc
and Nix should be able to serialize and copy the store path without requiring root privileges.
Screenshots
No response
Relevant log output
$ ls -l /nix/store/48pcyqxywyw4nvnr903daa8cxg8p19zi-gavin-bc-7.1.0/bin/dc
lrwx------ root wheel ... /nix/store/48pcyqxywyw4nvnr903daa8cxg8p19zi-gavin-bc-7.1.0/bin/dc -> bc
$ readlink /nix/store/48pcyqxywyw4nvnr903daa8cxg8p19zi-gavin-bc-7.1.0/bin/dc
readlink: /nix/store/48pcyqxywyw4nvnr903daa8cxg8p19zi-gavin-bc-7.1.0/bin/dc: Permission denied
$ sudo readlink /nix/store/48pcyqxywyw4nvnr903daa8cxg8p19zi-gavin-bc-7.1.0/bin/dc
bc
$ nix copy --to ssh://user@host ./result
error: reading symbolic link "/nix/store/48pcyqxywyw4nvnr903daa8cxg8p19zi-gavin-bc-7.1.0/bin/dc": Permission denied
Additional context
The likely cause is upstream scripts/safe-install.sh.
In gavin-bc 7.1.0 it sets:
and then creates symlinks with:
if test "$symlink" ; then
ln -s "$src" "$tmp"
else
cat < "$src" > "$tmp"
chmod "$mode" "$tmp"
fi
Therefore the symlink is created while umask 077 is active. Unlike the regular-file branch, the symlink branch does not subsequently apply the requested mode.
This is mostly invisible on systems where symlink permission bits are ignored, but Darwin stores and enforces symlink permissions, resulting in an inaccessible 0700 symlink once the Nix store path is owned by root.
Possible fixes
A simple downstream fix in nixpkgs would be to correct the symlink permissions after installation on Darwin, for example:
postFixup = lib.optionalString stdenv.hostPlatform.isDarwin ''
chmod -h 555 "$out/bin/dc"
'';
Alternatively, this could be fixed upstream by using a less restrictive umask specifically when creating symlinks, for example:
if test "$symlink" ; then
(
umask 022
ln -s "$src" "$tmp"
)
else
...
fi
The upstream fix would also prevent the same problem for any other symlinks created by this installation helper.
Temporary workaround
For an existing Nix store path, changing only the symlink mode works around the problem:
$ sudo chmod -h 555 /nix/store/...-gavin-bc-7.1.0/bin/dc
After this, readlink, nix-store --dump, and nix copy work for ordinary users.
A local nixpkgs overlay can apply the same workaround:
(final: prev: {
gavin-bc = prev.gavin-bc.overrideAttrs (old: {
postFixup = (old.postFixup or "") + ''
chmod -h 555 "$out/bin/dc"
'';
});
})
Automation/AI disclosure
This issue report was drafted with assistance from ChatGPT (GPT-5.6 Sol). I manually reviewed and verified the technical content before submission.
System metadata
- system:
"aarch64-darwin"
- host os:
Darwin 24.6.0, macOS 15.7.9
- multi-user?:
yes
- sandbox:
no
- version:
nix-env (Determinate Nix 3.21.9) 2.34.8
- nixpkgs:
/nix/store/xk2kl6xaj4dp0rdnk6p32nrwhkxmi7vp-source
Are you using nix-darwin?
Yes, I am using nix-darwin.
Notify maintainers
@delafthi
Note for maintainers: Please tag this issue in your pull request description. (i.e. Resolves #ISSUE.)
I assert that this issue is relevant for Nixpkgs
Is this issue important to you?
Add a 👍 reaction to issues you find important.
Nixpkgs version
Describe the bug
On Darwin,
gavin-bc7.1.0 installs thebin/dcsymlink with mode0700.For a package installed in the Nix store, the resulting symlink is owned by
root:wheel:As a result, non-root users cannot read the symlink:
while reading it as root works correctly:
This also breaks Nix operations that need to serialize the store path. For example,
nix copyfails when it reachesgavin-bc:Other store paths in the same closure can be serialized and copied normally.
The
dc -> bcsymlink itself is correct. The problem is specifically its mode on Darwin.Steps to reproduce
On macOS, build
gavin-bc:nix build nixpkgs#gavin-bcInspect the
dcsymlink:ls -l result/bin/dcThe symlink is created with permissions equivalent to:
Obtain the actual store path and try reading the symlink as an ordinary user:
When the store path is owned by
root, this fails withPermission denied.Reading the same link as root succeeds:
The problem can also be reproduced by trying to serialize the store path:
nix-store --dump "$p" >/dev/nullThis fails for an ordinary user when Nix attempts to read
bin/dc.Similarly, if a closure containing
gavin-bcis copied to another Nix store:nix copy --to ssh://user@host ./resultthe operation eventually fails with:
Expected behaviour
bin/dcshould be readable by ordinary users, like other symlinks in Nix store paths.For example, it could have mode
0555or0755on Darwin:An ordinary user should be able to run:
and Nix should be able to serialize and copy the store path without requiring root privileges.
Screenshots
No response
Relevant log output
Additional context
The likely cause is upstream
scripts/safe-install.sh.In
gavin-bc7.1.0 it sets:umask 077and then creates symlinks with:
Therefore the symlink is created while
umask 077is active. Unlike the regular-file branch, the symlink branch does not subsequently apply the requested mode.This is mostly invisible on systems where symlink permission bits are ignored, but Darwin stores and enforces symlink permissions, resulting in an inaccessible
0700symlink once the Nix store path is owned by root.Possible fixes
A simple downstream fix in nixpkgs would be to correct the symlink permissions after installation on Darwin, for example:
Alternatively, this could be fixed upstream by using a less restrictive umask specifically when creating symlinks, for example:
The upstream fix would also prevent the same problem for any other symlinks created by this installation helper.
Temporary workaround
For an existing Nix store path, changing only the symlink mode works around the problem:
$ sudo chmod -h 555 /nix/store/...-gavin-bc-7.1.0/bin/dcAfter this,
readlink,nix-store --dump, andnix copywork for ordinary users.A local nixpkgs overlay can apply the same workaround:
Automation/AI disclosure
This issue report was drafted with assistance from ChatGPT (GPT-5.6 Sol). I manually reviewed and verified the technical content before submission.
System metadata
"aarch64-darwin"Darwin 24.6.0, macOS 15.7.9yesnonix-env (Determinate Nix 3.21.9) 2.34.8/nix/store/xk2kl6xaj4dp0rdnk6p32nrwhkxmi7vp-sourceAre you using nix-darwin?
Yes, I am using nix-darwin.
Notify maintainers
@delafthi
Note for maintainers: Please tag this issue in your pull request description. (i.e.
Resolves #ISSUE.)I assert that this issue is relevant for Nixpkgs
Is this issue important to you?
Add a 👍 reaction to issues you find important.