Skip to Content
FlakeBOM

FlakeBOM

Access to FlakeBOM is granted as part of our Determinate Secure Packages offering. Contact us at sales@determinate.systems to discuss terms of access or schedule a demo.

FlakeBOM provides a quick and reliable way to generate SBOMs from Nix flakes. At Determinate Systems, we use it routinely audit the software that we use in production environments.

Though you can use it on any flake, and with any version of Nix, FlakeBOM provides the most information when used in conjunction with Determinate Nix and Determinate Secure Packages.

FlakeBOM currently generates JSON SBOMs that follow the CycloneDX v1.5 specification.

Usage

To quickly generate an SBOM, invoke the flakebom command inside the directory that contains your flake, or point it to an absolute path of a different flake. By default, this generates an SBOM that contains:

  • All components referenced by your flake’s outputs, including all of their dependencies. If a component has metadata that FlakeBOM understands, it’s also included (for example license information).
  • Vulnerability exchange (VEX) information for any patches that have been found during scanning, including which component(s) they apply to

In addition to the above, FlakeBOM can include a number of optional data within the final SBOM, depending on the arguments that are provided:

  • --dependencies: Documents dependency relationships under the dependencies key.
  • --experimental-features purls: Adds in the package URL (pURL) for certain language-specific components (such as PyPI or cargo).
  • --should-realise: This makes FlakeBOM realise (build) derivations as it comes across them. When attempting to retrieve provenance information, this only works if the derivation exists locally. This option exists to guarantee that this be the case.

For more information about FlakeBOM’s different options, run flakebom --help locally.

Note that to make use of functionality related to store provenance, you need to run Determinate Nix on your system.

Options for comprehensive coverage

To ensure that your final SBOM contains the most amount of information, we recommend enabling all of the above options when invoking flakebom:

flakebom --dependencies --experimental-features purls --should-realise

In addition to running FlakeBOM with the above options, it is also necessary to meet the following prerequisites so that the derivations in your Nix store actually do have provenance information:

  1. Use Determinate Nix on all machines involved in the build process, as provenance is currently not available in other Nix distributions.

  2. Enable provenance by including the following in your custom Determinate Nix config:

    /etc/nix/nix.custom.conf
    extra-experimental-features = provenance

    Or, alternatively, by including the following in your NixOS configuration:

    { nix.settings.extra-experimental-features = "provenance"; }
  3. Use a binary cache that preserves the Provenance: field in the narinfo, for example FlakeHub Cache

  4. Use Determinate Secure Packages, as it automatically populates the provenance properties for the packages it provides with identifying information.

Why is this necessary?

While FlakeBOM aims to collect as many components as possible via evaluating the Nix expressions directly, this only works for those that are declared behind one of the “standard” attributes for inputs, like buildInputs, nativeBuildInputs, etc. If a derivation references another store path through a different method, for example by way of using something like ${lib.getExe someDerivation} inside its buildPhase, this isn’t detected at eval time.

These types of components do show up in the derivation’s closure however, which is how FlakeBOM is able to learn of them. Provenance helps to bridge the gap in these scenarios, by attaching identifying information to store derivations, such that tools like FlakeBOM can still access information about things like licenses, package identifiers, or VEX metadata, without having to know how to evaluate the derivation’s Nix expression.

Since provenance requires a derivation to be present locally, we recommend running FlakeBOM with --should-realise. Note that this does not mean the derivation has to be built locally, and running FlakeBOM with --should-realise will attempt to fetch derivations from your configured binary cache(s) by default.

Quick tips

Specific outputs

Sometimes generating an SBOM for all flake outputs is not desirable. In this case, you can tell FlakeBOM to only include specific attributes using the -a argument. For example, you can generate an SBOM only for specific packages:

# Only generate an SBOM for the `default` package on x86_64-linux flakebom -a packages.x86_64-linux.default # Generate an SBOM for multiple packages on x86_64-linux flakebom -a packages.x86_64-linux.foo -a packages.x86_64-linux.bar

Different systems

By default, FlakeBOM generates an SBOM for outputs that match the current system. If you want to include outputs from a different system, or perhaps multiple systems, you can make use of the --system argument:

# Generate an SBOM for components used on aarch64-linux, # even if we're on x86_64-linux or aarch64-darwin, etc. flakebom --system aarch64-linux # Generate an SBOM for multiple Linux systems flakebom --system aarch64-linux --system x86_64-linux

Additional VEX metadata

FlakeBOM already includes some VEX information by default, however, if you want to add in your own metadata, for example because you’ve done your own independent analysis of certain vulnerabilities, you can do so. The --merge-vex argument accepts a path to a CycloneDX v1.5 JSON SBOM containing VEX information under the vulnerabilities key:

flakebom --merge-vex ./path/to/my/sbom.cdx.json

Customizing package discovery

FlakeBOM discovers components for SBOM inclusion by inspecting your flake’s schema. The default schema already includes commonly recognized flake outputs like packages and checks, but if your flake provides derivations under different top-level outputs, FlakeBOM will only pick up on them if these outputs are correctly represented within your flake’s schema.

Additionally, FlakeBOM will recurse your schema’s output until its deepest level, so you can replicate upstream Nixpkgs’ package set convention, for example.

Note that by default, the legacyPackages output is not inspected by FlakeBOM, as evaluating it is expensive, since it requires recursing into nested attribute sets. To override this behavior and include the output in your SBOM, you may run FlakeBOM with the --legacy argument. Be warned though that this may result in significantly longer inspection times, depending on the complexity and depth of your flake outputs.

If you require recursive component inspection, the recommended approach is to supply your own flake schema instead of relying on the legacyPackages output.

Integration with Determinate Secure Packages

Determinate Secure Packages (DSP) includes a large set of additional metadata related to package and vulnerability identification that is currently not available in upstream nixpkgs. FlakeBOM includes this metadata by default, so to ensure that the final SBOM is as accurate as possible, we recommend using DSP as your nixpkgs flake input.

Additionally, DSP provides provenance metadata for all covered packages, which ensures FlakeBOM can obtain all important information, even from derivations that it doesn’t encounter during eval.

Last updated on