← All Posts

Software Bills of Delivery: Beyond SBOMs with Component Models

Matthias Bruns · · 8 min read
software-supply-chain component-model sbom artifact-management

Traditional Software Bills of Materials (SBOMs) have served as the foundation for software supply chain transparency, but they’re showing their limitations in today’s complex, distributed environments. While SBOMs catalog components and dependencies, they fall short of tracking the complete delivery lifecycle across cloud-native architectures. Enter Software Bills of Delivery and component models—a more comprehensive approach that tracks not just what’s in your software, but how it moves through your entire delivery pipeline.

The SBOM Foundation and Its Limits

A Software Bill of Materials is a formal record of all software component parts and software dependencies used in application development and delivery. The National Telecommunications and Information Administration (NTIA) has established baseline requirements for SBOM creation and delivery, making them increasingly mandatory for government contracts and enterprise software.

SBOMs excel at providing a snapshot of components at build time. They answer critical questions like “What open source libraries are we using?” and “Do we have any known vulnerabilities?” But they struggle with the dynamic nature of modern software delivery:

  • Static snapshots vs. dynamic environments: SBOMs capture a point-in-time view, but container images, serverless functions, and microservices change constantly
  • Limited artifact tracking: They focus on source dependencies but miss runtime artifacts, configuration files, and deployment metadata
  • Deployment context gaps: SBOMs don’t track where components are deployed, how they’re configured, or their runtime relationships

These limitations become critical when you’re managing hundreds of microservices across multiple clusters, each with their own dependency chains and deployment patterns.

Component Models: The Next Evolution

Component models extend beyond traditional SBOMs by treating software artifacts as first-class entities with rich metadata throughout their lifecycle. The Open Component Model (OCM) offers a practical solution for the delivery of software artifacts, providing a standardized way to describe, package, and transport software components with their complete context.

Unlike SBOMs, component models track:

  • Artifact provenance: Complete build and deployment history
  • Runtime dependencies: Not just compile-time dependencies, but actual runtime relationships
  • Configuration metadata: Environment-specific settings and their sources
  • Delivery pipelines: How components move through CI/CD systems
  • Deployment topology: Where components run and how they communicate

This comprehensive tracking enables what we call “Software Bills of Delivery”—living documents that evolve with your software as it moves through environments.

Software Bills of Delivery in Practice

A Software Bill of Delivery goes beyond listing components to track the complete delivery journey. Here’s what this looks like in a real cloud-native environment:

With OCM, a component constructor file serves as the bill of delivery. It captures not just what artifacts exist, but where they come from and how to access them. The following example is for illustration — refer to the OCM component constructor reference for the authoritative schema:

# component-constructor.yaml — illustrative example, see ocm.software/docs for full schema
components:
  - name: github.com/company/user-service
    version: 2.1.3
    provider:
      name: company.com
    labels:
      - name: build.commit
        value: abc123def456
      - name: build.timestamp
        value: "2024-01-15T10:30:00Z"
      - name: build.pipeline
        value: github-actions
    resources:
      - name: container-image
        type: ociImage
        version: 2.1.3
        access:
          type: OCIImage/v1
          imageReference: registry.company.com/user-service:2.1.3
      - name: helm-chart
        type: helmChart
        version: 2.1.3
        access:
          type: Helm/v1
          helmRepository: registry.company.com
          helmChart: user-service-chart
          version: 2.1.3
    sources:
      - name: source
        type: git
        access:
          type: File/v1alpha1
          uri: https://github.com/company/user-service
    componentReferences:
      - name: postgres
        componentName: github.com/company/postgres
        version: "14.9"
      - name: redis
        componentName: github.com/company/redis
        version: "7.2"

This constructor captures artifacts, their sources, and component references — forming a complete, machine-readable bill of delivery that OCM can sign, verify, and transfer across registries.

Implementing Component Models for Supply Chain Security

Modern software supply chain security requires tracking components across their entire lifecycle. Here’s how component models address key security concerns:

Provenance Tracking

Component models maintain cryptographic proof of artifact origins:

type ComponentProvenance struct {
    BuildSystem   string            `json:"buildSystem"`
    SourceRepo    string            `json:"sourceRepo"`
    CommitHash    string            `json:"commitHash"`
    Builder       string            `json:"builder"`
    BuildTime     time.Time         `json:"buildTime"`
    Attestations  []Attestation     `json:"attestations"`
    Signatures    []Signature       `json:"signatures"`
}

type Attestation struct {
    Type      string    `json:"type"`      // "build", "test", "security-scan"
    Result    string    `json:"result"`    // "pass", "fail", "warning"
    Details   string    `json:"details"`
    Timestamp time.Time `json:"timestamp"`
    Verifier  string    `json:"verifier"`
}

Runtime Dependency Resolution

Unlike static SBOMs, component models track actual runtime dependencies:

# Runtime dependency discovery
runtimeDependencies:
  discovered:
    - service: payment-api
      version: "1.4.2"
      protocol: https
      endpoint: payment-api.internal:443
      discoveredAt: "2024-01-15T16:50:00Z"
      
  declared:
    - service: user-db
      version: "14.9"
      protocol: postgresql
      endpoint: user-db.production:5432
      
  external:
    - service: stripe-api
      endpoint: api.stripe.com
      version: "2023-10-16"
      sla: "99.9%"

Vulnerability Correlation

Component models enable precise vulnerability tracking across deployments:

{
  "vulnerabilityReport": {
    "component": "user-service:2.1.3",
    "scanTime": "2024-01-15T17:00:00Z",
    "findings": [
      {
        "cve": "CVE-2024-0001",
        "severity": "high",
        "affectedArtifacts": [
          "container:user-service@sha256:8f8a8b8c8d8e8f"
        ],
        "deploymentImpact": [
          {
            "environment": "production",
            "instances": 5,
            "exposure": "internal-only",
            "mitigations": ["network-policy", "pod-security-policy"]
          }
        ]
      }
    ]
  }
}

Distributed Systems and Component Relationships

In distributed architectures, understanding component relationships becomes crucial. Component models map these relationships explicitly:

Service Mesh Integration

componentRelationships:
  upstreamServices:
    - name: api-gateway
      traffic: "100%"
      protocol: http/2
      
  downstreamServices:
    - name: user-db
      queries: ["SELECT", "UPDATE", "INSERT"]
      connectionPool: 10
      
    - name: notification-service
      protocol: grpc
      async: true
      
  sidecarComponents:
    - name: envoy-proxy
      version: "1.28.0"
      config: istio-proxy-config
      
    - name: datadog-agent
      version: "7.49.0"
      config: monitoring-config

Cross-Cluster Dependencies

Modern applications span multiple clusters and cloud providers. Component models track these distributed relationships:

crossClusterDependencies:
  - component: shared-cache
    cluster: us-west-2-cache
    endpoint: redis.shared.company.internal
    latency: "< 5ms"
    
  - component: analytics-pipeline
    cluster: data-processing
    protocol: kafka
    topics: ["user-events", "audit-logs"]
    
  - component: cdn
    provider: cloudflare
    endpoints: ["cdn.company.com"]
    cachePolicies: ["static-assets", "api-responses"]

Automation and Tooling

Component models shine when integrated into automated workflows. Here’s how to implement automated delivery tracking:

CI/CD Integration

OCM uses a component-constructor.yaml file as input and the ocm add component-version command to push it into an OCI registry. Keys for signing are configured via .ocmconfig rather than passed as flags.

#!/bin/bash
# Build pipeline integration
set -e

# Build and push the container image
docker build -t registry.company.com/user-service:${BUILD_ID} .
docker push registry.company.com/user-service:${BUILD_ID}

# Write the component constructor
cat > component-constructor.yaml <<EOF
components:
  - name: github.com/company/user-service
    version: ${BUILD_ID}
    provider:
      name: company.com
    labels:
      - name: build.commit
        value: ${GIT_COMMIT}
    resources:
      - name: container-image
        type: ociImage
        version: ${BUILD_ID}
        access:
          type: OCIImage/v1
          imageReference: registry.company.com/user-service:${BUILD_ID}
    sources:
      - name: source
        type: git
        access:
          type: File/v1alpha1
          uri: https://github.com/company/user-service
EOF

# Add the component version to the OCM repository
ocm add component-version \
  --repository ${OCI_REGISTRY} \
  --constructor component-constructor.yaml

# Sign the component version (credentials configured in .ocmconfig)
ocm sign component-version \
  ${OCI_REGISTRY}//github.com/company/user-service:${BUILD_ID} \
  --signature company-signature

Runtime Discovery

Automated discovery keeps component models current:

func discoverRuntimeDependencies(ctx context.Context, podName string) (*RuntimeDependencies, error) {
    // Network traffic analysis
    connections, err := analyzeNetworkConnections(podName)
    if err != nil {
        return nil, err
    }
    
    // Service mesh integration
    envoyConfig, err := getEnvoyConfiguration(podName)
    if err != nil {
        return nil, err
    }
    
    // DNS resolution tracking
    dnsQueries, err := analyzeDNSQueries(podName)
    if err != nil {
        return nil, err
    }
    
    return &RuntimeDependencies{
        NetworkConnections: connections,
        ServiceMeshRoutes:  envoyConfig.Routes,
        DNSResolutions:     dnsQueries,
        DiscoveredAt:       time.Now(),
    }, nil
}

Security Benefits and Compliance

Component models provide significant security advantages over traditional SBOMs:

Compliance Automation

CISA’s SBOM requirements focus on transparency, but component models enable automated compliance checking:

complianceChecks:
  - policy: "no-high-severity-vulnerabilities"
    status: "enforced"
    lastCheck: "2024-01-15T18:00:00Z"
    
  - policy: "signed-artifacts-only"
    status: "enforced"
    exceptions: []
    
  - policy: "approved-base-images"
    status: "warning"
    violations:
      - component: "legacy-service"
        reason: "using deprecated base image"

Supply Chain Attack Detection

Component models enable sophisticated attack detection:

type SupplyChainAnomaly struct {
    Type        string    `json:"type"`
    Component   string    `json:"component"`
    Description string    `json:"description"`
    Severity    string    `json:"severity"`
    DetectedAt  time.Time `json:"detectedAt"`
}

func detectAnomalies(current, previous *ComponentModel) []SupplyChainAnomaly {
    var anomalies []SupplyChainAnomaly
    
    // Unexpected dependency changes
    for _, dep := range current.Dependencies {
        if !containsDependency(previous.Dependencies, dep) {
            anomalies = append(anomalies, SupplyChainAnomaly{
                Type:        "unexpected-dependency",
                Component:   current.Name,
                Description: fmt.Sprintf("New dependency added: %s", dep.Name),
                Severity:    "medium",
                DetectedAt:  time.Now(),
            })
        }
    }
    
    // Build environment changes
    if current.BuildEnvironment.Builder != previous.BuildEnvironment.Builder {
        anomalies = append(anomalies, SupplyChainAnomaly{
            Type:        "builder-change",
            Component:   current.Name,
            Description: "Build environment changed",
            Severity:    "high",
            DetectedAt:  time.Now(),
        })
    }
    
    return anomalies
}

Implementation Roadmap

Moving from SBOMs to component models requires a phased approach:

Phase 1: SBOM Enhancement

Start by enriching existing SBOMs with delivery metadata. Integrate SBOM generation directly into CI/CD pipelines and add deployment context.

Phase 2: Component Model Adoption

Implement component descriptors alongside SBOMs. Begin tracking artifact relationships and deployment topology.

Phase 3: Runtime Integration

Deploy discovery agents to automatically update component models with runtime dependencies and actual service relationships.

Phase 4: Advanced Analytics

Implement anomaly detection, compliance automation, and predictive security analysis based on component model data.

The Future of Software Supply Chain Transparency

Software Bills of Delivery represent the evolution from static documentation to dynamic, living records of software components and their relationships. By implementing component models, organizations gain unprecedented visibility into their software supply chains, enabling proactive security, automated compliance, and confident deployment practices.

The shift from SBOMs to comprehensive component models isn’t just about better documentation—it’s about building software supply chains that are transparent, secure, and resilient by design. As distributed systems become more complex, this level of visibility becomes essential for maintaining security and operational excellence.

Component models provide the foundation for the next generation of software supply chain security tools, enabling organizations to move from reactive vulnerability management to proactive risk prevention. The question isn’t whether to adopt this approach, but how quickly you can implement it to stay ahead of emerging threats and compliance requirements.

Reader settings

Font size