SBOM: Software Bill of Materials Explained

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.

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.