
September 09, 2026
12 min read
By Kokil Thapa | Last reviewed: September 2026
You ship code weekly, but can you list every library inside your production build in under five minutes? That gap is exactly why teams now need to SBOM: Generate a Software Bill of Materials as a standard release artefact. An SBOM is a machine-readable inventory of components, versions, licences, and relationships in your application stack. Regulators, enterprise buyers, and security teams increasingly expect one before they trust your software. This guide walks through practical generation for Laravel and PHP stacks you already run in production.
What Is an SBOM and Why Should You Generate a Software Bill of Materials?
An SBOM is structured metadata about what your software contains. Think of it as a parts list for code. Each entry names a component, its version, its supplier, and often its licence. When a CVE hits a library, you search the SBOM instead of guessing which servers run the vulnerable package.
The U.S. National Telecommunications and Information Administration defines minimum SBOM elements: supplier name, component name, version, other unique identifiers, dependency relationship, author, and timestamp. You do not need a custom spreadsheet. Standard formats like SPDX and CycloneDX encode those fields so scanners and auditors can consume them automatically.
On real client projects I maintain, SBOM output lives beside the build artefact. When a client asks for supply-chain documentation, you hand over a file generated from the same commit that went live. That beats reconstructing dependencies from memory two months later.
Supply-chain attacks moved SBOM from niche to normal. The NTIA minimum elements guide remains the baseline reference most procurement teams cite. If you sell B2B software or maintain portals for regulated sectors, expect SBOM requests in RFPs.
Who needs an SBOM today
- Teams shipping Laravel or WordPress apps with dozens of Composer or plugin dependencies
- Agencies delivering enterprise application development to clients with audit requirements
- DevOps engineers running CI pipelines that already lint and test each deploy
- eCommerce platforms where a vulnerable payment or cart library creates direct business risk
How Do You Generate an SBOM for a Laravel or PHP Application?
PHP projects expose dependencies through composer.lock. That lock file is your ground truth. Never generate an SBOM from composer.json alone — it lists version ranges, not pinned releases. The same rule applies to Node: use package-lock.json, not bare package.json.
Start with CycloneDX tooling. The official CLI reads lock files and emits standard JSON. Install it globally or run it in CI with a pinned version.
# Install CycloneDX CLI (Node 26 LTS)
npm install -g @cyclonedx/cyclonedx-npm @cyclonedx/cyclonedx-php-composer
# Generate SBOM from Composer lock
cyclonedx-php-composer make-sbom \
--output-file=sbom-composer.json \
--output-format=JSON
# Generate SBOM from npm lock (Vite 8.x frontend)
cyclonedx-npm --output-file sbom-npm.json --output-format JSON
For SPDX output, use syft from Anchore. It scans directories, container images, or lock files and supports multiple formats.
# Install syft (check latest release tag on GitHub)
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
# Scan project root — picks up composer.lock and package-lock.json
syft dir:. -o spdx-json=sbom-spdx.json
# Scan a built Docker image after deploy
syft packages your-registry/app:1.4.2 -o cyclonedx-json=sbom-image.json
On a production Laravel application, I run both Composer and npm scans because the attack surface spans backend and frontend. Merge is optional early on. Two files per release is fine until your compliance team asks for one unified document.
Laravel-specific checklist
- Commit
composer.lockandpackage-lock.json— never deploy without them - Run SBOM generation after
composer install --no-devon the release build - Include PHP runtime version in metadata (PHP 8.3 minimum for Laravel 13, PHP 8.2 for Laravel 12)
- Store SBOM files in your artefact bucket with the git SHA in the filename
- Attach SBOM hash to your deploy log for traceability
WordPress and WooCommerce stacks need a different scan target. Scan the wp-content/plugins and themes directories plus core version. For sites I maintain under support and maintenance contracts, a quarterly SBOM diff catches plugins that drifted out of date.
Which SBOM Format Should You Choose: SPDX, CycloneDX, or SWID?
Three formats dominate. Pick one primary format per organisation. Converting between them is possible but lossy. Standardise early so your CI templates stay simple.
| Format | Best for | Licence metadata | Tooling ecosystem | Typical output |
|---|---|---|---|---|
| SPDX | Legal and licence compliance teams | Excellent — built for licence expressions | syft, SPDX tools, Linux Foundation | .spdx, JSON, YAML |
| CycloneDX | Security and DevSecOps workflows | Good — improving each release | CycloneDX CLI, Dependency-Track, Grype | .json, .xml |
| SWID | Enterprise IT asset management | Limited compared to SPDX | TagVault, commercial scanners | ISO/IEC 19770-2 tags |
For most web agencies and product teams, CycloneDX JSON is the pragmatic default. It integrates cleanly with OWASP Dependency-Track and vulnerability scanners. SPDX wins when your client's legal team cares deeply about licence classification. The SPDX specification and CycloneDX specification are the authoritative references — read the schema once so you know which fields auditors will ask about.
SWID tags matter mainly for packaged desktop or appliance software. Most Laravel and WordPress deployments never need SWID unless a procurement template explicitly requires ISO/IEC 19770-2 tags.
How Do You Integrate SBOM Generation Into CI/CD Pipelines?
Manual SBOM creation fails within a month. Someone forgets, or the file drifts from the deployed build. Wire generation into the same pipeline that runs tests. I use GitLab CI on several sister sites sharing a Deployer 7 workflow — the pattern below fits that stack and adapts to GitHub Actions easily.
# .gitlab-ci.yml excerpt
generate_sbom:
stage: build
image: node:26-bookworm
script:
- curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
- composer install --no-dev --prefer-dist --no-interaction
- npm ci
- syft dir:. -o cyclonedx-json=sbom-${CI_COMMIT_SHORT_SHA}.json
- grype sbom:${CI_COMMIT_SHORT_SHA}.json --fail-on high
artifacts:
paths:
- sbom-*.json
expire_in: 1 year
rules:
- if: $CI_COMMIT_BRANCH == "main"
Pair SBOM output with a vulnerability scanner. Grype reads CycloneDX directly. OSV-Scanner accepts SPDX. Fail the pipeline on critical CVEs only after you have a remediation process. Blocking every low-severity finding on day one creates noise your team will ignore.
Sign the SBOM if your compliance framework requires integrity proof. GPG-sign the JSON file and store the detached signature alongside it. Document the public key in your internal runbook. For smaller agencies, a checksum in the CI log plus immutable artefact storage is often enough.
GitLab CI vs GitHub Actions placement
Run SBOM generation in the build stage, before deploy. The scan must reflect the exact dependency tree that ships. Scanning your dev laptop and deploying different packages from CI defeats the purpose. On projects using Linux system administration with Deployer 7, I attach the SBOM filename to the release tag notes.
Validate JSON output in CI with a schema check. CycloneDX publishes a JSON schema. A one-line ajv validate step catches malformed files before they reach a client inbox. Use the JSON formatter tool locally when debugging schema errors — truncated arrays and missing required fields show up fast with pretty-printed output.
What Are Common SBOM Generation Mistakes in Production Deployments?
Most SBOM programmes fail on process, not tooling. These mistakes show up repeatedly across client audits and internal reviews.
- Scanning dev dependencies in production SBOMs. Run
composer install --no-devfirst. Dev tools like PHPUnit should not appear in production SBOMs. - Ignoring transitive dependencies. Your SBOM must include nested packages, not just top-level entries. Both syft and CycloneDX resolve the full tree from lock files.
- Generating once and never updating. An SBOM from six months ago is historical data, not a current inventory. Tie generation to every release.
- Skipping container base images. If you deploy Docker, scan the image layer. OS packages in the base image carry CVEs too.
- No linkage to deployed version. Always embed git SHA, build timestamp, and environment in SBOM metadata fields.
A pattern I have seen repeatedly: teams store SBOM files in email threads. Put them in object storage or your CI artefact registry with retention matching your compliance window. For legal-tech portals like Mijar Law Associates or booking systems such as Adventure Third Pole Trek, document retention matters as much as generation.
Vulnerability response workflow
When a CVE drops, import the latest SBOM into Dependency-Track or run Grype against it. Identify affected services. Patch, redeploy, regenerate SBOM. Record the cycle in your incident log. This workflow pairs naturally with API security practices and secrets management covered in Ansible Vault for secrets.
For eCommerce systems like Quick And Easy Nepalese Grocery, payment libraries and cart packages deserve priority in your vulnerability triage. Not every CVE is exploitable in your configuration. Document why you accepted or deferred each finding.
How Do You Validate and Share an SBOM With Clients or Auditors?
Generation is half the job. Delivery and validation complete it. Auditors want three things: completeness, accuracy, and traceability to a specific release.
Validate completeness against NTIA minimum elements. Your SBOM should list supplier, component name, version, unique identifier (PURL or CPE), dependency relationship, timestamp, and author. CycloneDX and SPDX both support these fields when generated from lock files.
Share SBOMs through secure channels. A password-protected zip sent over email works for small clients. Larger enterprises prefer SFTP or a vendor portal upload. Include a README explaining format, generator tool, and version scanned.
Cost is modest. Open-source tools are free. Dependency-Track community edition runs on a small VPS — roughly Rs 2,500/month (~USD 19) on a basic cloud instance. The labour cost is pipeline setup, typically four to eight hours for a standard Laravel project. That is cheaper than an emergency audit after a supply-chain incident.
If you build custom platforms under custom software development contracts, add SBOM delivery to your statement of work now. Clients will ask for it. Pricing the work upfront avoids scope arguments later.
Key Takeaways
- Generate SBOMs from lock files (
composer.lock,package-lock.json), not loose manifest version ranges. - Standardise on CycloneDX JSON for security workflows or SPDX JSON for licence-heavy audits.
- Wire SBOM generation and vulnerability scanning into CI so every main-branch release produces a fresh artefact.
- Store SBOM files with git SHA, timestamp, and optional GPG signature — not in email threads.
- Run
composer install --no-devbefore scanning so production SBOMs exclude test tooling. - Pair SBOM output with Grype or OSV-Scanner and define clear severity thresholds before failing builds.
People Also Ask
Is an SBOM required by law in 2026?
No universal global mandate exists yet, but U.S. federal software procurement guidelines and EU cyber-resilience proposals strongly encourage SBOM delivery. Enterprise RFPs and security questionnaires increasingly treat SBOMs as expected deliverables regardless of formal regulation.
Can I generate an SBOM without Docker?
Yes. Tools like syft and CycloneDX CLI scan local directories and lock files directly. Docker scanning adds value when you containerise deployments, but bare-metal Laravel apps on Apache and PHP-FPM work fine with directory-based scans.
How often should you regenerate an SBOM?
Regenerate on every production release at minimum. Weekly regeneration helps high-churn teams. The SBOM must always match the deployed build — a stale file is worse than none because it creates false confidence.
What is the difference between an SBOM and a dependency audit?
An SBOM is a structured inventory of all components. A dependency audit evaluates those components for known vulnerabilities, licence conflicts, or outdated versions. Run the audit against the SBOM — they are complementary, not interchangeable.
Build Supply-Chain Visibility Into Your Next Release
You now have the tooling, format choices, and CI patterns to SBOM: Generate a Software Bill of Materials on every release instead of scrambling during an audit. Start with one Laravel or WordPress project, add a syft step to your existing pipeline, and store the output beside your deploy artefacts. Expand to vulnerability gating once the baseline workflow is stable. If you want help wiring SBOM generation into a production stack or testing and optimization pipeline, contact us to discuss your deployment setup. You can also review how we ship secure platforms in our portfolio or explore related DevOps reading on multi-cloud deployment patterns and essential developer tooling.
Frequently Asked Questions
0 Comments
Leave a comment
Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

