nix
nix copied to clipboard
NIX_SSL_CERT_FILE unreadable from nix sandbox
Describe the bug
Note: this issue is partially resolved by https://github.com/NixOS/nixpkgs/pull/401942, but further discussion is needed.
The following description of the issue assumes that the workaround in https://github.com/NixOS/nixpkgs/pull/401942 is not present:
The NIX_SSL_CERT_FILE env var is used for overriding nix's ssl-cert-file config value via an env var.
The NIX_SSL_CERT_FILE env var is also respected in several Nixpkgs packages (via patches) that need certificate bundles.
By default, NIX_SSL_CERT_FILE used to be unset inside the build environment unless something inside nixpkgs set it to a value: the cacert hook's main job was to do this.
However after https://github.com/NixOS/nixpkgs/pull/303307 was merged into Nixpkgs, NIX_SSL_CERT_FILE was added as a default impure env var for fetchers. It also made the cacert hook respect the variable if it was not unset (in case it inherited the impure env var).
This can be useful. But only if NIX_SSL_CERT_FILE is readable.
In most cases NIX_SSL_CERT_FILE is unset by default, so it doesn't cause problems.
If NIX_SSL_CERT_FILE is set to a path readable from the builder itself, it still doesn't cause problems.
However, in most cases where NIX_SSL_CERT_FILE is set to anything, it is set to a path that's not readable from the builder, e.g. /etc/ssl/certs/ca-certificates.crt or /nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt.
See: The author of https://github.com/NixOS/nixpkgs/pull/303307 has a program which uses the impure env var behaviour of NIX_SSL_CERT_FILE, but it can only use it by putting the cert in the world-readable /tmp directory
Users of nix-darwin have the NIX_SSL_CERT_FILE of the nix-daemon (where impure env vars are inherited from) set by default, because security.pki.installCACerts is set to true by default.
See:
https://github.com/nix-darwin/nix-darwin/blob/b6fff20c692d684d250a39453ed1853dd44c96ab/modules/security/pki/default.nix#L82-L89
https://github.com/nix-darwin/nix-darwin/blob/b6fff20c692d684d250a39453ed1853dd44c96ab/modules/services/nix-daemon.nix#L63-L65
"Luckily" because darwin does not have sandboxing enabled by default, this is not a problem.
However, this means that if we enable sandboxing on darwin, we are very likely to encounter the fact that NIX_SSL_CERT_FILE is not readable from the builder.
In darwin, we could actually fix this readability issue because darwin doesn't use chroot for sandboxing, it just uses access whitelist rules.
Here's a possible solution just adding the set certificate file in the allowlist: https://gerrit.lix.systems/c/lix/+/2906
NIX_SSL_CERT_FILE being unreadable breaks many things in Nixpkgs: e.g. fetchgit and rustPlatform.fetchCargoVendor, basically everything using cacert as a setup-hook.
fetchCargoVendor failure: https://github.com/NixOS/nixpkgs/issues/385366
fetchgit failure: https://github.com/NixOS/nixpkgs/issues/385366#issuecomment-2738035391
Steps To Reproduce
- have a nix-darwin system
- have sandboxing enabled
- in a FOD derivation, have
impureEnvVars = lib.fetchers.proxyImpureEnvVars(a list that containsNIX_SSL_CERT_FILE, among others) - in the FOD's build script run
cat "$NIX_SSL_CERT_FILE" - get a permission error (which means that it is not whitelisted by the sandbox)
Additional context
Checklist
- [ ] checked latest Nix manual (source)
- [ ] checked open bug issues and pull requests for possible duplicates
Add :+1: to issues you find important.
Thanks for opening this.
Repro for me:
$ nix config show sandbox
true
$ nix repl nixpkgs#legacyPackages.aarch64-darwin
Nix 2.24.12
Type :? for help.
Loading installable 'flake:nixpkgs#legacyPackages.aarch64-darwin'...
Added 24154 variables.
nix-repl> :b fetchgit { url = "https://github.com/n8henrie/flake-templates"; hash = "sha256-nkwrC+gtQ1AgD0LOmnweBs25aIErWWiv8qckplrofvk=";}
error: builder for '/nix/store/i80ansib9qpy96ydqvxx1h8vvcmfv4h0-flake-templates.drv' failed with exit code 1;
last 7 log lines:
> exporting https://github.com/n8henrie/flake-templates (rev HEAD) into /nix/store/ycbh64cs7finbl4z8ig7wqm1k0iydbrr-flake-templates
> Initialized empty Git repository in /nix/store/ycbh64cs7finbl4z8ig7wqm1k0iydbrr-flake-templates/.git/
> fatal: unable to access 'https://github.com/n8henrie/flake-templates/': SSL certificate problem: unable to get local issuer certificate
> fatal: unable to access 'https://github.com/n8henrie/flake-templates/': SSL certificate problem: unable to get local issuer certificate
> fatal: unable to access 'https://github.com/n8henrie/flake-templates/': SSL certificate problem: unable to get local issuer certificate
> fatal: unable to access 'https://github.com/n8henrie/flake-templates/': SSL certificate problem: unable to get local issuer certificate
> Unable to checkout HEAD from https://github.com/n8henrie/flake-templates.
For full logs, run 'nix log /nix/store/i80ansib9qpy96ydqvxx1h8vvcmfv4h0-flake-templates.drv'.
error: build of '/nix/store/i9qaqh66iydxzr0sqqpkz6wvqfs63xdw-flake-templates.drv' failed
[0 built (4 failed), 0.0 MiB DL]
- system:
"aarch64-darwin" - host os:
Darwin 24.3.0, macOS 15.3.2 - multi-user?:
yes - sandbox:
yes - version:
nix-env (Nix) 2.24.12 - channels(root):
"nixpkgs" - nixpkgs:
/nix/store/6pz76h4dyj2s9il8pbrxi1knkmbs0z9a-source
@WeetHet created https://gerrit.lix.systems/c/lix/+/2869 in lix that sounds like it should resolve the issue.
An improved version: https://gerrit.lix.systems/c/lix/+/2906
Thanks for raising this, the readability issue was a surprise to me.
My original line of thinking was "why would you set this to an unreadable path"? But of course these things are usually accidental or a result of other intentions.
That lix change looks good to me, thanks!
If we don't want to always expose that file, a narrower change could be for the sandbox code which makes the file unreadable to also unset the envvar. But simply making that file available in-sandbox is much better ❤ .
When I originally posted the link to the lix "fix" the issue, I knew a lot less than what I know now, and I have since updated the issue description a lot.
Currently, I don't believe that the Lix fix is good enough, as it doesn't do anything for linux, and relies on the fact that darwin paths in the sandbox are identical to darwin paths outside of the sandbox.
I currently don't really have the bandwidth to try to come up with an ideal alternate solution, but in a few weeks, once I'm free, I will gladly discuss possible long term solutions.
Hopefully we can bring people from both NixOS/nix and Lix into the discussion.
https://git.lix.systems/lix-project/lix/issues/885
Okay, I don't know if I already sent this link or not, but I think it is important:
https://github.com/NixOS/nix/blob/acfdacc971bb411bb8b85a05a37b6fc7330c4370/src/libstore/unix/build/linux-derivation-builder.cc#L664-L668
For linux-only: the contents of whatever ssl-cert-file is set to (caFile), will appear at the hardcoded location /etc/ssl/certs/ca-certificates.crt when building a FOD.
But since NIX_SSL_CERT_FILE is not guaranteed to be set to /etc/ssl/certs/ca-certificates.crt exactly, we don't find it.
Now, we could make it place the contents of caFile to the same location as NIX_SSL_CERT_FILE, but IMO that's horrible.
Another solution would be to have the process override NIX_SSL_CERT_FILE to point to the location where the contents of caFile were placed inside the chroot. This is better.
Though, I have not thought through what should happen in different sandbox modes, what should we do for backwards compat or whatever.
I still have much to do for the next 7 days, so I can't really dive much deeper now.
Another solution would be to have the process override NIX_SSL_CERT_FILE to point to the location where the contents of caFile were placed inside the chroot. This is better.
Yes, that sounds right to me too. That way the invariant holds inside and outside of a build that NIX_SSL_CERT_FILE points to a valid cert file. That is, assuming settings.caFile comes from $NIX_SSL_CERT_FILE when set?