builtins.storePath can read impure symlinks in pure evaluation mode #1147

Closed
opened 2026-03-05 16:38:32 +00:00 by alois31 · 5 comments
Member

Describe the bug

Recently, builtins.storePath started being allowed in pure evaluation mode. While the intended functionality is pure, the unrestricted symlink resolution also performed by this builtin is not.

Steps To Reproduce

  1. cd /tmp (to get into a well-defined directory)
  2. nix-build '<nixpkgs>' -A hello (to obtain a symlink to the store)
  3. nix-instantiate --eval --option pure-eval true --expr 'builtins.storePath "/tmp/result"'
  4. The command succeds (prints "/nix/store/8qi947kixhz1nw83dkwxm6d0wndprqkj-hello-2.12.2" here, but the actual output doesn't matter)

Expected behavior

The command fails because the symlink resolution is impure.

nix --version output

nix (Lix, like Nix) 2.95.0-dev-8b38edaf1e01
System type: x86_64-linux
Additional system types: i686-linux, x86_64-v1-linux, x86_64-v2-linux, x86_64-v3-linux
Features: gc, signed-caches
System configuration file: /etc/nix/nix.conf
User configuration files: /home/aloisw/.config/nix/nix.conf:/home/aloisw/.config/kdedefaults/nix/nix.conf:/etc/xdg/nix/nix.conf
Store directory: /nix/store
State directory: /nix/var/nix
Data directory: /nix/store/sr8yca9yzwb8svk6s0c3vm0qc43rc97q-lix-2.95.0-dev-8b38edaf1e01/share
## Describe the bug [Recently](https://git.lix.systems/lix-project/lix/commit/37ccd28c3b12209c9f03f6f8b37a770b8a28c63d), `builtins.storePath` started being allowed in pure evaluation mode. While the intended functionality is pure, the unrestricted symlink resolution also performed by this builtin is not. ## Steps To Reproduce 1. `cd /tmp` (to get into a well-defined directory) 2. `nix-build '<nixpkgs>' -A hello` (to obtain a symlink to the store) 3. `nix-instantiate --eval --option pure-eval true --expr 'builtins.storePath "/tmp/result"'` 4. The command succeds (prints `"/nix/store/8qi947kixhz1nw83dkwxm6d0wndprqkj-hello-2.12.2"` here, but the actual output doesn't matter) ## Expected behavior The command fails because the symlink resolution is impure. ## `nix --version` output ``` nix (Lix, like Nix) 2.95.0-dev-8b38edaf1e01 System type: x86_64-linux Additional system types: i686-linux, x86_64-v1-linux, x86_64-v2-linux, x86_64-v3-linux Features: gc, signed-caches System configuration file: /etc/nix/nix.conf User configuration files: /home/aloisw/.config/nix/nix.conf:/home/aloisw/.config/kdedefaults/nix/nix.conf:/etc/xdg/nix/nix.conf Store directory: /nix/store State directory: /nix/var/nix Data directory: /nix/store/sr8yca9yzwb8svk6s0c3vm0qc43rc97q-lix-2.95.0-dev-8b38edaf1e01/share ```
Owner

Do you confirm this doesn't take place with the builtins.appendContext technique?

Do you confirm this doesn't take place with the `builtins.appendContext` technique?
pennae added this to the 2.95 milestone 2026-03-05 17:00:17 +00:00
Owner
Revert opened in https://gerrit.lix.systems/c/lix/+/5331.
Member

This issue was mentioned on Gerrit on the following CLs:

  • commit message in cl/5331 ("Revert "libexpr/primops: allow storePath in pure evaluation mode"")
<!-- GERRIT_LINKBOT: {"cls": [{"backlink": "https://gerrit.lix.systems/c/lix/+/5331", "number": 5331, "kind": "commit message"}], "cl_meta": {"5331": {"change_title": "Revert \"libexpr/primops: allow storePath in pure evaluation mode\""}}} --> This issue was mentioned on Gerrit on the following CLs: * commit message in [cl/5331](https://gerrit.lix.systems/c/lix/+/5331) ("Revert "libexpr/primops: allow storePath in pure evaluation mode"")
Member
# nix-instantiate --eval --option pure-eval true --expr 'let storePath = path: let path2 = builtins.unsafeDiscardStringContext path; in builtins.appendContext path2 { ${path2} = { path = true; }; }; in storePath "/tmp/result"'
error:
       … while calling the 'appendContext' builtin
         at «string»:1:80:
            1| let storePath = path: let path2 = builtins.unsafeDiscardStringContext path; in builtins.appendContext path2 { ${path2} = { path = true; }; }; in storePath "/tmp/result"
             |                                                                                ^

       error: context key '"/tmp/result"' is not a store path
       at «string»:1:111:
            1| let storePath = path: let path2 = builtins.unsafeDiscardStringContext path; in builtins.appendContext path2 { ${path2} = { path = true; }; }; in storePath "/tmp/result"
             |                                                                                                               ^
```console # nix-instantiate --eval --option pure-eval true --expr 'let storePath = path: let path2 = builtins.unsafeDiscardStringContext path; in builtins.appendContext path2 { ${path2} = { path = true; }; }; in storePath "/tmp/result"' error: … while calling the 'appendContext' builtin at «string»:1:80: 1| let storePath = path: let path2 = builtins.unsafeDiscardStringContext path; in builtins.appendContext path2 { ${path2} = { path = true; }; }; in storePath "/tmp/result" | ^ error: context key '"/tmp/result"' is not a store path at «string»:1:111: 1| let storePath = path: let path2 = builtins.unsafeDiscardStringContext path; in builtins.appendContext path2 { ${path2} = { path = true; }; }; in storePath "/tmp/result" | ^ ```
Owner

Right, the fix could be to re-introduce checkSourcePath in storePath. We will re-try in 96. This feature will be removed to 95, we are too close to the release window.

Right, the fix could be to re-introduce checkSourcePath in storePath. We will re-try in 96. This feature will be removed to 95, we are too close to the release window.
Sign in to join this conversation.
No milestone
No project
No assignees
4 participants
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#1147
No description provided.