From 5acf50a327b18f39c7b97f58d9724a4771c47cff Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 12 Jun 2025 11:04:07 +0200 Subject: [PATCH] Disallow the build directory having world-writable parents --- src/libstore/unix/build/derivation-builder.cc | 15 +++++++++++++++ tests/nixos/chroot-store.nix | 4 ++++ 2 files changed, 19 insertions(+) diff --git a/src/libstore/unix/build/derivation-builder.cc b/src/libstore/unix/build/derivation-builder.cc index a036c95f1..b089a0169 100644 --- a/src/libstore/unix/build/derivation-builder.cc +++ b/src/libstore/unix/build/derivation-builder.cc @@ -698,6 +698,18 @@ static void handleChildException(bool sendException) } } +static bool checkNotWorldWritable(std::filesystem::path path) +{ + while (true) { + auto st = lstat(path); + if (st.st_mode & S_IWOTH) + return false; + if (path == path.parent_path()) break; + path = path.parent_path(); + } + return true; +} + void DerivationBuilderImpl::startBuilder() { /* Make sure that no other processes are executing under the @@ -729,6 +741,9 @@ void DerivationBuilderImpl::startBuilder() createDirs(buildDir); + if (buildUser && !checkNotWorldWritable(buildDir)) + throw Error("Path %s or a parent directory is world-writable or a symlink. That's not allowed for security.", buildDir); + /* Create a temporary directory where the build will take place. */ topTmpDir = createTempDir(buildDir, "nix-build-" + std::string(drvPath.name()), 0700); diff --git a/tests/nixos/chroot-store.nix b/tests/nixos/chroot-store.nix index f89a20bc4..0a4fff992 100644 --- a/tests/nixos/chroot-store.nix +++ b/tests/nixos/chroot-store.nix @@ -41,5 +41,9 @@ in # Test that /nix/store is available via an overlayfs mount. machine.succeed("nix shell --store /tmp/nix ${pkgA} --command cowsay foo >&2") + + # Building in /tmp should fail for security reasons. + err = machine.fail("nix build --offline --store /tmp/nix --expr 'builtins.derivation { name = \"foo\"; system = \"x86_64-linux\"; builder = \"/foo\"; }' 2>&1") + assert "is world-writable" in err ''; }