Safeguard
Software Supply Chain•

How do you generate an SBOM for a PHP Composer project?

Install the CycloneDX Composer plugin, run make-sbom against an installed project, validate the output and run composer audit. Commands, flags and pitfalls.

Safeguard Security Team
4 min read

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

  1. Add the CycloneDX plugin as a dev dependency.
  2. In CI, run composer install --no-dev, then CycloneDX:make-sbom with JSON output and validation.
  3. Store the SBOM as a build artifact next to the release, named with the version.
  4. Run composer audit --locked and fail the build on findings you have not triaged.
  5. Generate separate SBOMs for the JavaScript assets and the container image.
  6. 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

Last reviewed: 18 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.