1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-09 20:16:03 +01:00

Add an owner check when searching for the flake root

When searching up the filesystem for the root of the flake (the
directory that contains the `flake.nix`), don’t go anywhere up if we
encounter a directory owned by a different user, as otherwise this other
user could craft an arbitrary flake, potentially causing bad stuff to
happen (shouldn’t in most cases since all it could do is run sanboxed
builds, but there’s probably a lot of edge-cases that would make this
very undesirable).

This is to fix Nix’s equivalent of CVE-2022-24765

This check is intentionnally not applied to the exact directory
specified since:
1. It’s up to the user to not point to an untrusted input
2. In multi-user Nix installations, that would prevent from using a
   flake in the Nix store (since it’s owned by root and not the current
   user)

Fix #6408
This commit is contained in:
Théophane Hufschmitt 2022-04-28 16:02:20 +02:00
parent f5e620bf2b
commit e5a211d77e
2 changed files with 11 additions and 5 deletions

View file

@ -1,3 +1,5 @@
# Release X.Y (202?-??-??)
- [`nix-channel`](../command-ref/nix-channel.md) now supports a `--list-generations` subcommand
* When searching upwards for the root of the flake, Nix doesnt consider
anything thats not owned by the current user anymore as its a
security hazard.

View file

@ -127,6 +127,8 @@ std::pair<FlakeRef, std::string> parseFlakeRefWithFragment(
// Save device to detect filesystem boundary
dev_t device = lstat(path).st_dev;
// Fix for the Nix equivalent of CVE-2022-24765
uid_t currentUser = geteuid();
bool found = false;
while (path != "/") {
if (pathExists(path + "/flake.nix")) {
@ -134,11 +136,13 @@ std::pair<FlakeRef, std::string> parseFlakeRefWithFragment(
break;
} else if (pathExists(path + "/.git"))
throw Error("path '%s' is not part of a flake (neither it nor its parent directories contain a 'flake.nix' file)", path);
else {
if (lstat(path).st_dev != device)
throw Error("unable to find a flake before encountering filesystem boundary at '%s'", path);
}
path = dirOf(path);
auto pathStat = lstat(path);
if (pathStat.st_dev != device)
throw Error("unable to find a flake before encountering filesystem boundary at '%s'", path);
if (pathStat.st_uid != currentUser) {
throw Error("unable to find a flake before encountering a directory not owned by us at '%s'", path);
}
}
if (!found)
throw BadURL("could not find a flake.nix file");