1
From Generation to Distribution
Practical Software Bill of Materials
Follow along at tinyurl.com/SBOM-Workshop
Software Engineering @ Carabiner
2
Adolfo García Veytia
Puerco
Follow along at tinyurl.com/SBOM-Workshop
CTO @ Kusari
3
Michael Lieberman
Follow along at tinyurl.com/SBOM-Workshop
Lockheed Martin OSPO
4
Ian Dunbar-Hall
Follow along at tinyurl.com/SBOM-Workshop
5
Generation
Sharing
Operations
Topics
Better
Follow along at tinyurl.com/SBOM-Workshop
Most SBOMs today are lack meaningful details. Let’s change that with a couple additional steps
6
Small changes are a huge improvement
Better SBOM Generation
7
SBOM Producer Life Cycle
Generation
Augmentation
Enrichment
Verification
Signing
Document Linking
Generate an SBOM with any of your favor tools
(choice doesn’t really matter)
8
Generation
Augmentation
Enrichment
Verification
Signing
Document Linking
What’s Missing?
These might be different for the SBOM document and top level component
As the Software Producer, you are the person who should be defining this information!
9
Generation
Augmentation
Enrichment
Verification
Signing
Document Linking
{
"bomFormat": "CycloneDX",
"specVersion": "1.6",
"serialNumber": "urn:uuid:12d218d3-382…",
"version": 1,
"metadata": {
"timestamp": "2025-03-24T06:05:27+00:00",
"tools": {
…
},
"component": {
"bom-ref": "3d9e6d32-875e-4a4e-81c4-f09415892df8",
"type": "application",
"name": "keycloak-25.0.4",
"properties": [
{
"name": "aquasecurity:trivy:SchemaVersion",
"value": "2"
}
]
}
},
Augmentation
10
Generation
Augmentation
Enrichment
Verification
Signing
Document Linking
Augment Document Metadata
11
Generation
Augmentation
Enrichment
Verification
Signing
Document Linking
sbomasm edit \
--subject Document \
--author 'VulnCon SBOM Workshop' \
--supplier 'keycloak (https://www.keycloak.org/)' \
--lifecycle 'pre-build' \
--repository 'https://github.com/keycloak/keycloak' \
--license 'Apache-2.0 (https://raw.githubusercontent.com/…/LICENSE.txt)' \
original-sbom.cdx.json > augmented-doc-sbom.cdx.json
`sbomasm` approach
Augment Top Level Component Metadata
12
Generation
Augmentation
Enrichment
Verification
Signing
Document Linking
sbomasm edit \
--subject primary-component \
--author 'VulnCon SBOM Workshop' \
--supplier 'keycloak (https://www.keycloak.org/)' \
--repository 'https://github.com/keycloak/keycloak' \
--license 'Apache-2.0 (https://raw.githubusercontent.com/…/LICENSE.txt)' \
augmented-doc-sbom.cdx.json > augmented-sbom.cdx.json
`sbomasm` approach
We now have …
13
{
…
"metadata": {
"timestamp": "2025-03-24T06:05:38+00:00",
"lifecycles":[{ "phase": "pre-build"}],
"tools": {…},
"authors": [{"name": "VulnCon SBOM Workshop"}],
"component": {
"type": "application",
"supplier": {
"name": "keycloak",
"url": ["https://www.keycloak.org/"]},
"authors": [
{"name": "CISA Tiger Group for SBOM Generation Reference Implementations"}],
"name": "keycloak-25.0.4",
"licenses": [
{
"license": {
"id": "Apache-2.0",
"name": "Apache License 2.0",
Generation
Augmentation
Enrichment
Verification
Signing
Document Linking
`sbomasm` approach
Static SBOM json document
14
Generation
Augmentation
Enrichment
Verification
Signing
Document Linking
{
"metadata": {
"component": {
"copyright": "bomctl a Series of LF Projects, LLC",
"description": "bomctl is format-agnostic Software Bill of Materials (SBOM) tooling, which is intended to bridge the gap between SBOM generation and SBOM analysis tools. It focuses on supporting more complex SBOM operations by being opinionated on only supporting the NTIA minimum fields or other fields supported by protobom.",
"externalReferences": [
{
"type": "documentation",
"url": "https://github.com/bomctl/bomctl"
},
{
"type": "vcs",
"url": "https://github.com/bomctl/bomctl.git"
},
{
"type": "license",
"url": "https://github.com/bomctl/bomctl/blob/main/LICENSE"
},
{
"type": "chat",
"url": "https://slack.openssf.org/#bomctl"
}
]
},
"licenses": [
{
"license": {
"id": "Apache-2.0",
"url": "https://raw.githubusercontent.com/bomctl/bomctl/main/LICENSE"
}
}
],
"lifecycles": [
{
"phase": "build"
}
],
"manufacture": {
"name": "bomctl a Series of LF Projects, LLC",
"url": ["https://github.com/bomctl/bomctl"]
},
"supplier": {
"name": "bomctl a Series of LF Projects, LLC",
"url": ["https://github.com/bomctl/bomctl"]
}
}
}
Merge approach
Merge with JQ
15
Generation
Augmentation
Enrichment
Verification
Signing
Document Linking
jq --slurp '.[0] * .[1]' "original-sbom.cdx.json" "metadata.json" > "augmented-sbom.cdx.json"
Merge approach
Enrichment
16
Generation
Augmentation
Enrichment
Verification
Signing
Document Linking
Enrichment with `parlay`
17
Generation
Verification
Signing
Document Linking
parlay ecosystems enrich \
augmented-sbom.cdx.json > enriched-sbom.cdx.json
Augmentation
Enrichment
18
Generation
Verification
Signing
Document Linking
Augmentation
Enrichment
{
"bom-ref": "00230f0a-d031-4ab5-953e-fe732cddca0c",
"type": "library",
"group": "org.yaml",
"name": "snakeyaml",
"version": "2.0",
"purl": "pkg:maven/org.yaml/snakeyaml@2.0"
}
{
"bom-ref": "00230f0a-d031-4ab5-953e-fe732cddca0c",
"type": "library",
"group": "org.yaml",
"name": "snakeyaml",
"version": "2.0",
"description": "YAML 1.1 parser and emitter for Java",
"licenses": [{"expression": "Apache-2.0"}],
"purl": "pkg:maven/org.yaml/snakeyaml@2.0",
"externalReferences": [
{ "url": "https://bitbucket.org/snakeyaml/snakeyaml",
"type": "website"},
{"url": "https://repo.maven.apache.org/maven2/org/yaml/snakeyaml/",
"type": "distribution"},
{ "url": "https://appdoc.app/artifact/org.yaml/snakeyaml/",
"type": "documentation"}],
"properties": [
{ "name": "ecosystems:first_release_published_at",
"value": "2010-03-08T12:26:25Z"},
{ "name": "ecosystems:latest_release_published_at",
"value": "2025-02-15T10:54:50Z"}
]
}
Verification
19
Generation
Verification
Signing
Document Linking
Augmentation
Enrichment
20
sbomqs score "enriched-sbom.cdx.json"
Generation
Verification
Signing
Document Linking
Augmentation
Enrichment
SBOM Quality by Interlynk Score:8.3 components:4027 enriched-sbom.cdx.json
+-----------------------+--------------------------------+-----------+--------------------------------+
| CATEGORY | FEATURE | SCORE | DESC |
+-----------------------+--------------------------------+-----------+--------------------------------+
| NTIA-minimum-elements | comp_with_name | 10.0/10.0 | 4027/4027 have names |
+ +--------------------------------+-----------+--------------------------------+
| | comp_with_supplier | 6.8/10.0 | 2721/4027 have supplier names |
+ +--------------------------------+-----------+--------------------------------+
| | comp_with_uniq_ids | 10.0/10.0 | 4027/4027 have unique ID's |
+ +--------------------------------+-----------+--------------------------------+
| | comp_with_version | 6.3/10.0 | 2538/4027 have versions |
+ +--------------------------------+-----------+--------------------------------+
| | sbom_authors | 10.0/10.0 | doc has 2 authors |
+ +--------------------------------+-----------+--------------------------------+
| | sbom_creation_timestamp | 10.0/10.0 | doc has creation timestamp |
| | | | 2025-03-24T06:05:38+00:00 |
+ +--------------------------------+-----------+--------------------------------+
| | sbom_dependencies | 10.0/10.0 | doc has 170 dependencies |
+-----------------------+--------------------------------+-----------+--------------------------------+
| Quality | comp_valid_licenses | 9.4/10.0 | 3790/4027 components with |
| | | | valid license |
+ +--------------------------------+-----------+--------------------------------+
…
Comparing Generated vs Final
21
Generation
Verification
Signing
Document Linking
Augmentation
Enrichment
+-----------------------+--------------------------------+-------------------+--------------------------------------+
| CATEGORY | FEATURE |SCORE (Gen / Final)| DESC |
+-----------------------+--------------------------------+-------------------+--------------------------------------+
| NTIA-minimum-elements | comp_with_name | 10.0 / 10.0 | 4028/4028 → 4027/4027 have names |
| | comp_with_supplier | 0.0 / 6.8 | 0/4028 → 2721/4027 have supplier |
| | comp_with_uniq_ids | 10.0 / 10.0 | 4028/4028 → 4027/4027 unique IDs |
| | comp_with_version | 6.3 / 6.3 | 2539/4028 → 2538/4027 have versions |
| | sbom_authors | 10.0 / 10.0 | 1 → 2 authors |
| | sbom_creation_timestamp | 10.0 / 10.0 | Timestamp updated |
| | sbom_dependencies | 10.0 / 10.0 | 170 dependencies |
+-----------------------+--------------------------------+-------------------+--------------------------------------+
| Quality | comp_valid_licenses | 2.0 / 9.4 | 815/4028 → 3790/4027 valid licenses |
| | comp_with_any_vuln_lookup_id | 9.6 / 9.6 | 3857/4028 → 3856/4027 have lookup id |
| | comp_with_deprecated_licenses | 10.0 / 9.9 | 0/4028 → 41/4027 deprecated licenses |
| | comp_with_multi_vuln_lookup_id | 0.0 / 0.0 | 0/4028 → 0/4027 have multiple IDs |
| | comp_with_primary_purpose | 10.0 / 10.0 | 4028/4028 → 4027/4027 primary purpose|
| | comp_with_restrictive_licenses | 10.0 / 10.0 | 0/4028 → 0/4027 restricted licenses |
| | sbom_with_creator_and_version | 10.0 / 10.0 | 1/1 tools have creator/version |
| | sbom_with_primary_component | 10.0 / 10.0 | Primary component found |
+-----------------------+--------------------------------+-------------------+--------------------------------------+
| Semantic | comp_with_checksums | 0.0 / 0.0 | 0/4028 → 0/4027 have checksums |
| | comp_with_licenses | 2.0 / 9.4 | 815/4028 → 3790/4027 have licenses |
| | sbom_required_fields | 10.0 / 10.0 | Required fields present |
+-----------------------+--------------------------------+-------------------+--------------------------------------+
| Structural | sbom_parsable | 10.0 / 10.0 | SBOM is parsable |
| | sbom_spec | 10.0 / 10.0 | Valid SBOM format |
| | sbom_spec_file_format | 10.0 / 10.0 | Valid file format |
| | sbom_spec_version | 10.0 / 10.0 | Supported spec version |
+-----------------------+--------------------------------+-------------------+--------------------------------------+
Visualize the SBOM Data
22
Generation
Verification
Signing
Document Linking
Augmentation
Enrichment
unpack sbom enriched-sbom.cdx.json
Naming Conventions
23
23
Generation
Verification
Signing
Document Linking
Augmentation
Enrichment
Standard + Format | Artifact Filename | SBOM Filename |
CycloneDX JSON | artifact-1.0.0.tar.gz | artifact-1.0.0.tar.gz.cdx.json |
CycloneDX XML | artifact-1.0.0.tar.gz | artifact-1.0.0.tar.gz.cdx.xml |
SPDX TAG:VALUE | artifact-1.0.0.tar.gz | artifact-1.0.0.tar.gz.spdx |
SPDX JSON | artifact-1.0.0.tar.gz | artifact-1.0.0.tar.gz.spdx.json |
SPDX XML | artifact-1.0.0.tar.gz | artifact-1.0.0.tar.gz.spdx.xml |
SPDX YAML | artifact-1.0.0.tar.gz | artifact-1.0.0.tar.gz.spdx.yml (or .yaml) |
Signing with `cosign`
24
Generation
Verification
Signing
Document Linking
Augmentation
Enrichment
cosign sign-blob kubectl-v0.31.1.cdx.json \
--output-certificate=kubectl-v0.31.1.cdx.json.pem \
--output-signature=kubectl-v0.31.1.cdx.json.sig
https://search.sigstore.dev/?logIndex=192544291
Attesting the SBOMs
25
Generation
Verification
Signing
Document Linking
Augmentation
Enrichment
Subject
Name: kubectl-v1.31.tar.gz
sha256:2387468236
Predicate
Type: SPDX/CycloneDX
Signed Envelope
bnd predicate kubectl-v0.31.1.cdx.json \
--type=https://cyclonedx.org/bom \
--subject-file=/tmp/kubectl.tgz \
--out=kubectl-v0.31.1.cdx.bundle.json
Packing in a Verifiable Bundle
26
Generation
Verification
Signing
Document Linking
Augmentation
Enrichment
{"mediaType":"application/vnd.dev.sigstore.bundl
{"mediaType":"application/vnd.dev.sigstore.bundl
bnd predicate kubectl-v0.31.1.cdx.json \
--type=https://cyclonedx.org/bom \
--subject-file=/tmp/kubectl.tgz \
--out=kubectl-v0.31.1.cdx.bundle.json
Generation Summary
27
Generation
Verification
Signing
Document Linking
Augmentation
Enrichment
Used `trivy` to generate an SBOM
Used `sbomasm` to augment top level metadata
Used `parlay` to enrich with component metadata
Used `sbomsm` to verify sbom completeness
Used `cosign` to sign the final sbom and store signature in Public Rekor
Skipped and could be an entirely separate workshop
github.com/SBOM-Community/SBOM-Generation
So … I generated an SBOM
where do I put it?
28
SBOM Sharing
Maturing Landscape Today
29
See CISA SBOM Sharing Primer
cisa.gov/resources-tools/resources/sbom-sharing-primer
(Commercial) Publish on portal/product page, and in distribution
30
Publishing
Retrieve
Redistribution
Verification
Signature Verification
31
Publishing
Retrieve
Redistribution
Verification
cosign verify-blob kubectl-v0.31.1.cdx.json \
--certificate kubectl-v0.31.1.cdx.json.pem \
--signature kubectl-v0.31.1.cdx.json.sig \
--certificate-identity-regexp='.*' \
--certificate-oidc-issuer-regexp='.*'
Signature Verification
Verify the attestation signature
32
Publishing
Retrieve
Redistribution
Verification
cosign verify-blob kubectl-v0.31.1.cdx.json \
--certificate kubectl-v0.31.1.cdx.json.pem \
--signature kubectl-v0.31.1.cdx.json.sig \
--certificate-identity-regexp='.*' \
--certificate-oidc-issuer-regexp='.*'
cat kubectl-v0.31.1.cdx.json.pem | base64 -d - | openssl x509 -text
Signature Verification
33
Publishing
Retrieve
Redistribution
Verification
cosign verify-blob kubectl-v0.31.1.cdx.json \
--certificate kubectl-v0.31.1.cdx.json.pem \
--signature kubectl-v0.31.1.cdx.json.sig \
--certificate-identity-regexp='.*' \
--certificate-oidc-issuer-regexp='.*'
cat kubectl-v0.31.1.cdx.json.pem | base64 -d - | openssl x509 -text
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature
X509v3 Extended Key Usage:
Code Signing
X509v3 Subject Key Identifier:
CE:5A:80:BC:.....
X509v3 Authority Key Identifier:
DF:D3:E9:CF:.....
X509v3 Subject Alternative Name: critical
email:puerco@carabiner.dev
1.3.6.1.4.1.57264.1.1:
https://accounts.google.com
1.3.6.1.4.1.57264.1.8:
..https://accounts.google.com
Attestation Verification
Verify the attestation signature
34
Publishing
Retrieve
Redistribution
Verification
cosign verify-blob kubectl-v0.31.1.cdx.json \
--certificate kubectl-v0.31.1.cdx.json.pem \
--signature kubectl-v0.31.1.cdx.json.sig \
--certificate-identity-regexp='.*' \
--certificate-oidc-issuer-regexp='.*'
bnd verify --skip-identity \
kubectl-v0.31.1.cdx.bundle.json
Retrieving SBOMs with `bomctl`
35
bomctl fetch https://raw.git…_v0.3.0.cdx.json
bomctl list
Publishing
Retrieve
Redistribution
Verification
Exporting SBOMs with `bomctl`
36
bomctl export \
https://anchore.com/syft…397e701fa#DOCUMENT
bomctl export -f cyclonedx \
https://anchore.com/syft…397e701fa#DOCUMENT
Publishing
Retrieve
Redistribution
Verification
Pushing SBOMs with `bomctl`
37
bomctl push -f spdx \
Urn:uuid:f360ad8b-dc41-4256-afed-337a04dff5db \
oci://${BOMCTL_PORT_URL}/hello-bomctl:latest
Publishing
Retrieve
Redistribution
Verification
Generation Summary
38
Publishing
Retrieve
Redistribution
Overview of publishing options
Used `bomctl` to retrieve SBOMs and display them in different formats
Used `bomctl` to redistribute an SBOM to an OCI registry
Verification
Verified Signatures & Attestations�Learned to inspect a sigstore certificate
SBOMs are more than just a document for compliance. They can be used for analyzing risks.
39
SBOMs are Useless if Just Left in a Bucket
Operations
Operational Maturity
40
Operational Outcomes
41
NOTE: Some of the examples below uses an SBOM data storage and API system called GUAC. Tools like GUAC require the running of multiple persistent services. That will take too long to explain for this workshop so for more details on how to set this up yourself see the below QR code:
GUAC
42
43
Collection
Ingestion
Correlation
Analysis
$ curl -LO https://raw.githubusercontent.com/SBOM-Community/VulnCon-SBOM-Workshop/refs/heads/main/examples/scalibr.spdx.json
$ cat scalibr.spdx.json�{
"spdxVersion": "SPDX-2.3",
"dataLicense": "CC0-1.0",
"SPDXID": "SPDXRef-DOCUMENT",
"name": "SCALIBR-generated SPDX",
"documentNamespace": "https://spdx.google/c0420d75-96e8-4233-9013-6af13c4e6c6a",...
Action
This can be optional
Tools
44
Collection
Ingestion
Correlation
Analysis
$ guacone collect --add-vuln-on-ingest --add-eol-on-ingest --add-license-on-ingest files ��VulnCon-SBOM-Workshop/examples�{"level":"info","ts":1684774157.098919,"caller":"cmd/files.go:167","msg":"[2.054952875s] completed doc {Collector:FileCollector Source:file:///../VulnCon-SBOM-Workshop/examples/scalibr.spdx.json}"}�…
Action
Example uses GUAC
Previous example used GUAC, with the --add-vuln-on-ingest, --add-eol-on-ingest, and --add-license-on-ingest flags. These flags pull in additional data about the software found in SBOMs for correlation.
Correlation is different from SBOM Enrichment!
OSV-Scanner can be used to scan an SBOM for vulnerability info.
45
Collection
Ingestion
Correlation
Analysis
$ osv-scanner scan --sbom scalibr.spdx.json --format vertical
Total 8 packages affected by 13 known vulnerabilities (0 Critical, 3 High, 10 Medium, 0 Low, 0 Unknown) from 1 ecosystem.
13 vulnerabilities can be fixed.
npm
sbom:/Users/mlieberman/Projects/fosdem-demo/sboms/scalibr.spdx.json: found 8 packages with issues
@babel/runtime@7.24.5 has the following known vulnerabilities:
GHSA-968p-4wvh-cqc8: Babel has inefficient RexExp complexity in generated code with .replace when... (https://osv.dev/GHSA-968p-4wvh-cqc8) …
Action
DuckDB can be used to run SQL-like syntax against data from various sources (e.g. files).
You can run queries like this example to understand differences and commonalities between SBOMs.
46
Collection
Ingestion
Correlation
Analysis
$ duckdb�D CREATE TABLE sbom AS
· SELECT * FROM read_json_auto('*.json', auto_detect=true, maximum_object_size="333554428");�D SELECT DISTINCT package.unnest.name AS package_name
· FROM
· sbom,
‣ UNNEST(packages) AS package;��┌──────────────────────────────────────┐
│ package_name │
│ varchar │
├──────────────────────────────────────┤
│ @alloc/quick-lru │
│ @esbuild/darwin-arm64 │
│ @esbuild/linux-arm64 │
│ @headlessui/vue │
│ @popperjs/core │
Action
GUAC examples
You can run GUAC queries to discover risks across versions and different pieces of software.
Answer questions:
47
Collection
Ingestion
Correlation
Analysis
$ guacone query vuln purl "pkg:npm/vite@5.2.11"�<output doesn’t format well here>��$ guacone query known package “pkg:npm/vite@5.2.11”�<output doesn’t format well here>
Action
Note: OSV Scaner’s fix functionality is still experimental and doesn’t always work
48
Collection
Ingestion
Correlation
Analysis
$ git clone https://github.com/whiskeytastingfoundation/wtf-frontend�$ cd wtf-frontend
$ osv-scanner fix \
--max-depth=3 \
--min-severity=5 \
--ignore-dev \
--strategy=in-place \
-L package-lock.json
Action
Note: This example requires you to ingest multiple sboms from: https://github.com/guacsec/guac-data which will take too long for this workshop and also not fit in the gitpod. See: docs.guac.sh for more GUAC examples
GUAC generates a patch plan that includes all the packages that need to be updated to fix an issue. It also includes additional information like points of contact.
49
Collection
Ingestion
Correlation
Analysis
$ guacone query patch --start-purl "pkg:golang/github.com/antlr/antlr4/runtime/go/antlr" --search-depth 10�---FRONTIER LEVEL 0---
353: pkg:golang/github.com/antlr/antlr4/runtime/go/antlr
…
---FRONTIER LEVEL 1---
193: pkg:golang/github.com/google/cel-go
…
---FRONTIER LEVEL 2---
51113: pkg:guac/spdx/k8s.gcr.io/kube-apiserver-v1.25.2
…
---FRONTIER LEVEL 3---
129945: src:git/github.com/caddyserver/caddy
…
---INFO NODES---
no info nodes found
---POINTS OF CONTACT---
no POCs found
Action
Policy as Code:
Runtime correlation:
Future Work
50
VEX: SBOM’s Little Sibling
Silencing non-exploitable vulnerabilities and false positives.
51
VEX
52
Resources
QUESTIONS ?