Skip to content

SBOM Governance Best Practices

Guidelines for managing SBOMs in enterprise environments, derived from industry best practices.

The Problem with Unfiltered SBOMs

Publishing raw scanner output creates several issues:

  1. False Positive Overload: 97%+ of CVE alerts are not exploitable in actual deployment context
  2. Architecture Exposure: Internal implementation details visible to customers
  3. Support Burden: Customer escalations for non-exploitable vulnerabilities
  4. Lack of Context: "Vulnerability exists" without "is it reachable?"

Two-Layer SBOM Architecture

Maintain separate SBOMs for different purposes:

1. Canonical SBOM (Internal)

Generated by deterministic tools (Syft, Trivy, cdxgen):

  • Legally and operationally authoritative
  • Deterministic and reproducible
  • Audit-grade
  • LLM-free
  • Contains all components including build-time dependencies

2. Enriched SBOM (Customer-Facing)

Derived from canonical SBOM with:

  • Reachability analysis results
  • VEX statements for non-exploitable issues
  • Runtime context (deployment status)
  • Filtered to shipping components only
Canonical SBOM (internal)
Static reachability analysis
Runtime context enrichment
VEX generation for non-exploitable
Enriched SBOM (customer-facing)

Delta-Based Review Process

For scalable SBOM governance:

1. Baseline Establishment

  • Generate canonical SBOM for release
  • Run full reachability analysis
  • Generate VEX for all findings
  • Store as baseline

2. Incremental Updates

On each release:

# Generate new SBOM
syft . -o cyclonedx-json > sbom-new.json

# Compute delta from baseline
sbom-diff baseline.json sbom-new.json > delta.json

# Review only new/changed components
graphize-appsec assess --delta delta.json

3. Review Gates

Change Type Review Required
New dependency Full reachability analysis
Version bump (patch) Quick scan
Version bump (major) Full analysis + manual review
Dependency removed Update VEX only

VEX Integration

VEX (Vulnerability Exploitability eXchange) is the output of reachability reasoning:

States

State Meaning
not_affected Vulnerability not exploitable
affected Vulnerability is exploitable
fixed Vulnerability has been remediated
under_investigation Analysis in progress

Justifications (for not_affected)

Justification Description
code_not_present Vulnerable code not in codebase
code_not_reachable No execution path to vulnerable code
requires_configuration Requires specific config not present
requires_dependency Requires dependency not present
requires_environment Requires environment not applicable
protected_by_compiler Language/compiler prevents exploitation
protected_by_mitigating_control Other controls prevent exploitation

CycloneDX VEX Example

{
  "vulnerabilities": [
    {
      "id": "CVE-2021-44228",
      "affects": [
        { "ref": "pkg:maven/org.apache.logging.log4j/log4j-core@2.14.1" }
      ],
      "analysis": {
        "state": "not_affected",
        "justification": "code_not_reachable",
        "detail": "Static analysis confirms no call path from public API to vulnerable JNDI lookup.",
        "response": ["will_not_fix"]
      }
    }
  ]
}

LLM Role in SBOM Pipeline

LLMs should be used for explanation and orchestration, not analysis decisions:

DO Use LLMs For

  • Generating human-readable explanations
  • Summarizing attack paths
  • Drafting VEX narrative text
  • Suggesting remediation options

DO NOT Use LLMs For

  • Deciding exploitability state
  • Modifying component identities
  • Adding/removing dependencies
  • Overriding reachability engine results
Deterministic Engine → VEX state (machine)
LLM → VEX explanation (human-readable)

Tool Recommendations

Purpose Tools
SBOM Generation Syft, Trivy, cdxgen
SBOM Management Dependency-Track
SBOM Quality sbomqs
SBOM Diff SBOMDiff, cyclonedx-cli diff
Reachability graphize-appsec, govulncheck

References