sbom_nix() describes the software that a default.nix written by the
rix package declares: R, R packages, packages from git or from the CRAN
archive, Nix system packages and TeX Live. Without Nix it reads the file as
text, runs no code from it and makes no network request unless you pass
snapshot. With Nix installed it reads the environment from the Nix store
instead; see Nix mode. advisories = TRUE also downloads OSV's advisory
data.
Usage
sbom_nix(
path = "default.nix",
nix = NA,
snapshot = NULL,
library = NULL,
author = getOption("sbom.author"),
organization = getOption("sbom.organization"),
regid = getOption("sbom.regid"),
timestamp = NULL,
overrides = NULL,
embedded = TRUE,
system = TRUE,
advisories = FALSE,
advisories_on_error = c("error", "continue")
)Arguments
- path
The path to the Nix file, usually
default.nix.- nix
Whether to use Nix to read the file.
NAuses Nix when it is installed,TRUErequires it andFALSEreads the file as text. See Details.- snapshot
NULL,"ppm", or the path or URL of a CRANPACKAGESfile, to look the package versions up in. The lookup uses the network only whensnapshotis given. See Details.- library
Library paths to read what the file does not record from. Each must exist.
NULLreads none.Who made the SBOM, recorded in its metadata.
authormay name several people;NAand empty names are dropped. Without either, an issue is recorded.- regid
The registration id of
organization: the domain name, or URL, of the organization, under which it registers SWID tags (ISO/IEC 19770-2). A SWID tag names the organization as its creator with this regid. It must be a single string, from which leading and trailing white space is dropped.NULL,NAand an empty or blank string mean none; then the tag uses the placeholderhttp://invalid.unavailable, and when anorganizationwas given, an issue is recorded. The default is thesbom.regidoption, asauthorandorganizationreadsbom.authorandsbom.organization.- timestamp
The creation time, as a date-time or as seconds since 1970-01-01 UTC. An explicit
timestampwins. Without one, theSOURCE_DATE_EPOCHenvironment variable is used when it is set, so that builds are reproducible, and a note says so; otherwise it is now. Nix setsSOURCE_DATE_EPOCHto 1980-01-01 in everynix-shell, and when the timestamp is that value a note says it is a placeholder.- overrides
Values to assert where
sbomfound none, or found something different.NULL, a data frame or the path to a CSV file, with the character columnscomponent(thenameorrefof one component, as sbom built it, before any row moves it; embedded and system components only byref),field,value,asserted_byandreason.fieldis one of"version","license_spdx","supplier_name","supplier_url","maintainer","purl"and"download_location". Rows are applied in order, and each is recorded with who asserted it and why. An override that contradicts a found value wins and adds anoverride-conflictissue. Asserting"version"makes it the exact version, and moves the component's package URL to it unless a row asserts the"purl": a package URL at the old version takes the new one, and one without a version gains it when its type iscran,github,gitlaborbitbucket. A package file named for the old version is renamed for the new one, and any other is dropped, as are the checksums of the version found. An asserted version of R is also the version of the base packages, each with a record of the assertion. Asserting a CRAN"purl"(pkg:cran) makes the component a CRAN package, or a Bioconductor package when itsrepository_urlnames bioconductor.org. When a component'srefis its package URL, thereffollows the package URL that the overrides leave, and every reference to it moves too; arefthat another component already has is an error. Any otherref, such asunknown/<name>, stays as it is. An asserted field removes the component's issues that it answers, such asversion-missingorpurl-inferred. An issue that also states a fact that stays true is reworded instead, as info: that a package came from a git repository, once its package URL is asserted; that a dependency is missing, once its version and package URL are both asserted; and that aLinkingTopackage is not installed, once its version is. The issues that name the components without a version, such assystem-version-unknown, name only those still without one, and go when none is left. A blank value, an unknown component or field, or a missing column, is an error.- embedded
Whether to record the code that packages carry inside them. A package named in
LinkingTois recorded as an embedded component of the package that compiles it in, nested under that package, as inferred, at the version and with the license that the library, lockfile or manifest records for it now. A C or C++ library that a package copies into itssrc/folder (source packages), or names in itsCOPYRIGHTSfile orcphentries (source and installed packages), is recorded as a vendored component of that package, from the rules ininst/extdata/vendored.csv. The version is read from the library's header when there is one, and is otherwise unknown. A JavaScript or CSS library declared in htmlwidgets YAML, or found by the header comment of a file underwww/,htmlwidgets/lib/orlib/(underinst/in source packages), is recorded as an npm component of that package, from the rules ininst/extdata/javascript.csv. Its license is not read.- system
Whether to detect system libraries. A package's
SystemRequirementstext is mapped to system libraries and programs with the rules of the pak package, when it is installed. sbom turns off pak's update of those rules, so pak uses the rules it has cached or ships and makes no network request. The shared libraries that installed compiled code links are read withotool(macOS) orldd(Linux).- advisories
Whether to list the OSV security advisories for the SBOM's packages, from the R Consortium advisory database that OSV publishes; see
sbom_advisories(). Only exact versions are compared, of the packages whose package URL is a CRAN one (pkg:cran), packages from CRAN-like repositories among them, matched by name. A package with a CRAN package URL and a minimum version, or none, is named in anadvisories-no-exact-versionissue. An R package that is not known to come from CRAN, because sbom could not tell where it came from (as for a package that is not installed), or because it was installed from a local source or from GitHub, GitLab, Bitbucket or git, is named in anadvisories-not-cranissue. Bioconductor packages are not compared: OSV does not cover them yet, and when the SBOM holds one a note says so. Matching is local, with the versions and package URLs afteroverrides, so no package name leaves the machine.FALSE, the default, lists none, makes no network request and adds a note that no advisory data was on hand.TRUEdownloads OSV's CRAN export,https://osv-vulnerabilities.storage.googleapis.com/CRAN/all.zip, and looks up the CVSS ratings of the upstream records it names athttps://api.osv.dev, sending only their public ids. On a machine without network access, download thatall.zipelsewhere and pass its path: it is read where it is, without the network and without ratings.The SBOM lists what OSV says about these exact versions: a package without an advisory is not shown to be free of flaws, and an upstream CVSS rating describes the upstream flaw, not how exposed the R package is.
- advisories_on_error
What happens when the advisory data cannot be downloaded or read, as when the download fails or the zip is damaged:
"error", the default, is an error of classsbom_advisories_errorthat names the problem;"continue"builds the SBOM without advisories, with an R warning of classsbom_advisories_unavailable, a warning issue and a note that no advisory data was on hand. A download larger than 50 MB is refused as an error too. A CVSS rating that cannot be looked up never fails the call: it is left out, with an issue. The lookups stop at the first that times out or fails at the connection, and take at most two minutes in all.
Value
An <sbom> object. See sbom_components() to read it.
Details
Nix mode
With Nix installed (nix-instantiate and nix-store on the path),
sbom_nix() evaluates the file, takes the inputs of its shell and reads
the runtime closure of their outputs from the Nix store. It is the only
way to read a hand-written Nix file. It runs nix-instantiate, which
evaluates the file and may download nixpkgs, so unlike the static read it
can use the network, through Nix. snapshot is not used. It records:
R, and each R package (every store path named
r-<name>), labeled observed, at the version in its store path or, when the path has none, in itsDESCRIPTIONin the store. A package's license and maintainer come from thatDESCRIPTIONwhen it is readable.A package that a file written by rix fetches from git or from the CRAN archive is described as in the static read below (its package URL, download location and description), with the version from the store. Any other package comes from the repository its
DESCRIPTIONnames. One whoseDESCRIPTIONnames none, or cannot be read, is taken to be the CRAN package of that name, with no supplier, and an issue says that its package URL is inferred.Every other store path as a component
nix/<name>of ecosystemnix, with the version in its store path and a description that names it. The outputs of one derivation (curl,curl-libandcurl-dev) are one component. One issue lists the store paths, and the R packages, that have no version.Dependencies from the references graph of the store:
Importsto an R package,Dependsto R,dynamic_linkto a Nix library (one that has aliboutput or a name starting withlib) andsystem_requirementto any other Nix package. The root points to the direct inputs of the shell. An issue counts any reference that sbom could not place.
Nix mode is experimental. It is built on the output formats documented for Nix 2.18 and later, and its tests use recorded examples of that output rather than a Nix installation.
nix = NA reads the store when Nix is installed and the file otherwise.
nix = TRUE requires Nix and is an error without it, or when Nix cannot
evaluate the file. nix = FALSE always reads the file, as below.
If none of the outputs of an input of the shell is in the store, because the
environment has not been built, sbom reads the file instead and adds the issue nix-not-built:
build the environment with nix-shell or nix-build first. For a
hand-written file there is nothing to fall back to, and that is an error.
library is not read in Nix mode, and system has no effect, since the
closure already holds the system packages.
Without Nix
Without Nix, sbom reads only files that rix generated, which it knows by their header comment. A hand-written Nix file is an error: it needs Nix.
What the static mode records:
The project folder, the folder of the file, is the root.
R, at the version of rix's
r_verwhen it is a version, as declared. Otherwise R has no version, and an issue says so.Each R package that the file names, by name only. These come from a nixpkgs snapshot that the file pins, but the file does not say which version that snapshot holds, so their versions are unknown and one issue says so. nixpkgs'
rPackagesholds Bioconductor packages as well as CRAN ones, so each is taken to be the CRAN package of that name, with no supplier, and one issue says that their package URLs are inferred.Packages that rix fetches from git, and from the CRAN archive. An archive package has the version in its file name, as declared. A git package has no version, but its URL and revision are recorded in its description, and a GitHub package has a package URL that names the revision. The R packages they depend on are listed as their dependencies. Their URLs are recorded without a user name, password, query string or fragment, which can hold tokens.
Each Nix system package, such as
glibcLocalesornix, as a componentnix/<name>of ecosystemnixwith no version and no package URL, since the package URL specification has nonixtype. TeX Live is one component,nix/texlive, whose description names the TeX packages. These are recorded whateversystemis, because the file declares them.A note on where the packages come from: the rstats-on-nix snapshot of a date, or a nixpkgs commit.
The sha256 values in the file are Nix's hashes of the unpacked source,
not hashes of a file, so they are written in a package's description and
never as a file hash. Python and Julia packages that the file installs are
not listed, and an issue says so.
Looking up versions
Apart from advisories, snapshot is the only way sbom_nix() uses the
network, and it does so only when you pass it. It looks the versions up in
a CRAN PACKAGES file:
NULL, the default, looks nothing up and makes no network request."ppm"reads the CRAN snapshot that Posit Package Manager keeps for the date of the pinned nixpkgs,https://packagemanager.posit.co/cran/<date>/src/contrib/PACKAGES. It works only when nixpkgs is pinned to a date; for a commit, an issue says so and nothing is looked up.A path or URL of a
PACKAGESfile reads that file instead.
Each CRAN package that the file names without a version takes the version
the snapshot lists, and sbom follows Depends, Imports and LinkingTo
in the snapshot to add the packages that Nix would install with it. The
versions and the added packages and dependencies are labeled inferred,
since the snapshot is a stand-in for what Nix installed. R, base and
recommended packages are left to R's own handling. Archive packages keep
the version in their URL, and git packages stay without a version. A
package that the snapshot lists is a CRAN package. One that it lacks,
named by the file or by a snapshot package's dependencies, may not be one,
so it is listed without a version or package URL, with an issue. If the
snapshot cannot be read, an issue says so. A snapshot given as a URL is
named in the notes by that URL, without its credentials, query string or
fragment, and a local file by its name.
library, embedded and system apply as for sbom_renv(), to the
packages whose version the file declares and that are installed in
library at that version. The installed copy fills in what the file
lacks: the license and maintainer. Without library, nothing is read from
an installed copy. One issue lists the packages left without a license or
maintainer.
Examples
nix <- file.path(tempdir(), "default.nix")
writeLines(c(
"# This file was generated by the {rix} R package v0.18.6 on 2026-11-05",
"# >rix(r_ver = \"4.4.1\")",
"let",
paste0(
" pkgs = import (fetchTarball ",
"\"https://github.com/rstats-on-nix/nixpkgs/archive/2024-10-01.tar.gz\") {};"
),
" rpkgs = builtins.attrValues {",
" inherit (pkgs.rPackages) dplyr data_table;",
" };",
"in rpkgs"
), nix)
sbom_nix(nix, nix = FALSE, system = FALSE)
#> <sbom> RtmpSDwKp5
#> Components: 4
#> Relationships: 2
#> Issues: 5 (see sbom_issues())
#> Advisories: not requested.
if (FALSE) { # \dontrun{
# Needs the network: looks the package versions up in a CRAN snapshot.
sbom_nix(nix, nix = FALSE, system = FALSE, snapshot = "ppm")
} # }