Skip to content

CPEs in package metadata for better vulnerability tracking #354012

@nikstur

Description

@nikstur

We should add a new standardized meta field called cpe that will contain a CPE (Common Platform Enumeration) string.

Why it's useful to have this

This enables tools like bombon that create SBOMs from arbitrary Nix derivations to insert this CPE for each package into the SBOM to enable (better) vulnerability tracking.

SBOMs that contain CPEs can be used to scan for vulnerabilities by tools like DependencyTrack, Grype, or nvdtools

This will also help Nixpkgs' upcoming security tracker.

Why we cannot automatically generate identifiers

  • sbomnix automatically generates CPEs and bombon automatically generates PURLs.
  • Automatically generating identifiers means guessing them (from pname, version, etc.) which is not sufficient for accurate vulnerability tracking.
  • Manually specifying them is the only way to achieve accurate enough results for useful tracking

Why CPEs over other identifiers

  • There are three main contender schemes: CPE, PURL, SWID
  • Compared to other identifiers (e.g. PURL or SWID), CPEs are canoncial. They are determined by the NVD (National Vulnerability Database) maintained by NIST. This makes it easy for contributors to manually determine the correct CPE (by searching the NVD) and add it to the metadata of a package.
  • CPEs do not depend on ecosystems (unlike PURL which requires a type field that identifies the package ecosystem, e.g. Debian or Fedora).
  • SWID seems to be hardly used and there is no CVE source that can actually be searched via SWIDs.

Implementation

I envision this to be an optional meta field. Something that maintainers who care about security can add but that does not have to be included. This field should be added to important packages over time by people that care about this information. I do not want this to be a hard requirement for new packages.

We could either populate this field directly by strings or add a library function (e.g. lib.mkCPE) that converts an attrset to the string representation.

Option 1:

meta = {
  cpe = "cpe:2.3:a:systemd_project:systemd:253:-:*:*:*:*:*:*";
};

Option 2:

meta = {
  cpe = lib.mkCPE {
    vendor = "systemd_project";
    product = pname;
    inherit version;
  };
};

Example CPE strings for systemd, glibc, openssl:

cpe:2.3:a:systemd_project:systemd:253:-:*:*:*:*:*:*
cpe:2.3:a:gnu:glibc:2.39:*:*:*:*:*:*:*
cpe:2.3:a:openssl:openssl:3.0.1:*:*:*:*:*:*:*

People that showed interest in this idea

@Mic92 @Lassulus @RaitoBezarius @arianvp @blitz

Metadata

Metadata

Assignees

No one assigned

    Labels

    0.kind: enhancementAdd something new or improve an existing system.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions