How to do vulnerability scanning with Nix SBOMS?

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 :frowning_face:

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 :smile:

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
            ];
          };
        };
    };
}
3 Likes

To clarify, @RaitoBezarius proposal for adding Nix to the PURL spec is not competing with the currently ongoing proposal to encode CPE information in Nixpkgs expressions, this is different people working independently on various parts of the puzzle.

2 Likes

Ah, thank you for the clarification. The whole space for security seems like quite the dragon!