-
Notifications
You must be signed in to change notification settings - Fork 599
Description
Description
There is an inconsistency in generating product version information between:
- ingesting NVD data into the database; and
- Performing queries on the database that look for exact versions (query ranges appear to be working).
Specifically, patch/update information is not used in the db, but is used when constructing queries for exact versions.
Openssh 8.5p1 is used below as a concrete example to explain the issue
Ingesting NVD data and populating the db
The CPE of cpe:2.3:a:openbsd:openssh:8.5:p1:*:*:*:*:*:* will be decoded by the decode_cpe23 function into
vendor = openbsd
product = openssh
version = 8.5
Note that the cpe update value is discarded.
CVEs associated with this CPE (eg. CVE-2024-6387) will be stored in the sqlite db against the version 8.5 and not 8.5p1.
For example:
| cve_number | vendor | product | version | versionStartIncluding | versionStartExcluding | versionEndIncluding | versionEndExcluding | data_source |
|---|---|---|---|---|---|---|---|---|
| CVE-2024-6387 | openbsd | openssh | * | 8.6 | 9.8 | NVD | ||
| CVE-2024-6387 | openbsd | openssh | 8.5 | NVD | ||||
| CVE-2024-6387 | openbsd | openssh | * | 4.4 | NVD | |||
| CVE-2024-6387 | openbsd | openssh | 4.4 | NVD |
Constructing the ProductInfo object and searching the db
The OpenSSH version header of OpenSSH_8.5p1 is parsed into
ProductInfo(vendor='openssh', product='openssh', version='8.5p1', location='NotFound', purl=None)
The query that should locate CVEs for exact versions is:
cve-bin-tool/cve_bin_tool/cve_scanner.py
Lines 144 to 154 in a3affea
| query = """ | |
| SELECT CVE_number FROM cve_range | |
| WHERE vendor=? AND product=? AND version=? | |
| """ | |
| # Removing * from vendors that are guessed by the package list parser | |
| vendor = product_info.vendor.replace("*", "") | |
| # Use our Version class to do version compares | |
| parsed_version = Version(product_info.version) | |
| self.cursor.execute(query, [vendor, product_info.product, str(parsed_version)]) |
Note that str(Version("8.5p1")) == "8.5p1"
Which results in the query that returns 0 rows when we actually expect 1 row.
SELECT CVE_number FROM cve_range
WHERE vendor='openbsd'
AND product='openssh'
AND version='8.5p1` Note that queries searching ranges work because all rows for a product are retrieved and the Version object is responsible for version comparisons and can deal with the patch/update component.
cve-bin-tool/cve_bin_tool/cve_scanner.py
Lines 158 to 170 in a3affea
| # Check for any ranges | |
| query = """ | |
| SELECT | |
| CVE_number, | |
| versionStartIncluding, | |
| versionStartExcluding, | |
| versionEndIncluding, | |
| versionEndExcluding | |
| FROM cve_range | |
| WHERE vendor=? AND product=? AND version=? | |
| """ | |
| self.cursor.execute(query, [vendor, product_info.product, "*"]) |
cve-bin-tool/cve_bin_tool/cve_scanner.py
Line 185 in a3affea
| and parsed_version >= Version(version_start_including) |
To reproduce
Steps to reproduce the behaviour:
- Download and install OpenSSH 8.5p1
- Scan
cve-bin-tool /path/to/sshd - Note CVE-2024-6387 is not reported in the output
- Confirm this version of OpenSSH is vulnerable https://nvd.nist.gov/vuln/detail/cve-2024-6387#config-div-32
Expected behaviour:
cve-bin-tool SHOULD report that OpenSSH 8.5p1 is vulnerable to CVE-2025-6387
Actual behaviour:
cve-bin-tool DOES NOT report that OpenSSH 8.5p1 is vulnerable to CVE-2025-6387
Version/platform info
Version of CVE-bin-tool:
$ cve-bin-tool --version
3.4
Installed from pypi
Operating system: Linux
$ uname -a
Linux foobar 6.12.67-1-lts #1 SMP PREEMPT_DYNAMIC Fri, 23 Jan 2026 12:42:41 +0000 x86_64 GNU/Linux
Python version:
$ python3 --version
Python 3.14.2
Anything else?
I should be able to create a PR but need guidance on what is actually considered the core issue to fix.
For example I can propose:
- Option 1: The patch/update versions be stored in the db, and query functions & SQL updated to account for this.
- Option 2: The
Versionobject should be able to return a patch/update free string for use when searching for exact queries ( eg.Version("8.5p1").patchless == "8.5"). - Option 3: Remove the SQL which searches for exact versions. Instead fetch all product rows and use the
Versionobject to select the exact matches (similar to the ranged query).
Or you may have another preferred option.
Cheers,
Tom