To generate an SBOM for a PHP project, install the CycloneDX Composer plugin, run composer CycloneDX:make-sbom in a project where composer install has run, write JSON output to a file, and validate it. Pair it with composer audit, which checks the same packages against advisories.
What is in a PHP SBOM?
An SBOM is, in CISA's words, a nested inventory: a list of the ingredients that make up software components. For a Composer project, the ingredients are the packages in composer.lock and their versions, licenses and relationships. CycloneDX, an OWASP specification now also standardised as ECMA-424, is one of the common formats; its current version listed on the project site is 1.7.
How do you install the generator?
The CycloneDX PHP Composer plugin is documented in its repository. It requires PHP 8.1 or later and Composer 2.3 or later for the current release line, and older plugin versions exist for older setups.
composer require --dev cyclonedx/cyclonedx-php-composer
You can also install it globally with composer global require, which keeps it out of your project's dependency set.
How do you run it?
The plugin adds the command CycloneDX:make-sbom. The repository documents these options, among others:
- output format: JSON or XML (XML is the default)
- output file path, with a dash meaning standard output
- omit dependency types: dev, plugin
- spec version, from 1.1 up to 1.7, defaulting to 1.5
- reproducible output
- validation of the resulting document
A practical release command:
composer install --no-dev --no-interaction
composer CycloneDX:make-sbom \
--output-format=JSON \
--output-file=sbom.cdx.json \
--spec-version=1.6 \
--validate
Check composer CycloneDX:make-sbom --help on your installed version, since flags can change between releases.
What does the tool read?
Per its documentation, it uses Composer itself to collect evidence about installed packages, and it prefers an actually installed setup over pure lock file analysis. It needs the manifest plus either a real install or a working lock file. So generate the SBOM in the same stage that builds the artifact, after install, not from a stale checkout.
Decide on dev dependencies on purpose. An SBOM for what ships should omit dev packages, for example by installing with --no-dev or using the omit option. An SBOM for audit of the build environment can include them. Label which one you made.
How is this different from composer audit?
composer audit is a check, not an inventory. Composer's documentation says it audits installed packages against dependency policies such as security advisories, using the Packagist API by default. It also detects abandoned packages and packages flagged as malware, and returns exit code 1 when it finds matching packages. It supports --locked to audit the lock file regardless of what is in the vendor directory, --no-dev, and several output formats.
Use both. The SBOM is the record you hand to a customer or store with the release. The audit is the gate that fails the build.
What goes wrong?
- Generating from a lock file that is out of date with
composer.json. - Mixing dev and production packages and then reporting findings in test tools as production risk.
- Forgetting non Composer components. A PHP application often also ships JavaScript assets, system packages in its container, and bundled libraries. Composer's SBOM covers only the Composer part.
- Treating the SBOM as static. It describes one build; regenerate per release.
What to do
- Add the CycloneDX plugin as a dev dependency.
- In CI, run
composer install --no-dev, thenCycloneDX:make-sbomwith JSON output and validation. - Store the SBOM as a build artifact next to the release, named with the version.
- Run
composer audit --lockedand fail the build on findings you have not triaged. - Generate separate SBOMs for the JavaScript assets and the container image.
- Re run the audit on a schedule, because new advisories appear after you ship.
Safeguard's SBOM and dependency scanning can ingest this file and add reachability analysis, so you can tell which advisories your code actually calls.
Quick check
Does the SBOM tell me if a package is vulnerable?
Not by itself. It lists what you ship. You match that list against advisories, with a tool such as composer audit or a scanner.
Which spec version should I choose?
The plugin defaults to 1.5 and supports up to 1.7 per its repository. Choose the newest version your downstream consumers can read.
Sources
- CycloneDX PHP Composer plugin, GitHub, fetched 18 October 2026
- Composer command line reference, audit, Composer docs, fetched 18 October 2026
- CycloneDX specification overview, OWASP CycloneDX, fetched 18 October 2026
- Software Bill of Materials, CISA, fetched 18 October 2026
Last reviewed: 18 October 2026.