How to add stuff to `/run/current-system/sw`? `/nix/store` isn't safe

Hi!

Now, the word on the street is that you guys are helpful and amazing. Well well, let’s see about that.

TLDR;

  1. I’m using nixos + zsh, and I want to expand my empire to also include pure-prompt for my prompt.
  2. /nix/store has the wrong permissions according to compaudit, it’s simply insecure. Because reasons.
    /usr/local/share/zsh/site-functions has the right permissions.
  3. How to add files to the right directory through my nixos config?

TSWR (Too short, will read);
The manual installation looks simple. Simply download two files and add the path to the $fpath variable.

No problem!”, I thought, “Here, hold my beer” I said. To myself.
"I’ll just download the files and do something like this in my programs.zsh.interactiveShellInit" I said with a confident laugh:

# ${./functions}) is a nix expression that evaluates to something like:
# _/nix/store/yrcgg8fd6lcr4y1kmlki4qkza80p0354-functions_
fpath=(${./functions}) $fpath)
# ^ very hard to say laughing confidently IRL

Cool! It works, I’m such a hacker! But, alas, there’s an annoying problem. I keep getting:

zsh compinit: insecure directories, run compaudit for list.
Ignore insecure directories and continue [y] or abort compinit [n]?

And this tells me that the problem is that the nix store isn’t safe in the eyes of zsh:

$ compaudit
# Outputs:
# There are insecure directories:
# /nix/store

When looking at the already existing fpath variable, I can see this for example /usr/local/share/zsh/site-functions.

I think it is defined here somehow, with environment.pathsToLink.

So, how do I add files to /usr/local/share/zsh/site-functions through my nixos configuration?
OR, how do I define a new directory to be linked? How can nix know which directory I want (environment.pathsToLink only accepts strings, not paths)?

Well well indeed!

Looking on Stackoverflow it seems like compaudit doesn’t like if a directory mode is a+w. So I guess the next question is, can you run ls -la /nix?

On a nixos system is should look something like this:

$ ls -la /nix/
total 11808
drwxr-xr-x     5 root root       4096 Apr 26  2017 .
drwxr-xr-x    18 root root       4096 Jul  8 13:51 ..
drwxrwxr-t 15210 root nixbld 12058624 Oct 31 21:58 store
drwxr-xr-x     4 root root       4096 Sep 10  2016 var

So I don’t see a world-writable directory here but it might be different on other systems.

Your turn :slight_smile:

Actually reading SO again, it looks like it’s also unhappy with group-writable, which the /nix/store has. compaudit isn’t giving the right assessment in this particular case as only nix builders should have access to the nixbld group. I think it’s to prevent the members of the “users” group to extend each-other’s shell.

I don’t really like it but compinit -u might be the best option here.

2 Likes

Thank you! I guess the gang on the street were right, after all. I don’t know much about permissions, that clearified a few things for me.

Yeah, the -u-thingy works, it suppresses the warning. Although, I’m with you here, it feels wrong to just ignore the warning.

But it would also feel wrong to change the permissions since I want my system to be fully deterministic (and safe at the same time), I’m currently not aware of any solution that would allow me to set the permissions in my configuration.

The best thing would be if I could use the shared directory somehow, but I’m not sure how. I think I will choose not to use methods that require custom stuff fpaths in that case

Regarding the -u thing. If it can be guaranteed somehow that zsh will only load configuration from the /nix/store then it’s safe to enable it. I don’t know enough about zsh and how nix wraps it to tell you if that is already the case or not.

1 Like

I had the same problem and was wondering why the default fpath entries under “${pkgs.zsh}share/zsh/5.9/functions” do not trigger the compaudit warning. By trial and error I found out that compaudit only complains about the direct parent of the fpath entry.

So instead of

{ programs.zsh.interactiveShellInit = "fpath+=${./functions}"; }

you should use

{ pkgs, ... }:
let
  zsh-functions = pkgs.runCommand "zsh-functions" {} ''
    mkdir -p $out/functions
    cp ${./functions}/* $out/functions
  '';
in
{ programs.zsh.interactiveShellInit = "fpath+=${zsh-functions}/functions"; }

As I read about zcompile and that you can compile multible function files into
one zwc file, I thought I could benifit from the imutable nature of the nix
store and am now even doing this:

{ pkgs, ... }:
let
  zsh-functions = pkgs.runCommand "zsh-functions" {} ''
    mkdir $out
    ${pkgs.zsh}/bin/zsh -c 'zcompile $out/functions.zwc ${./functions}/*'
  '';
in
{ programs.zsh.interactiveShellInit = "fpath+=${zsh-functions}/functions.zwc"; }

Sorry to resurrect this topic because it was the one I found when initially searching my problem so I hope this may help some other people in the future.