VULNIX(1)
π VULNIX(1) β the vulnix manual, bestie edition β¨
okay so you're reading vulnix(1), the User Commands page for everybody's favorite Nix(OS) vulnerability scanner. grab a snack, this is gonna be good π
β¨ NAME β¨
vulnix β a Nix(OS) vulnerability scanner. that's it, that's the vibe check π
πΈ SYNOPSIS πΈ
vulnix [OPTIONS] --system
vulnix [OPTIONS] PATH ...
π¦ DESCRIPTION π¦
so here's the whole thing: vulnix goes digging through Nix derivations and their transitive closure, hunting for vulnerable software versions as published in the NIST NVD. when it finds affected derivations it reports them, together with the matching CVE identifiers. no cap, that's the entire point π
the last argument is where the search starts, and it can be any one of these:
- a derivation, like
/nix/store/0123456789-program-1.0.drv - an output file in the Nix store that has a known deriver
- a link into the Nix store, like
result
before the actual scanning begins, parts of the NIST NVD database get fetched and parsed. that database copy is cached between vulnix invocations and gets checked at regular intervals, so it's not re-downloading the world every time π
also? vulnix uses whitelists to mask certain combinations of packages and CVEs that straight up should not be reported. iconic behavior honestly.
π OPTIONS π
-g,--guest=PATHβ scan a foreign Nix installation rooted atPATH. heads up bestie: paths you pass as positional arguments or with--profilehave to be absolute paths as seen inside the guest, like/nix/store/...or/nix/var/nix/profiles/defaultβ they are not host paths. and--system/--gc-rootslikewise inspect the guest installation. π«Ά-S,--systemβ scans the current system, defined as the transitive closure of/run/current-system. the classic.-G,--gc-rootsβ scans all active garbage collection roots. ngl this one is of limited use, because the scan will include all old system generations. you've been warned π-p,--profile=PATHβ scan a nix profile (eg:/nix/var/nix/profiles/per-user/$USER/profile,~/.nix-profile). these are typically created withnix-env -iornix profile installβ but notnix build --profile, which creates normal store paths that don't need this special handling. subtle but important β¨-f,--from-file=FILEβ scans derivations read from a file. expects one derivation path like/nix/store/*.drvper line. super useful together with-R/--no-requisites, which means that exactly the specified derivations will be scanned π-w,--whitelist=FILE | URLβ loads a whitelist from the specified local path or URL. checkvulnix-whitelist(5)for the whitelist syntax explanation. and no stress: it is not an error if the path/URL does not exist. this option can be given multiple times (stack 'em, queen) π-W,--write-whitelist=FILEβ writes a new copy of the whitelist containing all reported vulnerable package versions in addition to existing whitelist entries (the ones loaded with-w). use it to evolve your whitelists so every vulnerable version gets reported exactly once. note: expired whitelist entries (like ones where the date set with theuntiloption has passed) will not be written into the new whitelist π-r,--requisites/-R,--no-requisitesβ decides whether the transitive closure of the specified paths gets computed and scanned, or only the given pathnames. defaults to--requisites. the whole "closure or nah" question πΈ-c,--cache-dir=DIRECTORYβ puts cached NVD entries intoDIRECTORY. the directory gets created if it doesn't exist. defaults to~/.cache/vulnixβ-m,--mirror=URLβ fetches NIST NVD updates fromURL. defaults tohttps://nvd.nist.gov/feeds/json/cve/1.1/π₯-j,--jsonβ outputs affected package versions as a JSON document. see JSON output below π-s,--show-whitelistedβ shows whitelisted results in addition to regular (non-whitelisted) results. iykyk π§-v,--verboseβ prints additional info on stderr, including NVD updates, derivation paths, and clickable links to CVE advisories. may be given twice for an extra level of debugging information. double it and give it to the next person π-V,--versionβ prints program version and exits π--helpβ prints options summary and exits π
π EXIT STATUS π
the exit statuses are compatible with the Nagios plugin development guidelines, https://nagios-plugins.org/doc/guidelines.html β which means you can drop this straight into the majority of monitoring systems. slay for CI.
vulnixexits 0 if no vulnerabilities are found π- if all of the shown vulnerabilities are whitelisted, it exits 1
- otherwise, found vulnerabilities lead to exit status 2
- exit status 3 indicates an error condition π
β οΈ note that exit status 1 may never occur if the --show-whitelisted option is not given. literally cannot happen. plot twist.
π ENVIRONMENT π
these environment variables affect vulnix, bestie:
HOMEβ determines the default cache directory.PATHβ used to invoke up low-level Nix utilities likenix-store.
π«Ά FILES π«Ά
vulnix maintains a cache dir located at ~/.cache/vulnix by default.
the Nix store is assumed to be under /nix/store. this pathname is hardcoded β no, you can't change it, don't ask π
π NOTES π
Patch detection
vulnix tries to detect patches for specific CVEs, and these get automatically excluded from reports. the way that works: the patches field of each derivation is scanned for names containing CVE identifiers. if a single patch fixes multiple vulnerabilities, all the relevant CVE identifiers should go in the patch name, separated by arbitrary non-numerical characters. see EXAMPLES below β¨
JSON output
when invoked with --json, a JSON document consisting of a list of dicts is written to stdout. each list item is an affected derivation and contains these keys:
nameβ package name and versionpnameβ package name without versionversionβ version onlyaffected_byβ list of applicable CVE identifierswhitelistedβ list of CVE identifiers which are masked by whitelist entriesderivationβ pathname of the scanned derivation filecvssv3_basescoreβ dict of CVSS v3 impact base scores for each CVE found
π BUGS π
invoking vulnix with an empty cache directory can take quite a while, since it needs to download and process NIST NVD archives of the last 5 years. once initialized, only changed entries get fetched. so likeβ¦ go get a beverage β
also the cache directory grows slowly but steadily, as there are new CVE advisories added on an ongoing basis. it's not a bug it's a lifestyle π±
π§ COMPATIBILITY π§
vulnix is known to parse derivation files created by Nix versions up to 2.3.
π₯ EXAMPLES π₯
Is my NixOS system vulnerable?
vulnix --system
Scan the output of nix-build(1) for dependencies with security advisories:
nix-build ... -o result
vulnix result
Report advisories for a derivation and its transitive closure as a structured JSON document:
vulnix -j /nix/store/cm0lrdrf6crb5v38iyygfsbzvivpmh6w-python3-3.6.4.drv
Report all advisories affecting the NixOS base install, whitelisting formerly known vulnerabilities and creating an updated whitelist (a.k.a. vulnerability roundup):
nix-build -I nixpkgs=. nixos/release-combined.nix
vulnix -j \
-w https://raw.githubusercontent.com/ckauhaus/nixos-vulnerability-roundup/master/whitelists/master.toml \
-W whitelist-master-new.toml \
result
An excerpt from a derivation source that applies a patch against CVE-2018-9055. note the name attribute, which contains a CVE identifier:
patches = [
(fetchpatch {
name = "CVE-2018-9055.patch";
url = http://paste.opensuse.org/view/raw/330751ce;
sha256 = "0m798m6c4v9yyhql7x684j5kppcm6884n1rrb9ljz8p9aqq2jqnm";
})
];
if the patch fixes two vulnerabilities, it could be named CVE-2018-9055+CVE-2018-9600.patch, for example. see? told you π
π SEE ALSO π
vulnix-whitelist(5), nix-store(1), nix-build(1), NIST NVD https://nvd.nist.gov, Nix https://nixos.org/nix/
and that's the page!! π mwah π«Ά
this has been Version 1.12.5, dated January 1980 (yes really, the copyright date said January 1980, we don't question the icons) β VULNIX(1), out. β¨π
π¦ where this page comes from
- nixpkgs unstable: vulnix 1.12.5
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms