Published 25 March 2026
SBOM for WordPress plugins: a practical guide
The Software Bill of Materials is one of the CRA’s most talked-about requirements, and probably the one that confuses WordPress developers the most. If you have never heard of an SBOM before, this guide explains what it is, why the regulation wants one, and how to actually generate one for your plugin.
What is an SBOM?
A Software Bill of Materials is a structured, machine-readable inventory of every component inside a piece of software. It lists each library, framework, package, and third-party dependency your software includes, along with version numbers, licence information, and other identifying metadata.
Think of it like a food ingredient label. A packaged food product must list its ingredients so consumers know what they are eating. An SBOM does the same for software: it tells users, auditors, and regulators what code is inside your product.
SBOMs are not a new idea. The software supply chain security community has been developing SBOM standards for years. What the CRA does is make them a legal requirement for products on the EU market. It went from best practice to compliance obligation.
Why the CRA requires an SBOM
The CRA requires manufacturers to identify and document all components and dependencies in their products. Annex I references the need to include an SBOM as part of the technical documentation package.
The reasoning is simple: you cannot manage what you do not know about. Modern software is built on layers of third-party libraries. A typical WordPress plugin might pull in a dozen Composer packages, each with its own dependencies, creating a tree that can run to hundreds of individual components.
When a vulnerability appears in one of those components, say a widely used HTTP client library, the first question every affected developer asks is: “Am I using that library?” Without an SBOM, answering that takes manual digging. With an SBOM, you check in seconds.
Here is what the SBOM actually does for you under the CRA:
- Vulnerability management: When a new CVE drops, you can immediately check whether your product is affected by cross-referencing the SBOM against advisory databases.
- Supply chain transparency: Downstream users and authorities can see what components your product contains and assess the associated risks.
- Licence compliance: An SBOM shows the licences of all included components, helping you verify that nothing has an incompatible licence.
- Incident response: During a security incident, an up-to-date SBOM tells you the exact scope of exposure without emergency code audits.
SBOM formats: CycloneDX vs SPDX
Two major SBOM formats exist: CycloneDX and SPDX. They are both open standards with wide support, and either one satisfies the CRA’s SBOM requirement.
CycloneDX
Developed by the OWASP Foundation, CycloneDX was built with security use cases in mind. It is a lightweight format available in JSON and XML, with good support for vulnerability tracking, dependency relationships, and licence metadata. It is popular among application security teams and fits the security-focused SBOM that the CRA envisions.
SPDX
SPDX (Software Package Data Exchange) came from the Linux Foundation and has its roots in licence compliance. It is an ISO standard (ISO/IEC 5962:2021) and is widely used in the open-source community, particularly for tracking licence obligations across dependency trees.
Which should you pick?
The CRA does not mandate a specific format. Both work. For WordPress plugin developers, we think CycloneDX is the more practical choice:
- Its JSON format is easy to generate and parse programmatically.
- It integrates well with vulnerability databases like OSV.dev and the NVD.
- The specification is smaller, so you can implement it faster without specialised tooling.
- CRA Guard uses CycloneDX 1.5 as its output format, so you can generate one with a single click inside your WordPress dashboard.
What goes in a WordPress plugin SBOM
Your SBOM should capture every component that ships with your plugin or theme when it lands on a user’s site. For a typical WordPress plugin, that means:
PHP dependencies (from composer.json)
If your plugin uses Composer, every package in your composer.json (and their transitive dependencies resolved in composer.lock) should appear in the SBOM. Common examples: HTTP clients like Guzzle, templating libraries, payment gateway SDKs, utility packages.
JavaScript dependencies (from package.json)
If your plugin has a frontend build step (React components, Vue apps, compiled scripts), the npm packages that end up in your built output are part of your shipped product. Dev-only dependencies like linters, test frameworks, and build tools generally do not need to appear since they are not distributed to end users.
Bundled third-party libraries
Some WordPress plugins include third-party libraries directly in the repo, vendored or copy-pasted without a package manager. These are often the hardest to track but just as important to document. If you have a /vendor or /lib directory with manually included code, each library should be in the SBOM with its version and licence.
WordPress core itself
Your plugin runs on WordPress, but WordPress core is not your product. It is the platform. You do not need to include WordPress core in your SBOM, the same way a mobile app developer does not include the operating system. However, if your plugin bundles a copy of a WordPress core component (like a specific version of jQuery or a WP utility library), that bundled copy should be listed.
What metadata to include for each component
For each component, include at minimum:
- Name, the package name (e.g.,
guzzlehttp/guzzle). - Version, the exact version included (e.g.,
7.8.1). - Type, whether it is a library, framework, or application.
- Licence, the SPDX licence identifier (e.g.,
MIT,GPL-2.0-or-later). - Package URL (purl), a standardised identifier for the component (e.g.,
pkg:composer/guzzlehttp/guzzle@7.8.1).
How to generate an SBOM
You have several options, from fully automated to completely manual. Here is what we have found works best.
Option 1: CRA Guard’s built-in SBOM generator
CRA Guard (premium tier) includes an SBOM generator built specifically for WordPress plugins. It reads your composer.json and composer.lock files, resolves the full dependency tree, and outputs a CycloneDX 1.5 JSON document. The whole thing runs inside your WordPress dashboard. Upload or point it at your project files and it produces the SBOM in one step.
If you want a CRA-ready SBOM without touching the command line or adding CI/CD steps, this is the fastest path.
Option 2: Composer CycloneDX plugin
The cyclonedx/cyclonedx-php-composer Composer plugin generates a CycloneDX SBOM directly from your Composer project. Install it as a dev dependency and run it during your build:
composer require --dev cyclonedx/cyclonedx-php-composer
composer make-bom --output-format=json --output-file=sbom.cdx.jsonGood option if you are comfortable with the terminal and want SBOM generation in your CI/CD pipeline.
Option 3: Syft (for multi-ecosystem projects)
Anchore’s Syft is a general-purpose SBOM tool that supports multiple ecosystems including Composer (PHP) and npm (JavaScript). It scans a project directory and produces a CycloneDX or SPDX document covering all detected dependencies. If your plugin has both PHP and JavaScript components, Syft captures both in a single SBOM. We have used it on a couple of projects and it works well, though the output can be verbose.
Option 4: Manual creation
For very simple plugins with few or no external dependencies, you can write an SBOM by hand. The CycloneDX JSON spec is straightforward, and a minimal document listing your plugin and its direct dependencies is not hard to create. But this does not scale and gets error-prone quickly once you have more than a handful of dependencies.
Keeping your SBOM current
An SBOM is not something you generate once and forget about. Every time you update a dependency, add a new library, or ship a new version of your plugin, the SBOM needs to be regenerated so it reflects what is actually in the product.
What we recommend:
- Regenerate on every release. Make SBOM generation part of your release checklist or build pipeline. We have it as a pre-release step.
- Version your SBOMs. Keep historical copies so you can trace which components were present in each release.
- Automate where you can. CI/CD integration means the SBOM stays current without you thinking about it.
- Cross-reference against vulnerability databases. Use your SBOM as input for regular vulnerability checks. CRA Guard’s vulnerability scanner does this automatically against the OSV.dev database.
Get started with your first SBOM
The SBOM requirement sounds intimidating if you have never dealt with one before, but in our experience it is one of the more straightforward CRA obligations. You already manage dependencies through composer.json and package.json. Generating an SBOM is mostly about formalising that information in a standard format.
CRA Guard makes it as simple as we could. Install the plugin, upload your composer.json, and generate a CycloneDX 1.5 SBOM in seconds. Pair it with the vulnerability scanner to see immediately whether any of your dependencies have known security issues.
For the broader compliance picture, including vulnerability handling, incident reporting, and documentation, read our complete CRA compliance guide.
Download CRA Guard Free on WordPress.org
Disclaimer: This article provides practical guidance on SBOM generation and is not legal advice. For authoritative interpretation of CRA requirements, consult a qualified legal professional.