The EU Cyber Resilience Act mandates Software Bills of Materials for all products with digital elements sold in the EU from December 2027. Article 20 says “machine-readable SBOMs covering top-level dependencies” but what does that actually mean when you’re staring at SPDX PackageSupplier fields or CycloneDX component metadata?
This guide is part of our comprehensive supply chain security guide, where we explore the regulatory, technical, and operational dimensions of protecting your software supply chain. Here we cut through the CRA’s regulatory language with field mapping tables, Terraform code you can use, and BomCTL validation commands that work. By the end you’ll have executable infrastructure-as-code templates, firmware extraction approaches, and CI/CD integration patterns that satisfy both notified bodies and your existing toolchain.
What are the mandatory SBOM requirements under Article 20 of the EU Cyber Resilience Act?
Article 20 requires a Software Bill of Materials in a commonly used, machine-readable format covering at least top-level dependencies. Your SBOM needs supplier information, component names and versions, unique identifiers (PURL or CPE), dependency relationships, author and timestamp metadata, and cryptographic hashes for each component. You provide this when the product hits the EU market and keep it current throughout the support period.
The regulatory text says “commonly used, machine-readable format” without getting specific. SPDX (ISO/IEC 5962) and CycloneDX (ECMA-424) both qualify—they’re internationally standardised, supported by major tools, and designed for automated processing. While Article 20 says “at least top-level dependencies,” you should include transitive dependencies for vulnerability tracking. This aligns with Germany’s BSI TR-03183-2 and CISA’s SBOM maturity model.
Core mandatory fields:
- Supplier: Who’s responsible for the component
- Component name: What it’s called
- Version: Which release you’re using
- Unique identifier: Package URL (PURL) or Common Platform Enumeration (CPE)
- Dependency relationships: What depends on what
- Author and timestamp: Who generated the SBOM and when
- Cryptographic hash: SHA-256 or stronger for integrity verification
These SBOMs go into your Article 13 technical documentation, which you’ll keep for 10 years after market placement. Market surveillance authorities can request them on demand.
The “when placed on the market” timing matters. You can’t retrofit SBOMs for products already shipping. New products entering the EU market after December 11, 2027 need compliant SBOMs. Substantial modifications to existing products trigger new SBOM generation. Security patches and minor updates need regenerated SBOMs but won’t necessarily trigger full reassessment.
How do I map CRA Article 20 requirements to SPDX and CycloneDX formats?
For SPDX, use PackageName for component identity, PackageVersion for version tracking, PackageSupplier for manufacturer information, SPDXID for unique identification, ExternalRef with type purl or cpe23Type for standardised identifiers, Relationship with DEPENDS_ON for dependency graphs, and PackageChecksum with algorithm SHA256 for hashes.
For CycloneDX, use component.name, component.version, component.supplier.name, component.bom-ref for unique identification, component.purl for package URLs, the dependencies array, and component.hashes array.
Both formats satisfy Article 20 without data loss. Here’s the mapping:
| CRA Requirement | SPDX 2.3 Field | CycloneDX 1.7 Field | |—————-|—————-|———————| | Supplier | PackageSupplier: Organization: Acme Corp | component.supplier.name: "Acme Corp" | | Component Name | PackageName: express | component.name: "express" | | Version | PackageVersion: 4.18.2 | component.version: "4.18.2" | | Unique Identifier | ExternalRef: PACKAGE-MANAGER purl pkg:npm/[email protected] | component.purl: "pkg:npm/[email protected]" | | Dependencies | Relationship: SPDXRef-Package DEPENDS_ON SPDXRef-Dep | dependencies[].ref: "pkg:npm/[email protected]" | | Timestamp | Created: 2025-01-02T10:30:00Z | metadata.timestamp: "2025-01-02T10:30:00Z" | | Author | Creator: Tool: syft-0.98.0 | metadata.tools[].name: "syft" | | Cryptographic Hash | PackageChecksum: SHA256: a1b2c3d4... | component.hashes[{alg:"SHA-256", content:"a1b2c3..."}] |
SPDX excels at licensing complexity with standardised identifiers for 500+ licenses. SPDX 3.0 introduced profiles for security, build provenance, and AI/data use cases.
CycloneDX is security-first by design. It has native Vulnerability Exploitability eXchange (VEX) integration and extends beyond software to Hardware BOMs for ASICs and FPGAs, Machine Learning BOMs, and Cryptographic BOMs. ECMA-424 standardisation provides international recognition.
For dual-format support, Protobom enables lossless conversion between SPDX and CycloneDX.
Format selection:
- Choose SPDX if licensing compliance drives your open source governance, you’re invested in Linux Foundation tooling, or provenance tracking across complex supply chains is critical
- Choose CycloneDX if security automation and vulnerability management are priorities, you need hardware/firmware/ML component coverage, VEX integration matters, or you want lightweight CI/CD integration
What is BomCTL and how do I use it to validate SBOM compliance?
BomCTL is an OpenSSF command-line utility for validating SBOMs against regulatory requirements and integrating compliance checks into CI/CD pipelines. Install via go install github.com/opensbom/bomctl@latest or grab pre-built binaries from GitHub releases. Run bomctl validate --format spdx --file sbom.json to verify SPDX schema compliance. Execute bomctl check --standard cra --file sbom.json to validate against Article 20’s mandatory fields.
The OpenSSF “SBOM Everywhere” Special Interest Group maintains BomCTL. It builds on Protobom’s format-agnostic data model, validating both SPDX and CycloneDX formats.
Basic validation workflow:
# Install BomCTL
go install github.com/opensbom/bomctl@latest
# Validate SPDX format compliance
bomctl validate --format spdx --file build/artifacts/sbom.spdx.json
# Check CRA Article 20 requirements
bomctl check --standard cra --file build/artifacts/sbom.spdx.json
# Output: ✓ Supplier information present for all packages
# ✓ Cryptographic hashes (SHA-256) present
# ✓ Dependency relationships complete
# ✗ ERROR: Package 'lodash' missing unique identifier (PURL/CPE)
# ✗ ERROR: PackageSupplier field empty for 'internal-utils'
Common failures:
Missing PackageSupplier: Your SBOM tool can’t determine component origin. Cross-reference package manager metadata (npm registry, Maven Central, PyPI) to identify the maintaining organisation. For internal components, configure your tool to inject your organisation name.
Incomplete dependency relationships: Your generator only captures direct dependencies. Switch to tools like Syft or Trivy that do deep dependency analysis by default.
Missing cryptographic hashes: You’re generating SBOMs before build completion. Restructure your CI/CD pipeline to generate SBOMs after build artifacts are created.
CI/CD integration example:
name: SBOM Generation and Validation
on: [push, pull_request]
jobs:
sbom-validation:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build application
run: make build
- name: Generate SBOM
uses: anchore/[email protected]
with:
format: spdx-json
output-file: build/sbom.spdx.json
- name: Install BomCTL
run: go install github.com/opensbom/bomctl@latest
- name: Validate SBOM format
run: bomctl validate --format spdx --file build/sbom.spdx.json
- name: Check CRA compliance
run: bomctl check --standard cra --file build/sbom.spdx.json
- name: Fail build on validation errors
if: failure()
run: exit 1
This treats validation failures as build failures, preventing non-compliant SBOMs from reaching production.
How does the CRA’s 10-year retention requirement work and how do I implement it?
Article 13(12) requires manufacturers to retain technical documentation including SBOMs for 10 years after market placement or for the product’s support period, whichever is longer. If you support a product for 15 years, retention extends to 15 years.
Implement using cloud storage lifecycle policies with immutable object lock preventing deletion, automated versioning tracking all SBOM updates, and compliance monitoring detecting policy violations.
Cloud storage advantages:
- Immutability: Object Lock in compliance mode prevents deletion even by administrators
- Audit logs: S3 access logging creates forensic trails showing who accessed what and when
- Geographic redundancy: Multi-AZ replication survives regional failures
- Regulatory access: Generate time-limited pre-signed URLs for secure delivery to authorities
Terraform implementation:
# S3 bucket for CRA SBOM retention
resource "aws_s3_bucket" "sbom_retention" {
bucket = "company-cra-sbom-archive-${var.environment}"
tags = {
Purpose = "CRA Article 13 technical documentation"
Compliance = "EU Cyber Resilience Act"
Retention = "10 years minimum"
}
}
# Enable versioning for SBOM update tracking
resource "aws_s3_bucket_versioning" "sbom_retention" {
bucket = aws_s3_bucket.sbom_retention.id
versioning_configuration {
status = "Enabled"
}
}
# Object Lock configuration
resource "aws_s3_bucket_object_lock_configuration" "sbom_retention" {
bucket = aws_s3_bucket.sbom_retention.id
rule {
default_retention {
mode = "COMPLIANCE" # Prevents deletion even by root account
years = 10
}
}
}
# Lifecycle policy: transition to Glacier Deep Archive after 90 days
resource "aws_s3_bucket_lifecycle_configuration" "sbom_retention" {
bucket = aws_s3_bucket.sbom_retention.id
rule {
id = "transition-to-deep-archive"
status = "Enabled"
transition {
days = 90
storage_class = "DEEP_ARCHIVE" # Lowest cost for 10-year retention
}
}
}
# Server-side encryption
resource "aws_s3_bucket_server_side_encryption_configuration" "sbom_retention" {
bucket = aws_s3_bucket.sbom_retention.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
Cost optimisation:
S3 Glacier Deep Archive costs approximately $0.00099 per GB-month (compared to $0.023 for S3 Standard), reducing storage costs by 95%. The 90-day transition keeps recent SBOMs in S3 Standard for fast retrieval during active support, while older SBOMs transition to Deep Archive where 12-hour retrieval times are fine for regulatory requests.
For a product portfolio generating 100 MB of SBOMs annually over 10 years (1 GB total), storage costs are approximately $1/month in Deep Archive versus $23/month in S3 Standard.
How do I extract firmware components for SBOM generation?
Firmware SBOM extraction means identifying all embedded components including ASICs, FPGAs, boot managers, network interface controllers, and their version information. Use binary decompilation tools to extract version strings, cross-reference with OEM supply chain documentation, and map components to CPE/PURL identifiers. Automated firmware analysis platforms like Eclypsium can scan firmware images, identify embedded modules, and generate CycloneDX SBOMs.
The CRA explicitly includes firmware in “all integrated components.” Annex III products—boot managers, network interfaces, ASICs, FPGAs, operating systems, industrial control systems—require third-party conformity assessment by notified bodies. For these products, incomplete firmware SBOMs may prevent market access.
Manual firmware extraction:
# Extract firmware image contents using binwalk
binwalk -e firmware-image.bin
# Identify version strings in extracted binaries
strings _firmware-image.bin.extracted/rootfs.squashfs | grep -i "version"
# Output: "Bootloader v2.4.1"
# "NIC Firmware 3.2.18"
# "Protocol Stack Build 20241015"
# Map identified components to standardised identifiers:
# - Bootloader v2.4.1 → CPE: cpe:2.3:o:vendor_a:bootloader:2.4.1:*
# - NIC Firmware 3.2.18 → PURL: pkg:firmware/vendor_b/[email protected]
CycloneDX advantage:
CycloneDX natively supports multiple BOM types:
- SBOM: Traditional application and library components
- HBOM: ASICs, FPGAs, System-on-Chip components
- Firmware components: Boot managers, BIOS/UEFI, network interface firmware
This enables single SBOM documents covering complete product composition:
{
"bomFormat": "CycloneDX",
"specVersion": "1.7",
"components": [
{
"type": "firmware",
"name": "Bootloader",
"version": "2.4.1",
"supplier": {
"name": "Vendor A Technologies"
},
"purl": "pkg:firmware/vendor-a/[email protected]",
"hashes": [
{
"alg": "SHA-256",
"content": "a1b2c3d4e5f6..."
}
]
},
{
"type": "hardware",
"name": "Network ASIC",
"version": "RevB",
"supplier": {
"name": "Vendor B Semiconductor"
},
"cpe": "cpe:2.3:h:vendor_b:network_asic:revb:*"
}
]
}
Cross-reference extracted component lists with OEM supply chain documentation to ensure completeness. For Annex III products, notified bodies will review component coverage during conformity assessment.
Start requesting firmware SBOMs from hardware vendors early. As CRA compliance becomes universal for EU market access, vendors will increasingly provide component documentation. For vendors who won’t provide SBOMs, consider component selection criteria including SBOM transparency.
How do I integrate SBOM generation into my CI/CD pipeline?
Integrate SBOM generation into CI/CD using GitHub Actions or GitLab CI to run generation tools on every build, validate with BomCTL, sign with SBOMit or cosign for integrity verification, and upload artifacts to S3 with 10-year retention lifecycle policies. For a complete step-by-step tutorial with working GitHub Actions workflows, see our guide on how to implement SBOM generation in your pipeline.
Tool selection:
- Syft (Anchore): Multi-language support, generates SPDX and CycloneDX, deep dependency analysis, container image scanning
- Trivy (Aqua Security): Integrated vulnerability scanning, supports filesystems and container images, CycloneDX and SPDX output
- CycloneDX CLI: Format conversion, SBOM merging, validation and diff capabilities
GitHub Actions workflow:
name: CRA SBOM Generation and Compliance
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
sbom-compliance:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Build application
run: npm ci && npm run build
- name: Generate SBOM with Syft
uses: anchore/[email protected]
with:
format: spdx-json
output-file: build/sbom.spdx.json
- name: Install BomCTL
run: |
go install github.com/opensbom/bomctl@latest
echo "$HOME/go/bin" >> $GITHUB_PATH
- name: Validate SBOM format
run: bomctl validate --format spdx --file build/sbom.spdx.json
- name: Check CRA compliance
run: bomctl check --standard cra --file build/sbom.spdx.json
- name: Sign SBOM with cosign
uses: sigstore/cosign-installer@v3
- name: Cryptographically sign SBOM
run: |
cosign sign-blob --yes \
build/sbom.spdx.json \
--output-signature build/sbom.spdx.json.sig \
--output-certificate build/sbom.spdx.json.cert
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_SBOM_UPLOAD_ROLE }}
aws-region: eu-west-1
- name: Upload SBOM to retention storage
run: |
PRODUCT_VERSION=$(jq -r '.name' package.json)-$(jq -r '.version' package.json)
aws s3 cp build/sbom.spdx.json \
s3://company-cra-sbom-archive/products/$PRODUCT_VERSION/sbom-$(date +%Y%m%d-%H%M%S).spdx.json \
--metadata "product=$PRODUCT_VERSION,cra-compliance=true"
- name: Fail build on validation errors
if: failure()
run: exit 1
Cryptographic signing:
SBOMit or cosign sign SBOMs with private keys, generating detached signatures for verification. Cosign supports keyless signing via Sigstore, eliminating private key management while providing transparency log entries.
Signing ensures:
- Integrity: Detect tampering if SBOM is modified
- Authenticity: Verify SBOM originated from claimed manufacturer
- Non-repudiation: Cryptographic proof manufacturer created specific SBOM version
Configure dependency update automation (Dependabot, Renovate) to trigger SBOM regeneration when dependencies change. Version your SBOMs alongside application releases.
What is the connection between SBOM requirements and CE marking?
SBOMs form part of the technical documentation required for CE marking conformity assessment under the CRA. You include SBOMs in the Article 13 technical file demonstrating compliance with Article 6 cybersecurity requirements. For Annex III products—boot managers, ASICs, FPGAs, operating systems—notified bodies review SBOM completeness, accuracy, and format compliance during mandatory third-party conformity assessment before CE marking authorisation. SBOM quality directly impacts CE marking eligibility and market access from December 2027.
Technical file composition (Article 13):
- SBOM: Machine-readable component inventory in SPDX or CycloneDX
- Risk assessments: Cybersecurity risk analysis per Article 10
- Test results: Security testing and vulnerability assessments
- Conformity proof: Evidence of Article 6 requirements compliance
- Update records: Documentation of security updates throughout support period
You’ll retain this for 10 years and make it available to market surveillance authorities on demand.
Conformity assessment pathways:
Lower-risk products follow self-assessment: you evaluate your product against CRA requirements, compile technical documentation including SBOMs, and issue an EU Declaration of Conformity.
Annex III products require third-party assessment by notified bodies. Product categories include:
- Boot managers and operating systems
- Network interfaces and communication modules
- ASICs and FPGAs with cryptographic functions
- Industrial control systems
- Hardware security modules
Notified body SBOM review:
During assessment, notified bodies evaluate:
- Completeness: All components documented
- Accuracy: Versions and hashes match deployed artifacts
- Format compliance: SBOM validates against SPDX or CycloneDX schemas
- Retention architecture: Evidence of 10-year retention capability
- Update procedures: Documented workflows for SBOM regeneration
The number of CRA-certified notified bodies remains limited. Begin conformity assessment planning 12-18 months before market placement to reduce timeline risk.
FAQ
Can I use both SPDX and CycloneDX formats for the same product?
Yes, generate both using Protobom for conversion. Some organisations maintain SPDX for licensing compliance teams and CycloneDX for security automation platforms. Ensure both formats stay synchronised by generating one as primary and converting to secondary, then cryptographically sign both.
Do I need to include transitive dependencies or just top-level dependencies?
Article 20 legally requires “at least top-level dependencies,” but including transitive dependencies is best practice for vulnerability tracking. Tools like Syft and Trivy include transitive dependencies by default. For Annex III products, notified bodies may expect comprehensive coverage.
How do I handle proprietary components where supplier won’t provide SBOM data?
Document the component with available information, mark unavailable fields as NOASSERTION per SPDX convention, and maintain evidence of supplier engagement attempts. For Annex III products, incomplete component information may impact notified body assessment.
When does the 10-year retention period start?
Retention starts at market placement date and extends for 10 years or the product support period, whichever is longer. Each product version has independent retention periods requiring tracking systems correlating SBOM artifacts with specific release dates.
Does the CRA apply to open source software?
The CRA applies to commercial activities involving products with digital elements sold in the EU. Open source software developed without monetisation is exempt. Commercial distributions (Red Hat, SUSE) and SaaS offerings using open source components are in scope.
How does SBOM requirement interact with Article 14 incident reporting?
SBOMs enable rapid vulnerability identification when exploits are discovered. When a component vulnerability is actively exploited, manufacturers must report to ENISA within 24 hours per Article 14 (effective September 2026). Accurate SBOMs accelerate incident response. For detailed procedures on meeting these regulatory breach notification requirements, see our 72-hour incident response playbook.
What happens if I update my product after market placement?
Substantial modifications changing risk level or intended purpose trigger new conformity assessment and updated SBOMs. Security patches and minor updates require regenerated SBOMs but don’t necessarily trigger full reassessment.
Can I automate SBOM signing for cryptographic integrity?
Yes, integrate SBOMit or cosign into pipelines to automatically sign SBOMs using private keys stored in secrets management. Cosign supports keyless signing via Sigstore, eliminating private key management while providing certificate transparency log entries.
How do market surveillance authorities access my SBOMs?
Authorities can request technical documentation on demand during inspections under Regulation (EU) 2019/1020. Implement secure retrieval workflows from retention storage using time-limited pre-signed URLs with audit logging.
What if my firmware vendor doesn’t provide component lists?
Engage vendors early requesting firmware SBOMs or component manifests. If unavailable, use firmware analysis tools (Eclypsium, binwalk) to extract components. For Annex III products, incomplete firmware SBOMs may fail notified body assessment.
Do SBOMs replace other security documentation requirements?
No, SBOMs complement other CRA requirements. Article 13 technical files must include risk assessments, vulnerability handling procedures, incident response plans, secure development evidence, test results, and conformity proof alongside SBOMs. For a complete overview of all supply chain security fundamentals beyond just SBOMs, review our comprehensive guide covering regulatory compliance, incident response, and security stack implementation.
How do I validate that my SBOM meets CRA requirements before submission?
Use BomCTL (bomctl check --standard cra --file sbom.json) to validate against Article 20 mandatory fields. Integrate BomCTL validation into CI/CD pipelines as quality gates failing builds when compliance issues are detected.