$NIX_PATH entries can shadow internal lookup paths #998

Open
opened 2025-09-26 05:59:58 +00:00 by getchoo · 0 comments

Note

This is a copy of https://github.com/NixOS/nix/issues/14085, and very cursed

Describe the bug

At times, Lix (or users) will call internal, vendored files (like <nix/fetchurl.nix>) for various operations. However, these can be shadowed by entries into $NIX_PATH from the environment, which will completely break some functionality - especially if the nix path entry actually contains files of the same name, as then Lix won't fall back to its internal files

Steps To Reproduce

  1. mkdir -p not-internal-nix
  2. echo 'assert false; "womp womp"' > not-internal-nix/fetchurl.nix
  3. NIX_PATH="nix=$PWD/not-internal-nix" nix-instantiate -E "import <nix/fetchurl.nix>"
  4. Observe the following error:
error:
       … while calling the 'import' builtin
         at «string»:1:1:
            1| import <nix/fetchurl.nix>
             | ^

       … while evaluating the file '/home/atlas/not-internal-nix/fetchurl.nix':

       error: assertion failed
       at /home/atlas/not-internal-nix/fetchurl.nix:1:1:
            1| assert false; "womp womp"
             | ^
            2|

Expected behavior

Internal Lix files are always used and the names of my path entries don't (silently) cause this unattended consequence

A more specific idea I had was to maybe limit the "regular" lookup paths here (i.e., use certain characters or make a longer string that will make it basically impossible to have these kinds of conflicts, unlike the more plausible nix entry name). This obviously wouldn't work for internal files like <nix/fetchurl.nix> that are meant to be consumed though...so maybe we could special case those "public" ones? Or just not allow entry names named nix to at least avoid this footgun?

nix --version output

nix (Lix, like Nix) 2.93.3
System type: aarch64-linux
Additional system types:
Features: gc, signed-caches
System configuration file: /etc/nix/nix.conf
User configuration files: /home/atlas/.config/nix/nix.conf:/etc/xdg/nix/nix.conf:/home/atlas/.nix-profile/etc/xdg/nix/nix.conf:/nix/profile/etc/xdg/nix/nix.conf:/home/atlas/.local/state/nix/profile/etc/xdg/nix/nix.conf:/etc/profiles/per-user/atlas/etc/xdg/nix/nix.conf:/nix/var/nix/profiles/default/etc/xdg/nix/nix.conf:/run/current-system/sw/etc/xdg/nix/nix.conf
Store directory: /nix/store
State directory: /nix/var/nix
Data directory: /nix/store/g33fs6kkqdb1gzw4gcrz367ln5afvvw1-lix-2.93.3/share

Additional context

Came across this originally in Nix through the very funny https://github.com/NixOS/nix/issues/14062, which was then diagnosed as this issue by @xokdvium, who also figured out the extent to which it goes

Pure evaluation is unaffected by this, since no $NIX_PATH

>[!NOTE] > This is a copy of https://github.com/NixOS/nix/issues/14085, and very cursed ## Describe the bug At times, Lix (or users) will call internal, vendored files (like `<nix/fetchurl.nix>`) for various operations. However, these can be shadowed by entries into `$NIX_PATH` from the environment, which will completely break some functionality - *especially* if the `nix` path entry actually contains files of the same name, as then Lix won't fall back to its internal files ## Steps To Reproduce 1. `mkdir -p not-internal-nix` 2. `echo 'assert false; "womp womp"' > not-internal-nix/fetchurl.nix` 3. `NIX_PATH="nix=$PWD/not-internal-nix" nix-instantiate -E "import <nix/fetchurl.nix>"` 4. Observe the following error: ``` error: … while calling the 'import' builtin at «string»:1:1: 1| import <nix/fetchurl.nix> | ^ … while evaluating the file '/home/atlas/not-internal-nix/fetchurl.nix': error: assertion failed at /home/atlas/not-internal-nix/fetchurl.nix:1:1: 1| assert false; "womp womp" | ^ 2| ``` ## Expected behavior Internal Lix files are always used and the names of my path entries don't (silently) cause this unattended consequence A more specific idea I had was to maybe limit the "regular" lookup paths here (i.e., use certain characters or make a longer string that will make it basically impossible to have these kinds of conflicts, unlike the more plausible `nix` entry name). This obviously wouldn't work for internal files like <nix/fetchurl.nix> that *are* meant to be consumed though...so maybe we could special case those "public" ones? Or just not allow entry names named `nix` to at least avoid this footgun? ## `nix --version` output ``` nix (Lix, like Nix) 2.93.3 System type: aarch64-linux Additional system types: Features: gc, signed-caches System configuration file: /etc/nix/nix.conf User configuration files: /home/atlas/.config/nix/nix.conf:/etc/xdg/nix/nix.conf:/home/atlas/.nix-profile/etc/xdg/nix/nix.conf:/nix/profile/etc/xdg/nix/nix.conf:/home/atlas/.local/state/nix/profile/etc/xdg/nix/nix.conf:/etc/profiles/per-user/atlas/etc/xdg/nix/nix.conf:/nix/var/nix/profiles/default/etc/xdg/nix/nix.conf:/run/current-system/sw/etc/xdg/nix/nix.conf Store directory: /nix/store State directory: /nix/var/nix Data directory: /nix/store/g33fs6kkqdb1gzw4gcrz367ln5afvvw1-lix-2.93.3/share ``` ## Additional context Came across this originally in Nix through the very funny https://github.com/NixOS/nix/issues/14062, which was then diagnosed as this issue by @xokdvium, who also figured out the extent to which it goes Pure evaluation is unaffected by this, since no `$NIX_PATH`
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lix-project/lix#998
No description provided.