sbom() looks at what a folder holds, builds the SBOM from the strongest
source it finds, and reads every other source to check it. It runs no code
from the project and makes no network requests, except that, with Nix
installed, a default.nix is read by running nix-instantiate (see
sbom_nix()), which may download nixpkgs, that snapshot looks up a
CRAN snapshot, and that advisories = TRUE downloads OSV's advisory data.
Arguments
- path
A project folder.
- ...
Named arguments for the reader that
sbom()picks: any argument ofsbom_renv(),sbom_rsconnect(),sbom_nix()(such asnixandsnapshot) orsbom_package()other than the file or folder it reads, such aslibrary,lib,dependencies,r_version,author,overridesoradvisories. The code scan takeslib,author,organization,regid,timestamp,overrides,embedded,system,advisoriesandadvisories_on_error. A Shiny app also takesevaluate_ui(seesbom_shiny()), which other folders ignore. A name that no reader takes is an error. The reader ignores those it does not take, except that the cross-checks ofDESCRIPTIONand the code also uselib. Overrides, given or fromsbom-overrides.csv, apply to the SBOM after the cross-checks, which compare what the sources say, and advisories are matched after the overrides.
Value
An <sbom> object. See sbom_components() to read it.
Details
The sources, from strongest to weakest:
renv.lock, read bysbom_renv().manifest.json, read bysbom_rsconnect(), when it is a Posit Connect manifest: one withversionandpackages, whose packages and files are objects.default.nix, read bysbom_nix(). A file that rix wrote lists the packages it names, without versions, unlesssnapshotis given or Nix is installed and the environment is built: then it is read from the Nix store, with versions. With Nix installed but the environment not built, the file itself is read, with an issue. A hand-written file can be read only with Nix.DESCRIPTION, read bysbom_package(), when it has aPackagefield.The R code itself, scanned with
renv::dependencies(). Each package it uses is looked up inliband listed at the version installed there, as inferred; one that is not installed is listed as unknown, with an issue. renv itself, which renv infers from arenv.lock, is left out, and so is the code in any subfolder that holds its ownrenv.lock,DESCRIPTIONormanifest.json, a project of its own. In a package folder, so are test fixtures and snapshots,inst/extdataand the files.Rbuildignoreexcludes. The root is the folder, an application named after it, with its git commit as the version. This is the weakest evidence, and a note says so.
A folder that is a Shiny app (see sbom_shiny()) is described by
sbom_shiny(), which sbom() calls for it. That includes a folder with
app.R, or ui.R and server.R, even when it also has a DESCRIPTION
without golem structure.
The strongest source present makes the SBOM. Every other source present,
and the code scan when the SBOM does not already come from it, are read
to cross-check it, and their disagreements become issues: a package that
one source lists and the other does not, or that they list at different
versions. A DESCRIPTION, the code, and a default.nix read without Nix
or a snapshot declare no versions, so they report only the packages they
use that the SBOM does not list. A DESCRIPTION
without a Package field is not a package, so it is used only to
cross-check the packages its Depends and Imports name. A source that
cannot be read for a cross-check, or a manifest.json that is not a
Posit Connect manifest, is an issue, not an error. So is a hand-written
default.nix that sbom cannot read, even when it is the strongest source:
one on a machine without Nix, or, under the default nix = NA, one that
Nix fails to evaluate or whose environment has not been built. A warning
says so, and the SBOM is built from the next source. Any other failure to
read the strongest source, such as nix = TRUE on a machine without Nix,
is an error. A cross-check reads default.nix with nix as given (by
default, Nix is used when it is installed, and nix = FALSE never calls
it) and without a snapshot. Under nix = TRUE, a default.nix that Nix
cannot read is an error even as a cross-check. When Nix runs for that
cross-check and cannot read the environment, its issue is carried into the
SBOM.
A project folder's git commit is read from the files in the nearest
.git in it or a folder above it, without running git. A folder that is
not in a git repository, or whose commit cannot be read, has no version,
with an issue.
When the folder holds sbom-overrides.csv and overrides is not given,
that file is applied as the overrides.
Advisories, when asked for with advisories, are matched once, with the
SBOM, after the overrides (and, for a Shiny app, after the app's own
components are added). The cross-checks never read advisory data. See
sbom_package() for what is matched and what is sent.
The inputs element of the SBOM's metadata lists every source read.
Examples
x <- sbom(sbom_example("connect-app"), system = FALSE)
x
#> <sbom> connect-app
#> Components: 9
#> Relationships: 8
#> Issues: 9 (see sbom_issues())
#> Advisories: not requested.
sbom_issues(x)
#> ref
#> 1 local/localpkg
#> 2 local/localpkg
#> 3 project/connect-app
#> 4 project/connect-app
#> 5 pkg:cran/biocpkg@1.2.3?repository_url=https://bioconductor.org/packages/3.22/bioc
#> 6 pkg:cran/glue@1.8.1?repository_url=https://packagemanager.posit.co/cran/latest
#> 7 local/localpkg
#> 8 unknown/ppmpkg
#> 9 project/connect-app
#> field severity code
#> 1 license warning license-no-spdx
#> 2 supplier warning supplier-unknown
#> 3 author info no-sbom-author
#> 4 library info drift-not-checked
#> 5 component warning drift-missing
#> 6 component warning drift-missing
#> 7 component warning drift-missing
#> 8 component warning drift-extra
#> 9 version warning version-missing
#> message
#> 1 The license of localpkg 0.0.1, file LICENSE, has no SPDX expression, so it is recorded as NOASSERTION.
#> 2 localpkg 0.0.1 was installed from a local source, so it has no supplier on record.
#> 3 No author or organization was given for this SBOM, so only the tool that made it is recorded.
#> 4 No project library was found, so the installed packages were not compared with renv.lock.
#> 5 biocpkg 1.2.3 is in renv.lock but not in manifest.json.
#> 6 glue 1.8.1 is in renv.lock but not in manifest.json.
#> 7 localpkg 0.0.1 is in renv.lock but not in manifest.json.
#> 8 ppmpkg 2.0.0 is in manifest.json but not in renv.lock.
#> 9 The project folder connect-app is not a git repository, so it has no version.