From fcf234898e4d5761d3e37b0c14e01b9ebf3bd3ff Mon Sep 17 00:00:00 2001 From: rnhmjoj Date: Sat, 11 Apr 2026 18:14:24 +0200 Subject: [PATCH 1/5] rofi: remove workaround for missing root user root is now available in the build sandbox and the check phase is working. --- pkgs/by-name/ro/rofi-unwrapped/package.nix | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/pkgs/by-name/ro/rofi-unwrapped/package.nix b/pkgs/by-name/ro/rofi-unwrapped/package.nix index c47e3a2bef96..2f7b2405609d 100644 --- a/pkgs/by-name/ro/rofi-unwrapped/package.nix +++ b/pkgs/by-name/ro/rofi-unwrapped/package.nix @@ -47,10 +47,6 @@ stdenv.mkDerivation (finalAttrs: { preConfigure = '' patchShebangs "script" - - # root not present in build /etc/passwd - substituteInPlace test/helper-expand.c \ - --replace-fail "~root" "~nobody" ''; depsBuildBuild = [ @@ -100,7 +96,7 @@ stdenv.mkDerivation (finalAttrs: { (lib.mesonEnable "xcb" x11Support) ]; - doCheck = false; + doCheck = true; nativeInstallCheckInputs = [ versionCheckHook From 577b32b084a372c19629804835076e8446781593 Mon Sep 17 00:00:00 2001 From: rnhmjoj Date: Sat, 11 Apr 2026 18:44:20 +0200 Subject: [PATCH 2/5] treewide: remove nobody/nogroup from examples The nobody/nogroup pair of should only ever be used by NFS to map remote uid/guids that are missing locally. Every other use is an abuse and generally a security concern. Specifically, they're NOT some special user/group that can be used to run programs without giving them any privileges. In fact, the opposite is true: the more programs you run as nobody/nogroup the more valuable files and resources become accessible to "nobody" and consequently exposed to a potentially compromised program. This removes mentions of nobody/nogroup from documentation and examples. --- nixos/modules/hardware/cpu/x86-msr.nix | 4 +- .../modules/services/networking/nftables.nix | 3 +- nixos/modules/services/networking/ocserv.nix | 4 +- .../services/web-servers/mighttpd2.nix | 6 +- .../modules/virtualisation/oci-containers.nix | 2 +- pkgs/build-support/docker/default.nix | 1 - pkgs/build-support/docker/examples.nix | 86 +++++++++---------- 7 files changed, 52 insertions(+), 54 deletions(-) diff --git a/nixos/modules/hardware/cpu/x86-msr.nix b/nixos/modules/hardware/cpu/x86-msr.nix index 9d8216f16d9d..60c5f5fe8ca9 100644 --- a/nixos/modules/hardware/cpu/x86-msr.nix +++ b/nixos/modules/hardware/cpu/x86-msr.nix @@ -45,13 +45,13 @@ in owner = mkOption { type = str; default = "root"; - example = "nobody"; + example = "alice"; description = "Owner ${set}"; }; group = mkOption { type = str; default = defaultGroup; - example = "nobody"; + example = "users"; description = "Group ${set}"; }; mode = mkOption { diff --git a/nixos/modules/services/networking/nftables.nix b/nixos/modules/services/networking/nftables.nix index 40718c879ccf..5a6671d1ccf3 100644 --- a/nixos/modules/services/networking/nftables.nix +++ b/nixos/modules/services/networking/nftables.nix @@ -111,7 +111,8 @@ in type = lib.types.lines; default = ""; example = lib.literalExpression '' - sed 's/skgid meadow/skgid nogroup/g' -i ruleset.conf + # replace users/groups that don't exist in the test + sed 's/skgid meadow/skgid root/g' -i ruleset.conf ''; description = '' This script gets run before the ruleset is checked. It can be used to diff --git a/nixos/modules/services/networking/ocserv.nix b/nixos/modules/services/networking/ocserv.nix index 6c403a9b3427..8433faef86a7 100644 --- a/nixos/modules/services/networking/ocserv.nix +++ b/nixos/modules/services/networking/ocserv.nix @@ -34,8 +34,8 @@ in auth = "plain[passwd=./sample.passwd]" tcp-port = 443 udp-port = 443 - run-as-user = nobody - run-as-group = nogroup + run-as-user = ocserv + run-as-group = ocserv socket-file = /run/ocserv-socket server-cert = certs/server-cert.pem server-key = certs/server-key.pem diff --git a/nixos/modules/services/web-servers/mighttpd2.nix b/nixos/modules/services/web-servers/mighttpd2.nix index 09f5f847f74a..7211016f2e85 100644 --- a/nixos/modules/services/web-servers/mighttpd2.nix +++ b/nixos/modules/services/web-servers/mighttpd2.nix @@ -24,10 +24,8 @@ in # IP address or "*" Host: * Debug_Mode: Yes # Yes or No - # If available, "nobody" is much more secure for User:. - User: root - # If available, "nobody" is much more secure for Group:. - Group: root + User: mighttpd2 + Group: mighttpd2 Pid_File: /run/mighty.pid Logging: Yes # Yes or No Log_File: /var/log/mighty # The directory must be writable by User: diff --git a/nixos/modules/virtualisation/oci-containers.nix b/nixos/modules/virtualisation/oci-containers.nix index cf1076b4d99a..b7dde1126933 100644 --- a/nixos/modules/virtualisation/oci-containers.nix +++ b/nixos/modules/virtualisation/oci-containers.nix @@ -197,7 +197,7 @@ let Override the username or UID (and optionally groupname or GID) used in the container. ''; - example = "nobody:nogroup"; + example = "alice:users"; }; volumes = mkOption { diff --git a/pkgs/build-support/docker/default.nix b/pkgs/build-support/docker/default.nix index ccc6709160ba..92e003c64afb 100644 --- a/pkgs/build-support/docker/default.nix +++ b/pkgs/build-support/docker/default.nix @@ -121,7 +121,6 @@ rec { inherit buildImage buildLayeredImage - fakeNss pullImage shadowSetup buildImageWithNixDb diff --git a/pkgs/build-support/docker/examples.nix b/pkgs/build-support/docker/examples.nix index d2ff74ded00b..6f7568f492c2 100644 --- a/pkgs/build-support/docker/examples.nix +++ b/pkgs/build-support/docker/examples.nix @@ -11,7 +11,6 @@ pkgs, buildImage, buildLayeredImage, - fakeNss, pullImage, shadowSetup, buildImageWithNixDb, @@ -27,11 +26,37 @@ let }; evalMinimalConfig = module: nixosLib.evalModules { modules = [ module ]; }; + nonRootShadowSetup = + { + user, + uid, + gid ? uid, + }: + with pkgs; + [ + (writeTextDir "etc/shadow" '' + root:!x::::::: + ${user}:!::::::: + '') + (writeTextDir "etc/passwd" '' + root:x:0:0::/root:${runtimeShell} + ${user}:x:${toString uid}:${toString gid}::/home/${user}: + '') + (writeTextDir "etc/group" '' + root:x:0: + ${user}:x:${toString gid}: + '') + (writeTextDir "etc/gshadow" '' + root:x:: + ${user}:x:: + '') + ]; + nginxArguments = let nginxPort = "80"; nginxConf = pkgs.writeText "nginx.conf" '' - user nobody nobody; + user nginx nginx; daemon off; error_log /dev/stdout info; pid /dev/null; @@ -55,9 +80,12 @@ let name = "nginx-container"; tag = "latest"; contents = [ - fakeNss pkgs.nginx - ]; + ] + ++ nonRootShadowSetup { + uid = 999; + user = "nginx"; + }; extraCommands = '' mkdir -p tmp/nginx_client_body @@ -596,46 +624,18 @@ rec { }; # buildLayeredImage with non-root user - bashLayeredWithUser = - let - nonRootShadowSetup = - { - user, - uid, - gid ? uid, - }: - with pkgs; - [ - (writeTextDir "etc/shadow" '' - root:!x::::::: - ${user}:!::::::: - '') - (writeTextDir "etc/passwd" '' - root:x:0:0::/root:${runtimeShell} - ${user}:x:${toString uid}:${toString gid}::/home/${user}: - '') - (writeTextDir "etc/group" '' - root:x:0: - ${user}:x:${toString gid}: - '') - (writeTextDir "etc/gshadow" '' - root:x:: - ${user}:x:: - '') - ]; - in - pkgs.dockerTools.buildLayeredImage { - name = "bash-layered-with-user"; - tag = "latest"; - contents = [ - pkgs.bash - pkgs.coreutils - ] - ++ nonRootShadowSetup { - uid = 999; - user = "somebody"; - }; + bashLayeredWithUser = pkgs.dockerTools.buildLayeredImage { + name = "bash-layered-with-user"; + tag = "latest"; + contents = [ + pkgs.bash + pkgs.coreutils + ] + ++ nonRootShadowSetup { + uid = 999; + user = "somebody"; }; + }; # basic example, with cross compilation cross = From 4d90b8bb6c1540de08f374bf9732868e3b926c51 Mon Sep 17 00:00:00 2001 From: rnhmjoj Date: Sat, 11 Apr 2026 18:54:30 +0200 Subject: [PATCH 3/5] nixos/tests/wpa_supplicant: do not use nobody --- nixos/tests/wpa_supplicant.nix | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/nixos/tests/wpa_supplicant.nix b/nixos/tests/wpa_supplicant.nix index 8b3321822b03..a16547712769 100644 --- a/nixos/tests/wpa_supplicant.nix +++ b/nixos/tests/wpa_supplicant.nix @@ -273,6 +273,11 @@ in # add a virtual wlan interface boot.kernelModules = [ "mac80211_hwsim" ]; + users.users.alice = { + isNormalUser = true; + group = "users"; + }; + # wireless client networking.wireless = { enable = lib.mkOverride 0 true; @@ -283,7 +288,7 @@ in }; testScript = '' - wpa_cli = "sudo -u nobody -g wpa_supplicant wpa_cli" + wpa_cli = "sudo -u alice -g wpa_supplicant wpa_cli" with subtest("Daemon is running and accepting connections"): machine.wait_for_unit("wpa_supplicant-wlan1.service") From 1f35c7befee1c2372b2237ab4bdbf8f9df680702 Mon Sep 17 00:00:00 2001 From: rnhmjoj Date: Sat, 11 Apr 2026 20:47:45 +0200 Subject: [PATCH 4/5] povray: do not use nobody/nogroup Instead of patching the user to nobody, point HOME to TMPDIR, so the configure script discovers the build user on its own. --- pkgs/by-name/po/povray/package.nix | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkgs/by-name/po/povray/package.nix b/pkgs/by-name/po/povray/package.nix index a1b284a9a339..a2744bfdd56f 100644 --- a/pkgs/by-name/po/povray/package.nix +++ b/pkgs/by-name/po/povray/package.nix @@ -51,10 +51,9 @@ stdenv.mkDerivation (finalAttrs: { cd unix ./prebuild.sh cd .. + export HOME=$TMPDIR sed -i -e 's/^povconfuser.*/povconfuser=$(TMPDIR)\/povray/' Makefile.{am,in} sed -i -e 's/^povuser.*/povuser=$(TMPDIR)\/.povray/' Makefile.{am,in} - sed -i -e 's/^povowner.*/povowner=nobody/' Makefile.{am,in} - sed -i -e 's/^povgroup.*/povgroup=nogroup/' Makefile.{am,in} ''; # https://github.com/POV-Ray/povray/issues/460 From b8b939cdcca154895f718f65c33d9abfa1add3a4 Mon Sep 17 00:00:00 2001 From: rnhmjoj Date: Sun, 12 Apr 2026 15:05:05 +0200 Subject: [PATCH 5/5] fetchfossil: do not use nobody Set the admin to the current user instead of nobody. Note: this doesn't seem to affect the output hash. --- pkgs/build-support/fetchfossil/builder.sh | 2 +- pkgs/build-support/fetchfossil/nix-prefetch-fossil | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/build-support/fetchfossil/builder.sh b/pkgs/build-support/fetchfossil/builder.sh index 43462834b19e..0b66a129c3d8 100644 --- a/pkgs/build-support/fetchfossil/builder.sh +++ b/pkgs/build-support/fetchfossil/builder.sh @@ -6,7 +6,7 @@ echo "Cloning Fossil $url [$rev] into $out" export HOME=$(pwd) # We must explicitly set the admin user for the clone to something reasonable. -fossil clone -A nobody "$url" fossil-clone.fossil +fossil clone -A $(whoami) "$url" fossil-clone.fossil mkdir fossil-clone WORKDIR=$(pwd) diff --git a/pkgs/build-support/fetchfossil/nix-prefetch-fossil b/pkgs/build-support/fetchfossil/nix-prefetch-fossil index 0e1ce4d9c060..32762f86425f 100755 --- a/pkgs/build-support/fetchfossil/nix-prefetch-fossil +++ b/pkgs/build-support/fetchfossil/nix-prefetch-fossil @@ -77,7 +77,7 @@ export HOME="$tmpPath" echo "Fetching Fossil repository $url at revision $rev..." >&2 # Clone the repository -fossil clone -A nobody "$url" "$tmpPath/fossil-clone.fossil" >&2 +fossil clone -A $(whoami) "$url" "$tmpPath/fossil-clone.fossil" >&2 # Create directory for checkout checkoutDir="$tmpPath/checkout"