Why doesn't nix-env require sudo or root?

Hi Everyone,

I am new to nixos security.

Question: why doesn’t nix-env not require sudo or root ? Anyone with access, locally or remotely, can install stuff ?

By the time we realize an unauthorized program has been installed, we may have lost everything; all our source code; all our private files – too late for a roll back.

Define “install”.

In FHS distros, there is typically only one global environment. With Nix there can be infinitely many separate environments.

Unprivileged users can modify their own environments at will using nix-env etc. but they cannot modify the global system environment; you need privileges for that. They are free to install whatever “unauthorised” program into their own environments as they please and potentially lose their data by running them but the program still only runs with the user’s privileges. Unless your user is privileged or your system can be abused to elevate privileges, the program cannot do harm to anyone but the individual user that ran it; it won’t affect the rest of the system.

It’s not any different from the user executing some bash script. It too could be malicious and they don’t need any privileges to “install” or run it on FHS distros either.


Hello and welcome!

As @Atemu already pointed out, installing software in nix-env doesn’t require sudo because it’s only available to the user who installed it (and not “system-wide”).

You might want to take a look at the Introduction of the Nix Reference Manual and the chapter on User Profiles - they explain how software is managed by Nix.

1 Like

OK so the user can only cause himself problems, and not affect anyone else globally. But an attacker can still use nix-env -i to install anything into that user’s ‘profile’ and steal all his data. Assume the attacker is not the user, but gained access to his account. It is true that the attacker can siphon out data many ways, but since the attacker can install programs, she will simply install an ftp server or something of that sort, and mass siphon away all the user’s data. Giving the user the rights to install programs for himself is like giving him a gun to shoot himself - if he doesnt shoot himself accidentally, and certainly dangerous if the user is a minor. A secure os should protect the user.

A more detailed example would be phish email with a script download. The script executes, installs a program ( because nix-env -i allows it ) and then the attack progresses.

At this point the user is already screwed.

You can tell Nix what users are allowed to use it: nix.conf - Nix Reference Manual


How can I change this nix.conf ?




The user already has guns in both of their hands; they can run any arbitrary binary they downloaded off the internet already or do curl ... | sh.

This cannot be done without limiting user freedom and is therefore not a policy you can expect libre software to implement by default.


Does the option nix.settings.allowed-users append to the settings in nix.conf ? I set this setting to @wheel. But there is already a * in the allow-users. And I created a new group 101, and useradd a new user with group 101. And checked that the new user is not part of wheel. And still was able to run nix-env ?

… Though it’s totally reasonable to ask about libre tools like AppArmor, SELinux, and sandboxing, namespacing, and virtualization environments to empower users to build their own safeguards.

(I usually bubblewrap or VM anything I don’t trust—depending on how much I distrust it—but otherwise don’t specifically prevent processes from using Nix to fetch new software. As others have pointed out, if I’m already running untrustworthy software using Nix to get more software to run in the same context doesn’t make things worse.)

(Would also love to try Spectrum someday, but that’s probably not helpful for you today.)


What I like about NixOS or think it is about is that it offers update transaction integrity - each entire update batch is sort of checksumed, So that an update batch is guaranteed not to have extra things inserted into the stream. A thing that ordinary package signatures do not provide. Correct me if I am wrong please.

I have a compromised modem. And the attackers have shown that they are able to compromise various brands of modem/routers. So I have given up changing ISPs in hope of getting an patchable modem/router.

Thus I need update transaction entire-batch security. The attackers have tampered with my update streams before and inserted malicious things.

Plus I am a security admin. I am entirely security focused. My home systems Windows and Linux are hardened, secured with the best technology available. And I try to mitigate as much as possible. I of course realize there is no absolute security, years of experience has taught me that. But we keep trying, don’t we? That’s our job.

I think the root of the misunderstanding here lies in not fully understanding how binaries are executed on Linux.

With or without nix, users can execute arbitrary binaries. Policy statements and traditional FHS distro behavior just make it look like that isn’t true.

Nothing stops your users grabbing a copy of the firefox source code and compiling it into a binary, and executing it as ./firefox. Nothing stops a phishing mail making a user download a precompiled ELF binary and executing it to send all their secrets to an attacker’s system. Nothing stops a user downloading a gentoo prefix.

This is true on distros without package managers with per-user prefixes, and AIUI it is largely true on Windows and Mac OS as well.

You can add additional software that does sanity checks at the kernel level to control which and how binaries are executed (e.g. firewalls, SELinux, apparmor, something that checks signatures before executing binaries, or a combination of things typically referred to as “antivirus”), which is how the various commercial OSes put some additional barriers up, but most Linux systems don’t have these enabled (IME only developers get Linux laptops in contexts where this is considered a problem, and SELinux causing too many problems with docker combined with people not fully understanding the implications means it’s just never enabled by policy), and to my knowledge none of these systems can control scripting or shared libraries yet.

Either way, the problem isn’t really a nix one, but a fundamental Linux (and in fact general purpose OS? I don’t think there’s much prior art for signed scripts, shared libraries, etc. even on Android/iOS) ecosystem issue.

The nix devs aren’t the right people to complain to, this’d probably take an industry-wide effort to fix.

Nix does have features to make ot harder for individuals to actually break policy and install random software using nix specifically, but you can’t currently fully prevent it even without nix.


" Nothing stops your users grabbing a copy of the firefox source code and compiling it into a binary, and executing it as ./firefox . Nothing stops a phishing mail making a user download a precompiled ELF binary and executing it to send all their secrets to an attacker’s system. Nothing stops a user downloading a gentoo prefix."

I appreciate the kinds of difficulties. But if I can control the use of nix-env and curl then it would be a step in the right direction.

I still use Ubuntu, and I can craft apparmor profiles. I read a Selinux book years ago, and I can re-read it again. I still haven’t figured out how to deploy an apparmor policy on NixOS. Nor have I experimented with creating a policy on NixOS.

Scripting security is a problem in Windows as well as Linux. Windows anti-malware products can detect or parse scripts, but their strengths are understandably limited.

I value NixOS for it’s transactional integrity feature as a security feature addressing the problem that I face. So termporarily settling on this os for now, I am attempting to mitigate as many problems as I can.

I am having problems with the option nix.settings.allowed-users, as explained above.

Fair enough! Your initial question just read like you’re not quite following why nix is capable of this.

It does, because it’s a list of string type, see the NixOS manual: NixOS Manual

You can forcibly set it to a specific list instead of appending like so:

nix.settings.allowed-users = lib.mkForce [

All settings with the same priority will be appended, so if you again set this setting with lib.mkForce in another module that list will be appended to this one (and both will override the default set in nixpkgs).

I’m a bit surprised it’s not a lib.mkDefault to have a lower priority by default, though. I’ve not checked, maybe something else is wrong, you can check the generated file in /etc/nix/nix.conf.

I don’t see how ordinary package signatures do not solve this too, unless their signing process is inherently broken.