-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
The semantics of CPE are insufficiently defined #12
Comments
I'm not suggesting that the CVE Record Format change to require or depend on CPE, but here is an NVD JSON example (https://services.nvd.nist.gov/rest/json/cves/2.0?cveId=CVE-2021-40690) where the CPE is clearly bound to status. [
{
"operator": "OR",
"negate": false,
"cpeMatch": [
{
"vulnerable": true,
"criteria": "cpe:2.3:a:apache:santuario_xml_security_for_java:*:*:*:*:*:*:*:*",
"versionEndExcluding": "2.1.7",
"matchCriteriaId": "AB706AA4-B7E9-4319-A2C0-65B7186507DB"
},
{
"vulnerable": true,
"criteria": "cpe:2.3:a:apache:santuario_xml_security_for_java:*:*:*:*:*:*:*:*",
"versionStartIncluding": "2.2.0",
"versionEndExcluding": "2.2.3",
"matchCriteriaId": "20BABD5C-5813-48B8-BAC9-0F36F381F12A"
}
]
}
]
|
A Microsoft CVE JSON example, good {
"vendor": "Microsoft",
"product": "Windows 10 Version 1809",
"cpes": [
"cpe:2.3:o:microsoft:windows_10_1809:10.0.17763.5820:*:*:*:*:*:x86:*",
"cpe:2.3:o:microsoft:windows_10_1809:10.0.17763.5820:*:*:*:*:*:x64:*",
"cpe:2.3:o:microsoft:windows_10_1809:10.0.17763.5820:*:*:*:*:*:arm64:*"
],
"platforms": [
"32-bit Systems",
"x64-based Systems",
"ARM64-based Systems"
],
"versions": [
{
"version": "10.0.0",
"lessThan": "10.0.17763.5820",
"versionType": "custom",
"status": "affected"
}
]
} |
https://cveproject.github.io/cve-schema/schema/docs/#oneOf_i0_containers_cna_affected_items_cpes
|
Note that if defaultStatus is not specified, it's unknown. IOW, we don't know one way or the other. My thinking is that in this example, the versions block is specified and lists a status of affected. Seems appropriate that this would translate to the defined CPEs and they also display the same affected versions in the CPEs. I could see how this would get much harder to interpret if multiple version blocks were included. In this case though, it's likely that they intended defaultStatus: unaffected. |
I created a related issue against the cve-schema repo today. Basically ADPs should be allowed to create a cpes array on it's own without having to define potentially conflicting or inaccurate product and version info. I hadn't considered the Red Hat example where it appears that the CPE info is complimentary to the product and version info. |
One option (which could be specific to an ADP) could be to require that any CVE |
Another option: CVE JSON could implement the CPE Applicability Language, or a subset of it, in order to use CPE to logically define status, versions, and version ranges. |
My knowledge about CPEs is largely informed by https://en.wikipedia.org/wiki/Common_Platform_Enumeration because I find it easier to consume than anything else... Separating vulnerable version identification from vulnerable product identification for a moment, in the light of CPEs (I believe) not yet being widely present on CVE List CVE records, I'd been wondering if the That would require tightening up the definition of what is expected to appear in It is my understanding that while there is a perception that there's a bootstrapping/chicken-and-egg problem with CPEs (until a product has its first CVE, it doesn't have a defined CPE) this is something of a myth, and it's possible to proactively request CPEs (in bulk even) from the NVD. This would mean that in line with the Secretariat's request for (vendor) CNAs to start adding CPEs to their CVEs, they should also be requested to obtain CPE Dictionary entries for products they own that have not yet had CVEs reported for. /cc @MrMegaZone |
@zmanion I'd discourage premature solutioning without having the actual requirements nailing down first. The |
Adding another example from https://cveawg.mitre.org/api/cve/CVE-2024-0229: {
"vendor": "Red Hat",
"product": "OpenShift Service Mesh 2.3.x",
"collectionURL": "https://access.redhat.com/downloads/content/package-browser/",
"packageName": "(as-yet-unknown)",
"defaultStatus": "affected",
"cpes": [
"cpe:/a:redhat:service_mesh:2.3"
]
} |
@zmanion Red Hat's use of CPEs is kind of unique (as you've discovered here). We still use CPE 2.2, which is at this point a very old standard. We've always used CPEs as a way to identify products (think RHEL 9.2, Windows 10.xyz). A product is by nature a loose concept that gives a grouping of components an arbitrary version number just so it's easier to refer to one thing rather than saying "I'm running kernel x.y.z, gnome a.b.c, emacs m.n.o, etc." We still need to be able to attach components to products somehow, so our affected entries always contain both the identifier of the product (one or more CPEs) and the individual components themselves, identified using the CPEs also then map to individual repositories from where (mostly RPM) content can be fetched using a mapping file available here: https://access.redhat.com/security/data/meta/v1/repository-to-cpe.json. This help scanning vendors to identify where a certain package on a system that is being scanned came from and they are able to link it to a specific product using all this data. Since we use CPEs as unique identifiers of products, they could just as well be UUIDs; that's the same reason why we haven't really pushed hard to update to CPE 2.3. CPEs are just much nicer to read than serial / SKU numbers or UUIDs. The textual descriptions in the The schema isn't very prescriptive about the use of CPEs so our interpretation is essentially:
I'll also note that our CSAF VEX files have this defined in a way that is a bit more intuitive. The product tree contains nodes for the products themselves, e.g.: {
"category": "product_name",
"name": "Red Hat Enterprise Linux AppStream EUS (v.9.2)",
"product": {
"name": "Red Hat Enterprise Linux AppStream EUS (v.9.2)",
"product_id": "AppStream-9.2.0.Z.EUS",
"product_identification_helper": {
"cpe": "cpe:/a:redhat:rhel_eus:9.2::appstream"
}
}
} and then nodes that identify an individual component, e.g.: {
"category": "product_version",
"name": "tigervnc-server-0:1.12.0-14.el9_2.5.aarch64",
"product": {
"name": "tigervnc-server-0:1.12.0-14.el9_2.5.aarch64",
"product_id": "tigervnc-server-0:1.12.0-14.el9_2.5.aarch64",
"product_identification_helper": {
"purl": "pkg:rpm/redhat/[email protected]_2.5?arch=aarch64"
}
}
} These two are then linked with a relationship node:
Here too we use CPEs as just an identifier of a particular product, and purls to identify a given component (we're still exploring what the best way to represent component version ranges is in this format, but we want to add it at some point). The CVE JSON schema could potentially borrow from this approach and move the We're open to feedback on any of the above of course, and happy to discuss the usage of CPEs across the entire data set. |
@mprpic thanks for the explanation. To be clear, and after some discussion on a couple WG meetings, my concern is with the CVE schema and not how Red Hat implements Today, without any schema changes, I think there may be a way (or ways) to un- or less ambiguously connect |
CPEs lack the ability to express a version range. This is why CVE 5.x has the richer syntax in the The SBOM Forum's paper touches on this, in part. I don't think doubling down on CPEs is a good strategy to pursue. If we focus on requirements, and drill down into vulnerability scanning in particular: a scanner needs a way to take the thing to be scanned (let's say it's a "product", made by a "vendor", at a particular "version") and determine how many CVEs "match" this. I think historically, scanners have turned that "product/vendor/version" information into a CPE string and then tried to match it exactly, which creates the need for affected version enumeration to be performed somewhere. |
CPE can express ranges, although it seems to have been added after the original specification(s) were published. Maybe it's more correct to say that NVD JSON can express ranges using CPE. https://nvd.nist.gov/General/News/CPE-Range-Notification I'd prefer a model that is agnostic to the software identifier, so that CPE could be a choice, but so could other identifiers. Not sure if this is even possible given the variety of version/range semantics. |
We're talking about subtly different things. I'm referring to the I fail to understand how examples 1 and 2 here are defining ranges. The third example is the
I believe you can achieve the moral equivalent of this with CVE 5.x
I agree that if we settled on using the CPE Dictionary to arbitrate valid values for |
On the https://nvd.nist.gov/General/News/CPE-Range-Notification page, Example 1 and Example 2 are examples of "On the vulnerability detail pages, ranges will be displayed to the user" mentioned in the first paragraph. Specifically, English words and phrases such as "Up to (including)" are displayed as part of the HTML on pages such as https://nvd.nist.gov/vuln/detail/CVE-2017-5528 (this is not identical to Example 1). English words and phrases such as "Up to (including)" are not an example of the change to the JSON content. Example 3 is an example of the change to the JSON content, in which the property There are (at least) two different NVD JSON schemas, with different purposes, that support ranges: https://csrc.nist.gov/schema/nvd/feed/1.1/nvd_cve_feed_json_1.1.schema and https://csrc.nist.gov/schema/cpematch/feed/1.0/nvd_cpematch_feed_json_1.0.schema - they both have these properties related to ranges: NVD JSON data can be used in use cases where explicitly mentioning a version in a cpe23Uri field implies higher confidence that that is an affected version (relative to the version number falling inside of a range). |
Thank you! That little bit of human-targeted prose in the first two examples was completely lost on me 🤦
Yes, the point I was trying to make earlier was that there's equivalent functionality today with CVE 5.x:
|
An option in the current schema is to use CPE inside of {
"cpes": [
"cpe:2.3:a:adminerevo:adminerevo:4.8.2:*:*:*:*:*:*:*",
"cpe:2.3:a:adminerevo:adminerevo:4.8.3:*:*:*:*:*:*:*"
],
"defaultStatus": "unknown",
"product": "AdminerEvo",
"programFiles": [
"plugins/file-upload.php"
],
"repo": "https://github.com/adminerevo/adminerevo",
"vendor": "AdminerEvo",
"versions": [
{
"lessThan": "4.8.3",
"status": "affected",
"version": "4.8.2",
"versionType": "custom"
},
{
"lessThan": "cpe:2.3:a:adminerevo:adminerevo:4.8.3:*:*:*:*:*:*:*",
"status": "affected",
"version": "cpe:2.3:a:adminerevo:adminerevo:0:*:*:*:*:*:*:*",
"versionType": "cpe"
}
]
} This still leaves |
I'm not in favor of including them in the affected versions like this as sites and tools currently render that content for humans - and CPE is very anti-human, IMHO. A lot of consumers, including the CVE.org site, would have to deal with this if we encourage CNAs to use CPEs this way. It would really make for ugly rendering on sites and tools, or the site/tools would need to change to recognize CPEs and not render them as they do other version types. As on the QWG call yesterday, if we don't want to spend too many resources on it, I'm strongly in favor of adopting the existing NVD CPE Match syntax into our schema: https://nvd.nist.gov/general/News/CPE-Match-Feed-1-0-Release CPE Match Range Example:
With versionStart[Including|Excluding] and versionEnd[Including|Excluding], as shown by @andrewpollock above, this maps to the existing version syntax pretty directly. As offered on the call my Matt, the advantage to this is that basically every tool today that is written to consume CPE uses this syntax, as they're pulling it from NVD now. If we adopt this it will be simpler for them to use our feed as a source. This would also make it easier for NVD to be an ADP as they'd be able to provide their data as-is - and if NVD is going to stick around I'd really prefer to see them become an ADP and not a splinter feed as they are now. I believe this would cover the use cases discussed, including Microsoft and Red Hat as above. You can specific all affected CPEs (vulnerable true and just list CPEs), all unaffected CPEs (vulnerable fales and list CPEs), or a range (vulnerable true or false, CPE, and versionStart and/or versionEnd). I think that covers all of the bases and doesn't impact existing tools which work with or render the versions from the JSON. |
Taking @andrewpollock's point about premature solutioning, IMO this issue is meant to be a partial improvement but will not be able to address fundamental issues with CPE or global-scale software identification or changes to how CVE conveys status and "products." There's some desire for CPE. CVE supports CPE, but badly. I suggest this issue is limited in scope to fixing CVE support for CPE, and I'm in favor of implementing CPE applicability/match, along the lines of importing existing formats/schemas when possible (similar to CVSS). CPE applicability/match could be implemented in CVE as one of the ways to populate an Another choice would be a new optional element within |
I think we need to deprecate the existing We would add a new element - could be called 'cpe-match' or whatever we want - which would use the existing NVD format, as discussed above, translated into JSON. I don't think it would cause any issues with display as existing tools would not render the new element, and any tools that are updated to do something with the element would be able to implement correct support. But I wouldn't expect this field to be exposed to humans as it is really meant for machine readability. |
Citation needed. I posit that desire is based very much off of that being how things have been done to date. We have an opportunity to evolve past this if it's no longer fit for purpose. Exploring generating a CPE 2.3 string from other CVE |
As a CNA I want to be able to provide CPE in a meaningful way and not rely on others to calculate it for us. We're being pushed to include CPE to support it for SBOM, VEX, etc Either we fix the schema or CNAs will start using x_ elements to do it. I've considered it. |
Any redundant data is an opportunity to get it incorrect/inconsistent. CPEs either need to be made fit for purpose or they need to be replaced with something that is. There's plenty of arguments that they're not fit for purpose. |
Can you elaborate on what "meaningful" means here. And to whom? |
Circling back to this today, with fresh eyes and thinking, and after a brief chat with @oliverchang... https://cveproject.github.io/cve-schema/schema/docs/#oneOf_i0_containers_cna_affected_items_cpes defines the semantics as (emphasis added):
So, from #12 (comment) regarding CVE-2024-30040:
It's part of a range, the range defined in the So my interpretation of the intent here is that any number of CPE strings used in the |
Chiming in here as the OSV schema maintainer. I also think we should avoid just pulling in the NVD CPE Match syntax into the CVE schema. It would be very confusing given that CVE 5 already enables rich versioning encoding in the existing schema (https://github.com/CVEProject/cve-schema/blob/main/schema/docs/versions.md). If I'm following/summarising this thread correctly, it seems like there's a few main issues? 1. How
|
Taking a moment to read through everything... The first thing I think should be stated here is that there is a difference between CPE Names (typically referred to as CPEs by most) and CPE Match Criteria (the things included in Applicability statements). Applicability Statements are the bridge that connect CPE Names in the CPE Dictionary and CVE Records. To @oliverchang 's point, the current affected section covers MOST of the bases if the goal is to provide CPE Names. However, if the goal is to provide a more complex representation of applicability using CPE Match Criteria in an Applicability Statement, that can be done by leveraging the existing NVD schema. Fun Definitions: CPE Name - The enumerations of known hardware, applications or operating systems that exist within the Official CPE Dictionary for products of interest. CPE Names must have the Part, Vendor, Product and Version components populated at a minimum to be valid. Within the NVD dataset we provide a configurations section for each CVE record. CVE Record configurations contain CPE Match Criteria. CPE Match Criteria - These are super sets of CPE Names. Unlike CPE Names, Match Criteria do not require certain components be populated to be valid and come in two representations: CPE Match String - These look very similar to a CPE Name, but have less restrictions on which components must be populated and are intended to reference one or more CPE Names within the CPE Dictionary. CPE Match String Range - A quicker and more natural way to express a grouping of CPE Name versions. While similar to the CPE Match String, these contain a base string combined with boundaries for the version component. Simple example using parts of CVE-2023-25727: Applicability Statement containing a CPE Match String and a CPE Match String Range "configurations": [
{
"nodes": [
{
"operator": "OR",
"negate": false,
"cpeMatch": [
{
"vulnerable": true,
"criteria": "cpe:2.3:a:phpmyadmin:phpmyadmin:4.0.0:*:*:*:*:*:*:*",
"matchCriteriaId": "BCD4C26A-0823-4EAA-8052-6D6A269308E5"
},
{
"vulnerable": true,
"criteria": "cpe:2.3:a:phpmyadmin:phpmyadmin:*:*:*:*:*:*:*:*",
"versionStartIncluding": "5.0.0",
"versionEndExcluding": "5.2.1",
"matchCriteriaId": "BCD4C26A-0823-4EAA-8052-6D6A269308E4"
}
]
}
]
}
] The same represented in the affected section CVE 5.X, but using the {
"product": "phpmyadmin",
"vendor": "phpmyadmin",
"cpes": [
"cpe:2.3:a:phpmyadmin:phpmyadmin:5.0.0:-:*:*:*:*:*:*",
"cpe:2.3:a:phpmyadmin:phpmyadmin:5.0.0:alpha1:*:*:*:*:*:*",
"cpe:2.3:a:phpmyadmin:phpmyadmin:5.0.0:rc1:*:*:*:*:*:*",
"cpe:2.3:a:phpmyadmin:phpmyadmin:5.0.1:*:*:*:*:*:*:*",
"cpe:2.3:a:phpmyadmin:phpmyadmin:5.0.2:*:*:*:*:*:*:*",
"cpe:2.3:a:phpmyadmin:phpmyadmin:5.0.3:*:*:*:*:*:*:*",
"cpe:2.3:a:phpmyadmin:phpmyadmin:5.0.4:*:*:*:*:*:*:*",
"cpe:2.3:a:phpmyadmin:phpmyadmin:5.1.0:-:*:*:*:*:*:*",
"cpe:2.3:a:phpmyadmin:phpmyadmin:5.1.0:rc1:*:*:*:*:*:*",
"cpe:2.3:a:phpmyadmin:phpmyadmin:5.1.0:rc2:*:*:*:*:*:*",
"cpe:2.3:a:phpmyadmin:phpmyadmin:5.1.1:*:*:*:*:*:*:*",
"cpe:2.3:a:phpmyadmin:phpmyadmin:5.1.2:*:*:*:*:*:*:*",
"cpe:2.3:a:phpmyadmin:phpmyadmin:5.1.3:*:*:*:*:*:*:*",
"cpe:2.3:a:phpmyadmin:phpmyadmin:5.1.4:*:*:*:*:*:*:*",
"cpe:2.3:a:phpmyadmin:phpmyadmin:5.2.0:-:*:*:*:*:*:*",
"cpe:2.3:a:phpmyadmin:phpmyadmin:5.2.0:rc1:*:*:*:*:*:*",
],
"versions": [
{
"version": "5.0.0",
"lessThan": "5.2.1",
"status": "affected",
"versionType": "semver"
}
]
},
{
"product": "phpmyadmin",
"vendor": "phpmyadmin",
"cpes": [
"cpe:2.3:a:phpmyadmin:phpmyadmin:4.0.0:*:*:*:*:*:*:*",
],
"versions": [
{
"version": "4.0.0",
"status": "affected",
"versionType": "semver"
}
]
},
|
In reference to #12 (comment), discussed again during today's QWG meeting: An individual opinion: I like (even prefer) the idea of not bolting on/duplicating data (and schema), so I'm on board with modifications that make it possible to derive CPE from CVE data. Fact (I think): I don't see how this can work (at least as proposed in #12 (comment)). I believe the breaking point is that CPE
|
Thanks for the feedback @zmanion!
How are people using Is there a specific need to map |
Yes, today I haven't tried a more complicated Red Hat or Cisco or Microsoft CVE Record yet, but maybe this works if there are some additional constraints or guarantees on the data (to enforce what I called "mapping" above), for instance, within an
From one of @andrewpollock's slides:
|
The word "implies" is probably a dangerous assumption. Under the current schema, rules, guidance, and history, a CNA can put anything in So I think I've just restated proposed solution 1.3, what I was missing is the explicit constrained mapping of CPE vendor and product fields to I still may personally favor importing the NVD CPE match schema, but am going to look at converting CVE |
And just because they can, doesn't mean they should, and certainly doesn't mean a coherent and usable machine-readable (or human-interpretable) CVE record results. The CVE schema should continue to evolve to make it hard for CNAs to do the wrong thing and easy for them to do the right thing (see also slide 6) |
Closing this, appreciate all of the discussion and I don't think we have yet solved the bigger issues around better status and global software identification, but the CVE Board voted to implement CPE Match Criteria and Applicability statements (I believe it is both terms) in the CVE Record Format, which addresses this specific issue. |
The
affected
array can containcpes
, but these are not associated with a version, version range, or status.Consider this snippet of https://cveawg.mitre.org/api/cve/CVE-2024-0229:
If I'm interpreting this correctly, all tigervnc versions are affected, except those with version from 0:1.8.0-31.el7_9 to infinity ('*') are unaffected. IOW, fixed in 0:1.8.0-31.el7_9.
So what do the
cpes
mean? Are they covered bydefaultStatus": "affected"
? Thecpes
seem to be detached from versions and version ranges.This example is from Red Hat, who are very deliberate and careful in how they produce CVE JSON. My concern is not necessarily with Red Hat's choices on how to convey vulnerability status, but with the semantics of
cpes
in the CVE Record format. Associating a CPE identifier withversions
seems to make better sense.The text was updated successfully, but these errors were encountered: