The Security Audit That Took Three Weeks (And Should Have Taken Three Minutes)
"We need a complete inventory of all software components in production by Friday."
The email from our compliance team landed on a Tuesday. We had three days to document every library, framework, OS package, and dependency across 150+ microservices. Oh, and they needed licenses, versions, and known vulnerabilities too.
I spent the first day in denial. The second day manually running npm ls, pip freeze, and mvn dependency:tree on dozens of repositories. By Wednesday night, I had Excel spreadsheets everywhere, merge conflicts in my brain, and still no clear picture of what was actually running in production.
Thursday morning, I discovered that Production wasn't running the code in Git. Containers had been patched manually. Services had emergency hotfixes never committed to source. My inventory was already obsolete before I finished it.
We missed the Friday deadline. The audit was delayed. And I learned a hard lesson: if you can't automatically generate an SBOM, you don't actually know what's in your software.
This article covers how I implemented automated SBOM generation, made it part of every build, and turned a three-week nightmare into a three-second API call.
What You'll Learn
Understanding Software Bill of Materials (SBOM) standards
SBOM formats: SPDX vs CycloneDX
Generating SBOMs with Syft, Trivy, and other tools
SBOM validation and enrichment
Integrating SBOM into CI/CD pipelines
SBOM for compliance (Executive Order 14028)
Supply chain transparency and attestation
What is an SBOM?
A Software Bill of Materials is a comprehensive inventory of all components in your softwareβlike a nutrition label for your application.
An SBOM includes:
Component names and versions
Dependencies (direct and transitive)
Licenses
Source locations
Cryptographic hashes
Supplier information
Known vulnerabilities (when enriched)
SBOM Standards: SPDX vs CycloneDX
SPDX (Software Package Data Exchange)
Created by the Linux Foundation, SPDX is the ISO standard (ISO/IEC 5962:2021).
CycloneDX
Created by OWASP, CycloneDX is focused on security use cases and supply chain transparency.
Comparison:
Feature
SPDX
CycloneDX
Standard
ISO/IEC 5962:2021
OWASP
Focus
License compliance
Security & supply chain
Vulnerability data
Extension
Built-in
Formats
JSON, YAML, RDF, TagValue
JSON, XML, Protocol Buffers
Services/APIs
Limited
Strong support
Attestation
Via extensions
Native VEX/VDR support
Generating SBOMs with Syft
Syft is my preferred SBOM generatorβit's fast, accurate, and supports both SPDX and CycloneDX.
Basic Syft Usage
GitLab CI SBOM Generation
SBOM Enrichment with Vulnerability Data
An SBOM becomes exponentially more valuable when enriched with vulnerability information.
Grype for Vulnerability Scanning
GitLab Integration
SBOM Validation and Quality
Not all SBOMs are created equal. Validate yours to ensure quality.
SBOM Quality Checker
SBOM for Compliance: Executive Order 14028
The U.S. Executive Order 14028 requires SBOMs for software sold to the federal government.
Compliance Requirements
Compliance Automation
SBOM Distribution and Consumption
Publishing SBOMs
SBOM API Service
Best Practices
1. Generate SBOMs at Build Time
2. Version and Store SBOMs
3. Enrich with Vulnerability Data
4. Automate SBOM Comparison
5. Make SBOMs Discoverable
Key Takeaways
β Generate SBOMs automatically - Part of every build β Choose the right format - CycloneDX for security, SPDX for compliance β Enrich with vulnerabilities - SBOMs + security data = powerful β Validate SBOM quality - Check completeness and accuracy β Store and version SBOMs - Track changes over time β Comply with regulations - EO 14028 and beyond β Make SBOMs accessible - APIs, registries, well-known URLs
What's Next
SBOMs document what you're deploying. Next, we'll ensure your infrastructure configuration itself is secureβInfrastructure as Code security scanning, policy enforcement, and compliance automation.
# sbom-compliance-policy.yml
requirements:
format:
- SPDX 2.2+ (JSON, YAML, or tag-value)
- CycloneDX 1.4+ (JSON or XML)
minimum_elements:
- Supplier name
- Component name
- Version of the component
- Other unique identifiers
- Dependency relationships
- Author of SBOM data
- Timestamp
recommended_elements:
- Cryptographic hash (SHA-256)
- License information
- Known vulnerabilities
- End of life/support dates
delivery:
- Machine-readable format
- Provided with software
- Updated on each release
# .gitlab-ci.yml
compliance_check:
stage: sbom
image: node:18-alpine
before_script:
- npm install -g @cyclonedx/cyclonedx-cli
script:
# Validate SBOM meets compliance requirements
- cyclonedx validate --input-file sbom-cyclonedx.json
# Check for required elements
- |
node -e "
const sbom = require('./sbom-cyclonedx.json');
const required = [
'metadata.component.supplier',
'metadata.component.name',
'metadata.component.version',
'metadata.timestamp'
];
const missing = required.filter(path => {
const parts = path.split('.');
let obj = sbom;
for (const part of parts) {
if (!obj[part]) return true;
obj = obj[part];
}
return false;
});
if (missing.length > 0) {
console.error('β Missing required elements:', missing);
process.exit(1);
}
console.log('β All required elements present');
"
dependencies:
- generate_sbom