Introduction
Hello,
My organization handles many docker images and I am trying to introduce Nix as an alternative method for building these images. One of the steps in introducing a new container to our registry is scanning for vulnerabilities using tools similar to Grype.
I figured the easiest way to insert a Nix based container into this pipeline would be to generate an SBOM and then use that SBOM with Grype to obtain an initial POC. My problem comes from the fact that I can’t seem to find a combination of SBOM generators and vulnerability scanners that will detect vulnerabilities in python packages included with a python environment. Let me illustrate with a simple example.
The package
I’ve arbitrarily chosen a package called python-multipart
which is vulnerable to GHSA-59g5-xgcq-4qw3 and is on both GitHub’s Security Advisory and NVD. I picked a nixpkgs revision corresponding to version 0.0.9
using Nix package versions.
Bombon
My first approach was to see if I could use @nikstur 's bombon with the following snippet
let
python = pkgs.python3.withPackages (
p: with p; [
python-multipart
]
);
in
{
packages = {
default = python;
sbom = bombon.lib.${system}.buildBom python { };
};
}
Bombon successfully captures the package in the SBOM
{
"type": "application",
"bom-ref": "dhmdrknyskqn7p4qci8w9l9rrpcysmr0-python3.12-python-multipart-0.0.9",
"name": "python3.12-python-multipart-0.0.9",
"version": "",
"scope": "required",
"purl": "pkg:nix/python3.12-python-multipart-0.0.9"
}
but when I run the SBOM through Grype I don’t get any vulnerabilities.
$ grype sbom:./result
✔ Vulnerability DB [updated]
✔ Scanned for vulnerabilities [0 vulnerability matches]
├── by severity: 0 critical, 0 high, 0 medium, 0 low, 0 negligible
└── by status: 0 fixed, 0 not-fixed, 0 ignored
No vulnerabilities found
A newer version of grype is available for download: 0.94.0 (installed version is 0.92.2)
I imagine this is because Nix is not yet defined as part of the PURL spec. I think the previous issue is most likely on hold due to @fricklerhandwerk 's Nixpkgs supply chain security project - #32 by fricklerhandwerk and @YorikSar 's work on adding CPEs (Common Platform Enumerations) to nix packages meta attribute as pointed out by @fricklerhandwerk at the bottom of the previously mentioned thread.
Syft
Syft also mentions that it has the capability to capture Nix packages in SBOMs so I tried the same approach as Bombon in first generating an SBOM and then sending it through Grype.
$ syft ./result
✔ Indexed file system /nix/store/236s9a8wc3p378hbm80bjrd4ml61ihd8-python3-3.12.5-env
✔ Cataloged contents f6a214f7a5fcda0c2cee9660b7fc29f5649e3c68aad48e20e950137c98913a68
├── ✔ Packages [0 packages]
└── ✔ Executables [14 executables]
[0000] WARN no explicit name and version provided for directory source, deriving artifact ID from the given path (which is not ideal)
No packages discovered
Syft doesn’t discover any packages
Sbomnix
Sbomnix also has the ability to generate SBOMs from nix store paths.
$ grype sbom:sbom.cdx.json
✔ Scanned for vulnerabilities [6 vulnerability matches]
├── by severity: 1 critical, 2 high, 3 medium, 0 low, 0 negligible
└── by status: 6 fixed, 0 not-fixed, 0 ignored
[0000] WARN invalid CPE: cpe:2.3:a:python3-3.12.5-env:python3-3.12.5-env::*:*:*:*:*:*:*
NAME INSTALLED FIXED-IN TYPE VULNERABILITY SEVERITY EPSS% RISK
openssl 3.0.14 1.0.2zk, 1.1.1za, 3.0.15, 3.1.7, 3.2.3, ... nix CVE-2024-5535 Critical 89.39 4.7
openssl 3.0.14 3.0.15, 3.1.7, 3.2.3, 3.3.2 nix CVE-2024-6119 High 62.89 0.3
openssl 3.0.14 1.0.2zl, 1.1.1zb, 3.0.16, 3.1.8, 3.2.4, ... nix CVE-2024-9143 Medium 60.81 0.2
sqlite 3.46.0 3.49.1 nix CVE-2025-3277 Medium 26.56 < 0.1
sqlite 3.46.0 3.49.1 nix CVE-2025-29087 High 13.33 < 0.1
openssl 3.0.14 1.0.2zl, 1.1.1zb, 3.0.16, 3.1.8, 3.2.4, ... nix CVE-2024-13176 Medium 13.19 < 0.1
A newer version of grype is available for download: 0.94.0 (installed version is 0.92.2)
This time the system dependencies report vulnerabilities however the python vulnerabilities are still left out. Looking inside the generated sbom.cdx.json
we can see why. Even though sbomnix is able to guess the CPEs, because Grype does not use CPEs, no vulnerabilities are found once again.
{
"type": "library",
"bom-ref": "/nix/store/ibqys8vnd6n15s5abfp9rg81nv13871k-python3.12-python-multipart-0.0.9.drv",
"name": "python3.12-python-multipart",
"version": "0.0.9",
"purl": "pkg:nix/python3.12-python-multipart@0.0.9",
"cpe": "cpe:2.3:a:python3.12-python-multipart:python3.12-python-multipart:0.0.9:*:*:*:*:*:*:*",
"description": "A streaming multipart parser for Python",
"licenses": [
{
"license": {
"id": "Apache-2.0"
}
}
],
"properties": [
{
"name": "nix:output_path",
"value": "/nix/store/dhmdrknyskqn7p4qci8w9l9rrpcysmr0-python3.12-python-multipart-0.0.9"
},
{
"name": "nix:drv_path",
"value": "/nix/store/ibqys8vnd6n15s5abfp9rg81nv13871k-python3.12-python-multipart-0.0.9.drv"
},
{
"name": "homepage",
"value": "https://github.com/andrew-d/python-multipart"
}
]
},
Vulnix
With the sbom options exhausted I tried to use the nix based vulnerability scanners as a last ditch effort even though I need to use SBOMs with my organization’s scanners.
In this case vulnix also does not identify any python dependencies
$ vulnix ./result
8 derivations with active advisories
------------------------------------------------------------------------
binutils-2.42
/nix/store/y5mx8497y389bwdwjl8sswn31zfci7zi-binutils-2.42.drv
CVE CVSSv3
https://nvd.nist.gov/vuln/detail/CVE-2025-0840 7.5
------------------------------------------------------------------------
curl-8.9.1
/nix/store/qw7wyz0zjdhzk90ciy8yxb3d6zpjlpn4-curl-8.9.1.drv
CVE CVSSv3
https://nvd.nist.gov/vuln/detail/CVE-2024-9681 6.5
https://nvd.nist.gov/vuln/detail/CVE-2025-0725
https://nvd.nist.gov/vuln/detail/CVE-2025-4947
------------------------------------------------------------------------
gcc-13.3.0
/nix/store/2paz2p74ndfi046qgrmii12fvrbpk4ax-gcc-13.3.0.drv
CVE CVSSv3
https://nvd.nist.gov/vuln/detail/CVE-2023-4039 4.8
------------------------------------------------------------------------
glibc-2.39-52
/nix/store/0fj9hk6x5yprg4v9l2b0g4fp1bnchalz-glibc-2.39-52.drv
CVE CVSSv3
https://nvd.nist.gov/vuln/detail/CVE-2024-33599
https://nvd.nist.gov/vuln/detail/CVE-2024-33600
https://nvd.nist.gov/vuln/detail/CVE-2024-33601
https://nvd.nist.gov/vuln/detail/CVE-2024-33602
------------------------------------------------------------------------
openssl-3.0.14
/nix/store/dk90k06afxlyvzrclkv6r57s2k6hb0q7-openssl-3.0.14.drv
CVE CVSSv3
https://nvd.nist.gov/vuln/detail/CVE-2024-6119 7.5
------------------------------------------------------------------------
perl-5.38.2
/nix/store/qcvhn33qbvkfxnxnjnzvsr1rgc9yrzk7-perl-5.38.2.drv
CVE CVSSv3
https://nvd.nist.gov/vuln/detail/CVE-2024-56406
------------------------------------------------------------------------
sqlite-3.46.0
/nix/store/53z81gf6p4v2q0cqagsk52sxf3f729aa-sqlite-3.46.0.drv
CVE CVSSv3
https://nvd.nist.gov/vuln/detail/CVE-2025-29087 7.5
------------------------------------------------------------------------
zlib-1.3.1
/nix/store/2ksxw3mkxlxr7l00fqvfgf3v1jnzzm7m-zlib-1.3.1.drv
CVE CVSSv3
https://nvd.nist.gov/vuln/detail/CVE-2023-6992 5.5
Vulnxscan
vulnxscan comes from the sbomnix repo and similarly does not yield any python dependencies.
$ nix run github:tiiuae/sbomnix#vulnxscan -- ./result
INFO Evaluating './result'
INFO Try force-realising store-path './result'
INFO Generating SBOM for target '/nix/store/236s9a8wc3p378hbm80bjrd4ml61ihd8-python3-3.12.5-env'
INFO Loading runtime dependencies referenced by '/nix/store/236s9a8wc3p378hbm80bjrd4ml61ihd8-python3-3.12.5-env'
INFO Running vulnix scan
INFO Running grype scan
INFO Running OSV scan
INFO Querying vulnerabilities
INFO Filtering patched vulnerabilities
INFO CVE-2024-5535 for 'openssl' is patched with: ['/nix/store/a2l99gf3kh2da9amplpvgxnqg7bn6ni7-CVE-2024-5535.patch']
INFO Console report
Potential vulnerabilities impacting version_local:
| vuln_id | url | package | version_local | severity | grype | osv | vulnix | sum |
|-----------------------+-------------------------------------------------+-----------+-----------------+------------+---------+-------+----------+-------|
| BIT-sqlite-2025-29087 | https://osv.dev/BIT-sqlite-2025-29087 | sqlite | 3.46.0 | | 0 | 1 | 0 | 1 |
| CVE-2025-29087 | https://nvd.nist.gov/vuln/detail/CVE-2025-29087 | sqlite | 3.46.0 | 7.5 | 1 | 0 | 1 | 2 |
| BIT-sqlite-2025-3277 | https://osv.dev/BIT-sqlite-2025-3277 | sqlite | 3.46.0 | | 0 | 1 | 0 | 1 |
| CVE-2025-3277 | https://nvd.nist.gov/vuln/detail/CVE-2025-3277 | sqlite | 3.46.0 | 6.9 | 1 | 0 | 0 | 1 |
| CVE-2024-33602 | https://nvd.nist.gov/vuln/detail/CVE-2024-33602 | glibc | 2.39-52 | | 0 | 0 | 1 | 1 |
| CVE-2024-33601 | https://nvd.nist.gov/vuln/detail/CVE-2024-33601 | glibc | 2.39-52 | | 0 | 0 | 1 | 1 |
| CVE-2024-33600 | https://nvd.nist.gov/vuln/detail/CVE-2024-33600 | glibc | 2.39-52 | | 0 | 0 | 1 | 1 |
| CVE-2024-33599 | https://nvd.nist.gov/vuln/detail/CVE-2024-33599 | glibc | 2.39-52 | | 0 | 0 | 1 | 1 |
| CVE-2024-13176 | https://nvd.nist.gov/vuln/detail/CVE-2024-13176 | openssl | 3.0.14 | 4.1 | 1 | 0 | 0 | 1 |
| CVE-2024-9143 | https://nvd.nist.gov/vuln/detail/CVE-2024-9143 | openssl | 3.0.14 | 4.3 | 1 | 0 | 0 | 1 |
| CVE-2024-6119 | https://nvd.nist.gov/vuln/detail/CVE-2024-6119 | openssl | 3.0.14 | 7.5 | 1 | 0 | 1 | 2 |
| BIT-sqlite-2024-0232 | https://osv.dev/BIT-sqlite-2024-0232 | sqlite | 3.46.0 | | 0 | 1 | 0 | 1 |
| CVE-2023-6992 | https://nvd.nist.gov/vuln/detail/CVE-2023-6992 | zlib | 1.3.1 | 5.5 | 0 | 0 | 1 | 1 |
| CVE-2023-4039 | https://nvd.nist.gov/vuln/detail/CVE-2023-4039 | gcc | 13.3.0 | 4.8 | 0 | 0 | 1 | 1 |
| MAL-2022-4301 | https://osv.dev/MAL-2022-4301 | libidn2 | 2.3.7 | | 0 | 1 | 0 | 1 |
| RUSTSEC-2019-0006 | https://osv.dev/RUSTSEC-2019-0006 | ncurses | 6.4.20221231 | | 0 | 1 | 0 | 1 |
INFO Wrote: /home/collin/projects/minimal_nix_container/vulns.csv
Conclusion/Question
This post is not intended to be a slight on any of the tools being used. After doing a bunch of research on this topic, I can see that properly identifying packages is quite the difficult task.
I’m still left wondering if I’m doing something wrong or if there is some flag I need to add somewhere to include some metadata on these python dependencies to allow them to be picked up by vuln scanners. I’m not sure how other organizations keep track of there vulnerabilities with Nix so if someone could shed some light on this subject I would greatly appreciate it.
If anything I hope this can be a useful user story
Reference flake
{
description = "Demonstration of vuln scanners with nix";
inputs = {
python-multipart-nixpkgs.url = "github:nixos/nixpkgs?rev=ab7b6889ae9d484eed2876868209e33eb262511d";
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
flake-parts.url = "github:hercules-ci/flake-parts";
bombon.url = "github:nikstur/bombon";
};
outputs =
inputs@{
self,
nixpkgs,
python-multipart-nixpkgs,
flake-parts,
bombon,
}:
flake-parts.lib.mkFlake { inherit inputs; } {
systems = [ "x86_64-linux" ];
perSystem =
{
pkgs,
self',
system,
...
}:
let
python = python-multipart-nixpkgs.legacyPackages.${system}.python3.withPackages (
p: with p; [
python-multipart
]
);
in
{
packages = {
default = python;
sbom = bombon.lib.${system}.buildBom python { };
};
devShells.default = pkgs.mkShell {
packages = with pkgs; [
python
syft
grype
vulnix
];
};
};
};
}