libstore: ban unpacking case hacked filenames from NARs

There is absolutely no good reason these should show up in NARs besides
misconfigured systems and as long as the case hack exists, unpacking
such a NAR will cause its repacking to be wrong on systems with case
hack enabled.

This should not have any security impact on Lix to fix, but it was one
of the vectors for CVE-2024-45593:
https://github.com/NixOS/nix/security/advisories/GHSA-h4vv-h3jq-v493

Change-Id: I85b6075aacc069ee7039240b0f525804a2d8edcb
This commit is contained in:
jade 2024-10-04 23:33:46 -07:00
parent 3571817e3a
commit 822997bd34
2 changed files with 15 additions and 10 deletions

View file

@ -270,7 +270,13 @@ static Generator<Entry> parseObject(Source & source, const Path & path)
co_yield MetadataString{name};
if (name.empty() || name == "." || name == ".."
|| name.find('/') != std::string::npos
|| name.find((char) 0) != std::string::npos)
|| name.find((char) 0) != std::string::npos
// The case hack is a thing that only exists on the
// filesystem.
// Unpacking one appearing in a NAR is super
// sketchy because it will at minimum cause corruption at
// the time of repacking the NAR.
|| name.find(caseHackSuffix) != std::string::npos)
{
throw Error("NAR contains invalid file name '%1%'", name);
}

View file

@ -60,15 +60,14 @@ EVIL_NARS: list[tuple[str, NarItem]] = [
(b'meow', Regular(False, b'kbityy'))
])),
])),
# FIXME: ban casehacked filenames being extracted from NARs
# ('invalid-casehack-1', Directory([
# (b'ZZZ~nix~case~hack~2', Regular(False, b'meow')),
# (b'zzz~nix~case~hack~1', Regular(False, b'eepy')),
# ])),
# ('invalid-casehack-2', Directory([
# (b'ZZZ~nix~case~hack~1', Regular(False, b'meow')),
# (b'zzz~nix~case~hack~1', Regular(False, b'eepy')),
# ])),
('invalid-casehack-1', Directory([
(b'ZZZ~nix~case~hack~2', Regular(False, b'meow')),
(b'zzz~nix~case~hack~1', Regular(False, b'eepy')),
])),
('invalid-casehack-2', Directory([
(b'ZZZ~nix~case~hack~1', Regular(False, b'meow')),
(b'zzz~nix~case~hack~1', Regular(False, b'eepy')),
])),
]
@pytest.mark.parametrize(['name', 'nar'], EVIL_NARS)