Common Platform Enumeration (CPE) is an open standard for naming software applications, operating systems, and hardware platforms in a consistent, structured way. It was developed in the mid-2000s by MITRE as part of efforts to improve automated security and asset management.
Today, NIST (as part of NVD, the National Vulnerability Database) manages the CPE program; organizations can submit new CPE entries for consideration to the NIST team.
CPE's main purpose is to facilitate the clear identification of software or hardware in security contexts. For example, vulnerability databases like the NVD tag each CVE (Common Vulnerability and Exposure) entry with the CPE names of affected products. Security scanners and vulnerability management tools then use those CPEs to determine if a given system or software component is impacted.
In essence, CPE provides a standardized, machine-readable format to encode the names and versions of IT products. This allows different tools and databases to refer to the same product using a common identifier.
In recent years, CPE has also found a role in software bill of materials (SBOM) documents. SBOM formats like CycloneDX and SPDX support listing CPE identifiers for components, which helps the SBOM consumer understand whether they may be affected by a particular vulnerability.
CPE Technical Details
CPE is based on a fixed, universal structure. Each CPE name is essentially a string divided into components that describe attributes of a particular platform or product.
The current version of CPE is the 2.3 specification (which was released in 2011). All references and examples in this section will be based on the current 2.3 spec.
CPE Component Attributes
Only the following attributes are considered valid as part of a CPE:
cpe:<version>:<part>:<vendor>:<product>:<version>:<update>:<edition>:<language>:<sw_edition>:<target_sw>:<target_hw>:<other>(Note that the “Edition” attribute was deprecated in CPE 2.3, but it’s included as an option to preserve backward compatibility with CPE 2.2)
Let’s briefly define these attributes:
- Part: This specifies the type of platform. It can be one of three letters:
afor application,ofor operating system, orhfor hardware. - Vendor: The organization or vendor that supplies the product.
- Product: The specific name of the software or platform.
- Version: The release version.
- Update: The update/patch level.
- Language: The language supported in the product’s UI as per the RFC5646 specification.
- SW_edition: How the product is tailored to the market, e.g. “Special” edition or “Online” edition.
- Target_sw: The software computing environment where the product operates.
- Target_hw: The instruction set architecture where the product operates.
- Other: Any additional product- or vendor-specific descriptor or information that doesn’t fit with one of the aforementioned attributes.
There are, of course, many scenarios where a specific application, operating system, or hardware component will not have values for each attribute on this list. In those cases, a value of either “ANY” or “NA” is assigned — we’ll explain the distinction and how these values are implemented in CPE strings in the following section.
CPE 2.3 Bindings
As you might imagine, the human-readable descriptions of the attributes listed above aren’t an ideal fit for automation. Rather, a conversion process is needed to ensure CPEs are fully machine-readable.
This process is referred to as formatted string binding. A CPE 2.3 string will begin with the prefix cpe:2.3: and include standardized attributes, separated by colons, in a pre-set order.
Additionally:
- Note that attributes with an “ANY” value (or unspecified value) are represented with an asterisk (*). “ANY” refers to cases where there aren’t restrictions on what can be considered an acceptable value for the given attribute or when the value is not specified. It’s common for CPEs to include multiple asterisks.
- Note that attributes with an “NA” value are represented with a hyphen (-). “NA” refers to “Not Applicable,” such as in cases when the given attribute is not used in the product’s description.
Let's explore an example based on OpenSSL 3.3.1 (any distribution or architecture), with the following attribute values:
[part="a", vendor="openssl", product="openssl", version="3.3.1", update=ANY, edition=ANY]This binds to the following CPE 2.3 formatted string:
cpe:2.3:a:openssl:openssl:3.3.1:::::::*In this example:
| Attribute | Value | Meaning |
|---|---|---|
| part | a | Application (as opposed to operating system o or hardware h) |
| vendor | openssl | The project/vendor name (as registered in the NVD CPE Dictionary) |
| product | openssl | The specific software package |
| version | 3.3.1 | The release version |
| update | * | Wildcard — no specific update level defined |
| edition, language, sw_edition, target_sw, target_hw, other | * | Wildcards, which represent "ANY" value or an unspecified value |
CPE Pros, Cons, and Comparisons
Although CPE shines in certain scenarios (such as standardizing the identification of commercial software), it struggles in other areas (such as reliably identifying open source software components).
And, while it shares a similar purpose with other commonly used unique identifiers (like PURL), there are meaningful differences.
CPE Pros
NVD Interoperability
CPE is the official naming scheme used by the NVD. If your tooling outputs CPEs, you can easily map products to CVEs using public vulnerability databases. This enables direct matching to known vulnerabilities without custom mappings and is important for automated vulnerability correlation in SCA tools and VEX analysis.
Commercial Software Support
Standardizing references to commercial software is an area where other naming schemes — such as PURL (Package URL) — tend to struggle. In contrast, software companies have long submitted their commercial products to NIST for inclusion in the CPE Dictionary. As such, organizations that rely on applications with a heavy volume of commercially produced components may find CPEs particularly helpful.
Asset and Risk Management
More broadly, CPE’s ability to support hardware and operating systems in addition to software packages helps teams build complete IT asset inventories with consistent naming across time and systems. CPE makes it easier to track risks associated with specific vendors, products, or product families.
CPE Cons
Inconsistent naming conventions
Although CPE entries are created following a defined specification, in practice, they often suffer from inconsistencies. This is the biggest downside we see associated with CPE. Different people or organizations may use slightly different naming for the same product, especially if the product’s name is complex.
For instance, one author might create a CPE for an open source library under vendor "apache," while another might use "apache_software_foundation.” As a result, CPE values are not always consistent or predictable. This can even lead to the outcome where a single real-world product ends up with multiple CPE names in the NVD because different CVE entries introduced the name in different ways.
Incomplete coverage of the software ecosystem
Typically, a CPE name gets added only when a CVE is published against a product/version. But this doesn’t necessarily mean the product/version doesn’t have vulnerabilities associated with it — just that the vulnerability isn’t in the NVD. The absence of a CPE for a component can be misleading, and it can force SBOM or tool vendors to invent placeholder CPE names if they want to include one. But those user-generated CPEs might not match any future official entry, leading to further inconsistency.
Centralization and lookup requirement
CPE is essentially a centralized identifier scheme. To know the "correct" CPE for a given product, one often has to consult the official CPE dictionary or NVD. Unlike PURLs, you cannot always derive a CPE name from the product itself without a reference. There is also little in the way of error tolerance: a typo or a version format mismatch often means a CPE query returns zero results, and it’s hard to know if that’s because the product has no vulnerabilities or the name was wrong.
CPE vs. PURL
CPE is not the only system for identifying software. PURL is another commonly used unique identifier, and it has clear advantages — and some disadvantages — when compared to CPE. (Though, to be clear, CPE and PURL can be used in a complementary fashion, so it isn’t necessarily an either/or proposition.)
PURLs are a newer URL-like identifier (e.g. pkg:maven/org.apache.logging/log4j-core@2.14.1) that precisely identifies software packages in package manager ecosystems. PURLs have become popular for SBOMs, especially in representing open source components, because they are generated from package metadata and don’t rely on a central authority. Unlike CPE, which might not exist for a given library until a CVE is created, PURLs cover virtually all packages by design. PURLs also avoid the inconsistency issues of CPE, which we documented earlier in this post.
On the other hand, PURL does not currently have robust support for commercial products. (Though, there are efforts to change that, such as those highlighted in this report from the OWASP SBOM Forum.) CPE, however, is commonly used for commercial products.
CPE and the SBOM Ecosystem
Originally, CPE was created largely to support automated vulnerability management programs. Today, in addition to supporting that use case, it plays a critical role in SBOM management.
Most SBOMs (including all that conform with NTIA requirements) include a unique identifier field for each component. The unique identifier field serves as a primary unlock for SBOMs to be truly machine-readable.
CPE (along with PURL) is a commonly used identifier. Formats like CycloneDX and SPDX support including CPE strings for components alongside other identifiers (such as package names or hashes).
In CycloneDX, CPE is an officially supported component. A CPE would be represented in the following way (replacing CPE HERE with the actual CPE string):
"components": [
{
"cpe":"CPE HERE"In SPDX, CPEs can be represented using the External Reference property, with the "SECURITY" category. A CPE would be represented as follows, replacing CPE HERE with the actual CPE. (Note the referenceType below refers to the current 2.3 CPE spec; there is a different referenceType for CPE 2.2.)
"externalRefs": [
{
"referenceCategory": "SECURITY",
"referenceType": "cpe23Type",
"referenceLocator": "CPE HERE"Despite this cross-format support for CPE, if and when possible, we'd recommend including both PURL and CPE in an SBOM (due to the limitations of each identifier). A common practice is to use PURLs for all packaged open source components (since those are readily obtainable) and supplement with CPE where it exists. Conversely, a commercial product might not have a PURL, but it may have a CPE for NVD lookup. This approach means that if a tool can't find a vulnerability via one unique identifier, it might find it via the other.
The Bottom Line on CPE
Despite its many limitations, Common Platform Enumeration (CPE) has a role to play in helping standardize the way we identify IT components. However, we strongly recommend against utilizing CPE as a sole or primary unique identifier.
Our recommended approach is to always include both PURL (to assist in open source component identification) and CPE (to assist in commercial software identification) in your SBOMs where possible, and request your software suppliers to do the same.
Along those lines, we’d advise organizations that have prioritized SBOM initiatives to make sure your SBOM and/or vulnerability management tooling vendors have PURL and CPE support.
If you have any questions about FOSSA's SBOM management or software supply chain security capabilities — or if you'd like to talk to one of our experts about using CPE/PURL in your organization — please reach out to our team.
Frequently Asked Questions About Common Platform Enumeration (CPE)
What is Common Platform Enumeration (CPE)?
Common Platform Enumeration (CPE) is an open standard for naming software applications, operating systems, and hardware platforms in a consistent, structured way. It was developed by MITRE in the mid-2000s and is now managed by NIST as part of the National Vulnerability Database (NVD). CPE provides a standardized, machine-readable format to encode the names and versions of IT products.
What is the current version of CPE?
The current version of CPE is 2.3, which was released in 2011. All CPE strings should use the cpe:2.3: prefix format, which includes standardized attributes separated by colons in a pre-set order.
How does CPE differ from PURL?
CPE is a centralized identifier scheme managed by NIST that requires consulting the official CPE dictionary to know the "correct" CPE for a product. PURL (Package URL) is a newer URL-like identifier that can be generated from package metadata and doesn't rely on a central authority. CPE is commonly used for commercial products, while PURL is popular for open source components in SBOMs.
What's better: CPE or PURL?
Neither CPE nor PURL is inherently better; they serve different purposes and have complementary strengths. CPE excels at identifying commercial software and has strong integration with the NVD for vulnerability matching. PURL is better for open source components, as it can be generated from package metadata and doesn't require a central authority. The best approach is to use both identifiers together in your SBOMs: PURLs for open source components and CPE where it exists, especially for commercial products. This dual-identifier strategy provides redundancy and improves vulnerability detection coverage.
Why is CPE important for SBOMs?
CPE plays a critical role in SBOM management because most SBOM formats (including CycloneDX and SPDX) support including CPE identifiers for components. CPE helps SBOM consumers understand whether they may be affected by a particular vulnerability by enabling direct matching to CVEs in the NVD.
What are the main limitations of CPE?
CPE suffers from inconsistent naming conventions, where different people or organizations may use slightly different naming for the same product. It also has incomplete coverage of the software ecosystem, as CPE names are typically only added when a CVE is published. Additionally, CPE requires centralization and lookup, making it less flexible than identifiers like PURL.
How is CPE used in vulnerability management?
CPE is the official naming scheme used by the NVD. Each CVE entry in the NVD is tagged with the CPE names of affected products. Security scanners and vulnerability management tools use those CPEs to determine if a given system or software component is impacted by known vulnerabilities.
Should I use CPE as my primary unique identifier in SBOMs?
No, we strongly recommend against utilizing CPE as a sole or primary unique identifier. Instead, always include both PURL (to assist in open source component identification) and CPE (to assist in commercial software identification) in your SBOMs where possible. This approach means that if a tool can't find a vulnerability via one unique identifier, it might find it via the other.
