Skip to main content

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.

AspectSPDXCycloneDX
FocusLicensing, compliance, supply-chain transparencyVulnerability and component analysis
FormatJSON, RDF, tag-value, spreadsheetJSON, XML
DepthRelationships and license groupsNested component trees, vulnerability metadata
AdoptionLinux Foundation; government/enterpriseOWASP; DevSecOps tools (Snyk, Dependabot)
npm tool supportvia npm-license-crawlervia 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/npm or 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.

Further Reading