In the wake of Log4Shell and SolarWinds, the software industry is grappling with a fundamental question: what is actually inside our software? The answer comes in the form of Software Bill of Materials (SBOM)—a formal, machine-readable inventory of every component, library, and dependency that comprises a software product. In this comprehensive guide, I will explain why SBOMs matter, how to generate them across different technology stacks, and how to operationalize them in your CI/CD pipeline.
The Regulatory Landscape
Executive Order 14028, issued May 2021, mandates SBOM for any software sold to the federal government. This is not a suggestion—it is a procurement requirement. The ripple effects are already visible: major enterprises are requiring SBOMs from their vendors, and the expectation is cascading through supply chains.
The National Telecommunications and Information Administration (NTIA) published minimum elements for SBOMs:
- Supplier Name: Who provided the component
- Component Name: Library name (e.g., log4j-core)
- Version: Specific version string
- Unique Identifier: Package URL (purl) or CPE
- Dependency Relationship: Direct vs transitive
- Timestamp: When the SBOM was generated
SBOM Formats: SPDX vs CycloneDX
Two formats dominate the ecosystem:
SPDX (Software Package Data Exchange)
Originated from the Linux Foundation. Strong in license compliance. Verbose format.
CycloneDX
Created by OWASP. Focused on security use cases. Lightweight JSON/XML format. My recommendation for most teams.
{
"bomFormat": "CycloneDX",
"specVersion": "1.4",
"version": 1,
"components": [
{
"type": "library",
"name": "Newtonsoft.Json",
"version": "13.0.1",
"purl": "pkg:nuget/Newtonsoft.Json@13.0.1",
"licenses": [{ "license": { "id": "MIT" } }]
}
]
}
Generating SBOMs by Technology Stack
.NET
# Install the tool
dotnet tool install --global CycloneDX
# Generate SBOM
dotnet CycloneDX MyApp.sln -o sbom.json -j
# For container images
syft mcr.microsoft.com/dotnet/aspnet:6.0 -o cyclonedx-json > base-image-sbom.json
Node.js / JavaScript
# Using cyclonedx-npm
npx @cyclonedx/bom -o sbom.json
# Using syft for lock file analysis
syft . -o cyclonedx-json > sbom.json
Python
# Using cyclonedx-bom
pip install cyclonedx-bom
cyclonedx-py -r requirements.txt -o sbom.json --format json
Operationalizing SBOMs in CI/CD
Generating SBOMs is step one. The real value comes from continuous monitoring. Here is a reference architecture:
flowchart TB
subgraph Build ["CI/CD Pipeline"]
Code["Source Code"] --> Build["Build"]
Build --> SBOM["Generate SBOM"]
SBOM --> Scan["Vulnerability Scan (Grype)"]
Scan --> Gate{Vulnerabilities?}
Gate -->|Critical| Fail["Fail Build"]
Gate -->|None| Publish["Publish Artifact + SBOM"]
end
subgraph Runtime ["Continuous Monitoring"]
Publish --> Registry["Container Registry"]
Registry --> DependencyTrack["Dependency-Track"]
DependencyTrack --> Alert["Alert on New CVEs"]
end
style Fail fill:#FFCDD2,stroke:#C62828
style DependencyTrack fill:#E8F5E9,stroke:#2E7D32
Step 1: Generate at Build Time
# GitHub Actions example
- name: Generate SBOM
run: syft . -o cyclonedx-json > sbom.json
- name: Scan for Vulnerabilities
run: grype sbom:sbom.json --fail-on critical
- name: Upload SBOM as Artifact
uses: actions/upload-artifact@v3
with:
name: sbom
path: sbom.json
Step 2: Store with Your Artifacts
Attach the SBOM to your container image as an OCI artifact or store it in your artifact repository (JFrog Artifactory, Azure Container Registry).
Step 3: Continuous Monitoring
Deploy Dependency-Track (OWASP project) to ingest SBOMs and continuously monitor for new vulnerabilities. When a new CVE is published affecting one of your dependencies, you receive an alert—even months after deployment.
Key Takeaways
- SBOMs are becoming mandatory for enterprise software
- CycloneDX is the recommended format for security use cases
- Integrate SBOM generation into CI/CD pipelines
- Use Grype for build-time vulnerability scanning
- Deploy Dependency-Track for continuous monitoring
Discover more from C4: Container, Code, Cloud & Context
Subscribe to get the latest posts sent to your email.