SBOM Guide
This guide covers everything you need to know about Software Bills of Materials (SBOMs) in CRA Evidence: what they are, how to generate them, how to upload them, and how to improve their quality.
What is an SBOM?
A Software Bill of Materials (SBOM) is a machine-readable inventory of all software components in your product. Think of it as an ingredient list for software.
Why SBOMs Are Required
CRA Article 13(6) states:
"Manufacturers shall identify and document vulnerabilities and components contained in the product with digital elements, including by drawing up a software bill of materials in a commonly used and machine-readable format."
SBOMs enable:
- Vulnerability tracking: Know if your components have known CVEs
- Supply chain transparency: Understand where your software comes from
- Incident response: Quickly assess impact when new vulnerabilities emerge
- Compliance evidence: Demonstrate due diligence to regulators
Supported Formats
CRA Evidence supports two industry-standard SBOM formats:
CycloneDX
Recommended. Modern, security-focused format.
- Versions: 1.5+ supported (1.6 for validation)
- Detection: File contains
"bomFormat": "CycloneDX" - Ecosystem: OWASP project with wide tooling support
{
"bomFormat": "CycloneDX",
"specVersion": "1.5",
"version": 1,
"components": [
{
"type": "library",
"name": "lodash",
"version": "4.17.21",
"purl": "pkg:npm/lodash@4.17.21"
}
]
}
SPDX
Linux Foundation standard, widely used in open source.
- Versions: 2.2+ supported
- Detection: File contains
"spdxVersion"field - Ecosystem: Strong in open source licensing compliance
{
"spdxVersion": "SPDX-2.3",
"SPDXID": "SPDXRef-DOCUMENT",
"packages": [
{
"SPDXID": "SPDXRef-lodash",
"name": "lodash",
"versionInfo": "4.17.21",
"externalRefs": [
{
"referenceType": "purl",
"referenceLocator": "pkg:npm/lodash@4.17.21"
}
]
}
]
}
Which to Choose?
| Consideration | CycloneDX | SPDX |
|---|---|---|
| Security focus | Native VEX support | Add-on |
| Tooling | Growing rapidly | Well-established |
| Vulnerability matching | Excellent | Good |
| License tracking | Good | Excellent |
| Recommendation | Preferred for CRA | Also acceptable |
How to Generate SBOMs
Quick Reference by Technology
| Technology | Tool | Command |
|---|---|---|
| Container images | Syft | syft image:tag -o cyclonedx-json |
| Node.js | @cyclonedx/cyclonedx-npm | cyclonedx-npm --output-file sbom.json |
| Python | cyclonedx-py | cyclonedx-py requirements |
| Java/Maven | cyclonedx-maven-plugin | mvn cyclonedx:makeAggregateBom |
| .NET | CycloneDX | dotnet CycloneDX |
| Go | cyclonedx-gomod | cyclonedx-gomod mod |
| Rust | cargo-sbom | cargo sbom |
Detailed Instructions
Container Images (Recommended: Syft)
Syft by Anchore is the most comprehensive tool for container SBOMs.
Installation:
# Linux/macOS
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
# Homebrew
brew install syft
# Docker
docker pull anchore/syft
Generate SBOM:
# From Docker image
syft myapp:latest -o cyclonedx-json > sbom.json
# From directory
syft dir:/path/to/code -o cyclonedx-json > sbom.json
# From container archive
syft docker-archive:myapp.tar -o cyclonedx-json > sbom.json
Best Practices for Syft:
# Include file metadata for better matching
syft myapp:latest -o cyclonedx-json --file sbom.json
# Include all layers (more comprehensive)
syft myapp:latest --scope all-layers -o cyclonedx-json > sbom.json
Node.js Projects
Using @cyclonedx/cyclonedx-npm (recommended):
# Install
npm install -g @cyclonedx/cyclonedx-npm
# Generate from package-lock.json (recommended)
cyclonedx-npm --output-file sbom.json
# Include dev dependencies
cyclonedx-npm --include-dev --output-file sbom.json
Using cdxgen (alternative):
# Install
npm install -g @cyclonedx/cdxgen
# Generate
cdxgen -o sbom.json
Python Projects
Using cyclonedx-py:
# Install
pip install cyclonedx-bom
# From requirements.txt
cyclonedx-py requirements requirements.txt -o sbom.json
# From Pipenv
cyclonedx-py pipenv -o sbom.json
# From Poetry
cyclonedx-py poetry -o sbom.json
# From environment (all installed packages)
cyclonedx-py environment -o sbom.json
Best Practices:
- Use lock files (Pipfile.lock, poetry.lock) for reproducible SBOMs
- Include both direct and transitive dependencies
Java/Maven Projects
Using CycloneDX Maven Plugin:
Add to pom.xml:
<build>
<plugins>
<plugin>
<groupId>org.cyclonedx</groupId>
<artifactId>cyclonedx-maven-plugin</artifactId>
<version>2.7.9</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>makeAggregateBom</goal>
</goals>
</execution>
</executions>
<configuration>
<projectType>application</projectType>
<schemaVersion>1.5</schemaVersion>
<includeCompileScope>true</includeCompileScope>
<includeRuntimeScope>true</includeRuntimeScope>
<includeProvidedScope>true</includeProvidedScope>
</configuration>
</plugin>
</plugins>
</build>
Generate:
mvn cyclonedx:makeAggregateBom
# Output: target/bom.json
Gradle Projects
Using CycloneDX Gradle Plugin:
Add to build.gradle:
plugins {
id 'org.cyclonedx.bom' version '1.8.2'
}
cyclonedxBom {
schemaVersion = "1.5"
includeConfigs = ["runtimeClasspath"]
skipConfigs = ["testCompileClasspath", "testRuntimeClasspath"]
}
Generate:
gradle cyclonedxBom
# Output: build/reports/bom.json
.NET Projects
Using CycloneDX .NET:
# Install as global tool
dotnet tool install -g CycloneDX
# Generate
dotnet CycloneDX MyProject.csproj -o sbom.json
Go Projects
Using cyclonedx-gomod:
# Install
go install github.com/CycloneDX/cyclonedx-gomod/cmd/cyclonedx-gomod@latest
# Generate
cyclonedx-gomod mod -json -output sbom.json
Uploading to CRA Evidence
Via Web Interface
- Navigate to your Product > Version
- Click the SBOM tab in the Artifacts section
- Drag and drop your SBOM file, or click to browse
- Wait for processing (usually a few seconds)
Via API
For CI/CD integration:
# Upload SBOM
curl -X POST "https://app.craevidence.com/api/v1/sboms/ingest" \
-H "Authorization: Bearer $API_TOKEN" \
-F "file=@sbom.json" \
-F "version_id=YOUR_VERSION_UUID"
Response:
{
"id": "sbom-uuid",
"filename": "sbom.json",
"format": "cyclonedx",
"component_count": 150,
"quality_score": 85.5,
"components_with_purl": 140,
"components_with_hash": 120,
"components_with_supplier": 100
}
See CI/CD Integration for pipeline examples.
Understanding Quality Scores
After upload, CRA Evidence calculates a quality score based on TR-03183 recommendations.
See Core Concepts for the quality score calculation: the four metrics (PURL 30%, Hash 30%, Supplier 20%, License 20%), the weighted formula, and the score range interpretation (Excellent/Good/Fair/Poor).
Improving SBOM Quality
Why Quality Matters
Low-quality SBOMs lead to:
- Missed vulnerabilities: No PURL = no CVE matching
- Incomplete supply chain view: Missing supplier info
- Audit concerns: Regulators may question completeness
How to Improve Each Metric
Improving PURL Coverage
PURLs (Package URLs) are standardized identifiers that enable vulnerability matching.
Format: pkg:type/namespace/name@version
Examples:
pkg:npm/lodash@4.17.21pkg:maven/org.apache.commons/commons-lang3@3.12.0pkg:pypi/requests@2.28.1
How to improve:
- Use modern SBOM tools: Syft, cdxgen automatically add PURLs
- Use lock files:
package-lock.json,Pipfile.lockcontain exact versions - Avoid manual SBOMs: Automated tools include PURLs by default
Improving Hash Coverage
SHA-256 hashes verify component integrity.
How to improve:
- Use Syft: Includes hashes by default
- Enable hash generation: Some tools require flags
# Syft (hashes included by default) syft myapp:latest -o cyclonedx-json # cyclonedx-py with hashes cyclonedx-py requirements --include-hash -o sbom.json
Improving Supplier Coverage
Supplier information shows component origin.
How to improve:
- Use comprehensive tools: Syft, cdxgen extract supplier data
- Generate from lock files: More metadata available
- Manual enrichment: For custom/internal components
Improving License Coverage
License information is needed for compliance.
How to improve:
- Use tools with license detection: Syft, cdxgen
- Include license files: Tools can detect LICENSE files
- Configure tools properly: Enable license scanning
Common Validation Errors
"CycloneDX schema validation failed"
Cause: SBOM doesn't match CycloneDX 1.6 schema.
Solution:
- Check your tool's output format version
- Upgrade your SBOM generation tool
- Validate locally:
cyclonedx validate --input-file sbom.json
"Could not detect SBOM format"
Cause: File missing format identifier.
Solution:
- CycloneDX must have
"bomFormat": "CycloneDX" - SPDX must have
"spdxVersion": "..."or"SPDXID": "..." - Ensure file is valid JSON
"Invalid JSON file"
Cause: Malformed JSON.
Solution:
- Validate JSON syntax:
jq . sbom.json - Check for truncation (incomplete upload)
- Ensure UTF-8 encoding
"Quality score below threshold"
Cause: Organisation has minimum quality enforcement.
Solution:
- Improve SBOM quality (see above)
- Or request threshold adjustment from admin
Best Practices
- Generate at build time: Integrate SBOM generation into your CI/CD pipeline so every release has a fresh, accurate SBOM — not a manually maintained one.
- Use lock files: Generate SBOMs from
package-lock.json,poetry.lock,go.sum, etc. to capture exact transitive dependency versions with correct PURLs and hashes. - Include transitive dependencies: Direct dependencies alone miss most vulnerabilities. Use tools like Syft or cdxgen which capture the full dependency tree.
CI/CD Integration Examples
See CI/CD Integration for complete examples including:
- GitHub Actions
- GitLab CI
- Jenkins
- Azure DevOps
Next Steps
Now that you understand SBOMs:
- Documents Checklist - Upload the other required CRA documents
- Vulnerability Workflow - Understand what happens after upload
- Technical File Export - Generate compliance bundles
Help us improve. What was missing or unclear?