Skip to content

Guardrails / Collectors

Software bill of materials ​

The components a build says it ships, read from the bill of materials it already wrote (CycloneDX or SPDX, in JSON, XML or tag-value) and normalized into one list with the licence each component names.

Facts keysbom
Versionv1
Scriptsbom.py
Timeout60 seconds

Inputs ​

InputDescriptionDefaultEnvironment
reportsComma separated globs matched against every file in the working directory and against bare file names, naming the bills of materials to read.bom.json,bom.xml,*.cdx.json,*.cdx.xml,cyclonedx*.json,cyclonedx*.xml,sbom*.json,*.spdx.json,sbom*.spdxGUARDRAIL_INPUT_REPORTS
maxComponentsMaximum number of components to carry in the facts. The counts still include components that are dropped.500GUARDRAIL_INPUT_MAXCOMPONENTS

When a guardrail declares an input with the same name, it passes its value through. That means you set these values in the guardrail's configuration in buildnote.json.

A guardrail asks for these facts by name and reads them back by the same name:

json
{
  "collect": ["sbom"]
}
python
sbom = guardrail.facts("sbom")

Facts ​

These are the fields of the document sbom collects. In a path, [] means each entry of the list before it, and [path] means a key of the object before it.

FactMeaning
sourcereport when a bill of materials was read, none when there was none.
reasonWhy nothing was read, present only when source is none.
reportsEvery bill of materials that was read, in path order.
reports[].pathPath of the bill of materials, relative to the directory the CLI runs in.
reports[].modifiedWhen it was last written, ISO 8601, so a bill of materials older than the build is recognisable.
reports[].formatFormat it was read as: cyclonedx or spdx.
formatFormat of the first bill of materials read, cyclonedx or spdx. Each report carries its own in reports[].format.
specVersionSpecification version that first bill of materials declares, such as 1.5 or SPDX-2.3, or null when it declares none.
counts.totalComponents across every bill of materials that was read.
counts.licensedComponents naming at least one licence.
counts.unlicensedComponents naming none.
licensesLicence identifier to the number of components naming it. A component naming two licences counts under both.
componentsThe components themselves, up to maxComponents.
components[].nameName of the component, as the bill of materials names it.
components[].versionVersion of the component, empty when it carries none.
components[].purlPackage URL of the component, or null when it carries none.
components[].typeWhat the component is, such as library, application or container, or null.
components[].licensesEvery licence the component names, by identifier or expression.
droppedComponents left out because maxComponents was reached.

If a collector can't finish, it prints what it gathered so far along with an incomplete key that says why. Facts after the point where it stopped are missing, so a check that depends on them should read incomplete first.

Example facts ​

Here are the facts the sbom collector gathers from an example project:

json
{
  "source": "report",
  "reports": [
    {
      "path": "bom.json",
      "modified": "2026-03-04T10:15:00Z",
      "format": "cyclonedx"
    }
  ],
  "format": "cyclonedx",
  "specVersion": "1.5",
  "counts": {
    "total": 4,
    "licensed": 3,
    "unlicensed": 1
  },
  "licenses": {
    "Apache-2.0": 2,
    "MIT": 1
  },
  "components": [
    {
      "name": "http4k-core",
      "version": "6.57.2.0",
      "purl": "pkg:maven/org.http4k/http4k-core@6.57.2.0",
      "type": "library",
      "licenses": [
        "Apache-2.0"
      ]
    },
    {
      "name": "slf4j-api",
      "version": "2.0.13",
      "purl": "pkg:maven/org.slf4j/slf4j-api@2.0.13",
      "type": "library",
      "licenses": [
        "MIT"
      ]
    },
    {
      "name": "guava",
      "version": "33.2.0-jre",
      "purl": "pkg:maven/com.google.guava/guava@33.2.0-jre",
      "type": "library",
      "licenses": [
        "Apache-2.0"
      ]
    },
    {
      "name": "logback-classic",
      "version": "1.5.6",
      "purl": "pkg:maven/ch.qos.logback/logback-classic@1.5.6",
      "type": "library",
      "licenses": []
    }
  ],
  "dropped": 0
}

Collected for ​

GuardrailCategoryInputs
supply-chain/components-licensedsupply-chainnone
supply-chain/disallowed-componentssupply-chainnone
supply-chain/disallowed-licensessupply-chainnone
supply-chain/sbom-presentsupply-chainnone
supply-chain/sbom-standard-formatsupply-chainnone

All collectors

Buildnote Limited
Registered in England and Wales, Reg: 16140412