Security: Improve checking of build products
Build product paths cannot reference locations outside of the Nix store. We previously disallowed paths from being symlinks, but this didn't take into account that parent path elements can be symlinks as well. So a build product /nix/store/bla.../foo/passwd, with /nix/store/bla.../foo being a symlink to /etc, would still work. So now we check all paths encountered during path resolution. Symlinks are allowed again so long as they point to the Nix store.
This commit is contained in:
@ -170,10 +170,9 @@ sub defaultUriForProduct {
|
||||
|
||||
sub checkPath {
|
||||
my ($self, $c, $path) = @_;
|
||||
my $storeDir = $Nix::Config::storeDir . "/";
|
||||
error($c, "Invalid path in build product.")
|
||||
if substr($path, 0, length($storeDir)) ne $storeDir || $path =~ /\/\.\./;
|
||||
error($c, "Path ‘$path’ is a symbolic link.") if -l $path;
|
||||
my $path = pathIsInsidePrefix($path, $Nix::Config::storeDir);
|
||||
error($c, "Build product refers outside of the Nix store.") unless defined $path;
|
||||
return $path;
|
||||
}
|
||||
|
||||
|
||||
@ -203,7 +202,7 @@ sub download : Chained('build') PathPart {
|
||||
$path .= "/" . join("/", @path) if scalar @path > 0;
|
||||
|
||||
# Make sure the file is in the Nix store.
|
||||
checkPath($self, $c, $path);
|
||||
$path = checkPath($self, $c, $path);
|
||||
|
||||
# If this is a directory but no "/" is attached, then redirect.
|
||||
if (-d $path && substr($c->request->uri, -1) ne "/") {
|
||||
@ -247,7 +246,7 @@ sub contents : Chained('build') PathPart Args(1) {
|
||||
|
||||
my $path = $product->path;
|
||||
|
||||
checkPath($self, $c, $path);
|
||||
$path = checkPath($self, $c, $path);
|
||||
|
||||
notFound($c, "Product $path has disappeared.") unless -e $path;
|
||||
|
||||
|
Reference in New Issue
Block a user