Software Bill of Materials (SBOM) for React
A Software Bill of Materials (SBOM) is a detailed inventory of all dependencies in your React application, including their versions, licenses, and known vulnerabilities. SBOMs are increasingly required by regulations (US Executive Order 14028, NIST SSDF) and industry frameworks (FedRAMP, SOC 2). For React teams, generating and maintaining an SBOM makes it easier to respond to vulnerability disclosures, track license compliance, and demonstrate security posture to customers and auditors.
What is an SBOM and Why React Projects Need One
An SBOM documents: "What's inside your application?" For a React app with 400+ dependencies, the answer is complex. An SBOM captures every package, version, and dependency relationship in a machine-readable format. When a new vulnerability is disclosed, you can search your SBOM to determine if your app is affected, rather than manually reviewing package-lock.json.
SBOMs are especially important for:
- B2B SaaS: Customers ask for SBOMs during procurement to assess supply-chain risk.
- Government and regulated sectors: NIST SSDF and FedRAMP require SBOMs.
- Open-source projects: Transparency builds trust; published SBOMs are auditable.
- Vulnerability response: When a CVE is disclosed, your SBOM lets you answer "are we affected?" in seconds.
SBOM Formats: SPDX vs. CycloneDX
Two standards dominate: SPDX (Software Package Data Exchange) and CycloneDX.
| Aspect | SPDX | CycloneDX |
|---|---|---|
| Focus | Licensing, compliance, supply-chain transparency | Vulnerability and component analysis |
| Format | JSON, RDF, tag-value, spreadsheet | JSON, XML |
| Depth | Relationships and license groups | Nested component trees, vulnerability metadata |
| Adoption | Linux Foundation; government/enterprise | OWASP; DevSecOps tools (Snyk, Dependabot) |
| npm tool support | via npm-license-crawler | via cyclonedx-bom |
For React projects, use CycloneDX (better for npm, integrates with modern tools like Snyk and GitHub). For compliance-heavy contexts (regulated industries), use SPDX.
Generating an SBOM for React: CycloneDX Approach
Step 1: Install CycloneDX CLI
npm install --save-dev @cyclonedx/npm
Step 2: Generate the SBOM
npx cyclonedx-npm --output-file sbom.json
This scans your package-lock.json and produces a CycloneDX JSON file:
{
"bomFormat": "CycloneDX",
"specVersion": "1.4",
"serialNumber": "urn:uuid:...",
"version": 1,
"metadata": {
"timestamp": "2026-06-02T09:00:00Z",
"component": {
"bom-ref": "my-react-app",
"type": "application",
"name": "my-react-app",
"version": "1.0.0"
}
},
"components": [
{
"bom-ref": "pkg:npm/[email protected]",
"type": "library",
"name": "react",
"version": "18.2.0",
"purl": "pkg:npm/[email protected]",
"licenses": [
{
"license": {
"name": "MIT"
}
}
],
"hashes": [
{
"alg": "SHA-1",
"content": "9ITUguJv6w5u..."
}
]
},
{
"bom-ref": "pkg:npm/[email protected]",
"type": "library",
"name": "react-dom",
"version": "18.2.0",
"purl": "pkg:npm/[email protected]",
"licenses": [
{
"license": {
"name": "MIT"
}
}
]
}
]
}
Each component includes: name, version, license, and a Package URL (PURL) for lookup. The SBOM is complete: all 400+ dependencies are listed.
Enriching Your SBOM with Vulnerability Data
CycloneDX supports embedding vulnerability metadata:
npx cyclonedx-npm --output-file sbom.json --component-depth 10
For richer vulnerability information, use Snyk's SBOM generator (integrates npm audit data):
npm install --save-dev snyk
npx snyk sbom --format=cyclonedx --json > sbom.json
This produces an SBOM with vulnerability annotations:
{
"components": [
{
"bom-ref": "pkg:npm/[email protected]",
"type": "library",
"name": "body-parser",
"version": "1.20.0",
"vulnerabilities": [
{
"ref": "CVE-2024-1234",
"source": {
"name": "NVD"
},
"severity": "high",
"description": "HTTP Request Smuggling"
}
]
}
]
}
Now auditors and security tools can scan the SBOM directly without re-running npm audit.
Integrating SBOM Generation into CI/CD
Add SBOM generation to your CI/CD pipeline so it's always up-to-date:
# .github/workflows/sbom.yml
name: Generate SBOM
on:
push:
branches: [main]
schedule:
- cron: '0 0 * * 0' # Weekly
jobs:
sbom:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'
- run: npm ci
- run: npm install --save-dev @cyclonedx/npm
- name: Generate SBOM
run: npx cyclonedx-npm --output-file sbom.json
- name: Upload SBOM to GitHub
uses: actions/upload-artifact@v4
with:
name: sbom
path: sbom.json
- name: Commit SBOM
run: |
git config user.name "GitHub Actions"
git config user.email "[email protected]"
git add sbom.json
git commit -m "chore: update SBOM" || exit 0
git push
This generates the SBOM weekly and commits it to the repository, ensuring it's always synchronized with package-lock.json.
Using Your SBOM: Vulnerability Response Workflow
When a vulnerability is disclosed (e.g., CVE-2024-1234 in body-parser), you can search your SBOM:
# Search for affected component
jq '.components[] | select(.name == "body-parser" and .vulnerabilities[]?.ref == "CVE-2024-1234")' sbom.json
If found, determine the version:
jq '.components[] | select(.name == "body-parser") | {name, version}' sbom.json
Output: {"name": "body-parser", "version": "1.20.0"}. Check against the CVE advisory (e.g., "affects < 1.20.3"). If your version matches, patch it immediately.
This takes seconds instead of manually searching package-lock.json.
Licensing Compliance via SBOM
An SBOM lists all licenses. Use it to audit compliance:
# Extract all unique licenses
jq -r '.components[].licenses[].license.name' sbom.json | sort -u
Output:
Apache-2.0
ISC
MIT
Ensure all licenses are acceptable. If a component uses GPL and your project is closed-source, that's a conflict. The SBOM makes this visible.
Publishing Your SBOM for Transparency
For open-source React libraries or transparent B2B applications, publish your SBOM in your GitHub releases:
# In your CI/CD, after generating sbom.json:
gh release upload v1.0.0 sbom.json --clobber
Users and security auditors can download the SBOM and inspect it. This builds trust and enables supply-chain transparency.
Key Takeaways
- An SBOM is a machine-readable inventory of all dependencies, versions, and licenses in your React app.
- CycloneDX is the preferred format for npm/Node.js projects; SPDX is better for licensing compliance.
- Generate SBOMs in CI/CD using
@cyclonedx/npmor Snyk; commit them to version control. - When vulnerabilities are disclosed, search the SBOM to determine affected versions in seconds.
- Publishing SBOMs (in releases or documentation) demonstrates security posture to customers and auditors.
Frequently Asked Questions
Does generating an SBOM slow down my build?
No. SBOM generation scans package-lock.json only, which is instant (< 1 second). It's a post-build artifact, not a blocking step.
Should I version-control the SBOM file?
Yes. Commit sbom.json to Git. This creates an audit trail: you can see when dependencies changed, helping with retrospective vulnerability analysis.
Can I use SBOM for security scanning instead of npm audit?
Partially. npm audit scans against real-time vulnerability databases; SBOM is a static snapshot. Use SBOM for compliance and historical analysis; use npm audit for real-time detection.
What if my SBOM lists GPL dependencies but my project is closed-source?
This is a legal issue, not a technical one. The SBOM makes it visible, forcing a decision: relicense, replace the dependency, or obtain a license from the GPL maintainer. Better to know upfront via SBOM than discover it at audit time.