Skip to content

Conversation

willmurphyscode
Copy link
Contributor

This makes version numbers that mix alphabetic and numeric components, like 4.2.8p14 and 4.2.8p2 compare correctly, e.g. 4.2.8p2 < 4.2.8p14 because 2 < 14. Previously, they would compare lexicogrpahically, occasionally resulting in a false positive or false negative.

A motivating real case:

# latest
$ grype -q "cpe:2.3:a:*:ntp:4.2.8p15:*:*:*:*:*:*:*" | rg -e NAME -e CVE-2016-7434
NAME  INSTALLED  FIXED IN          VULNERABILITY   SEVERITY  EPSS          RISK  
ntp   4.2.8p15   *4.2.8p9, 4.3.94  CVE-2016-7434   High      61.2% (98th)  41.0 
# this branch 
$ go run ./cmd/grype -q "cpe:2.3:a:*:ntp:4.2.8p15:*:*:*:*:*:*:*" | rg -e NAME -e CVE-2016-7434
NAME  INSTALLED  VULNERABILITY   SEVERITY  EPSS         RISK  
# where database has
$ grype db search --provider nvd --vuln CVE-2016-7434
VULNERABILITY  PACKAGE                                 NAMESPACE  VERSION CONSTRAINT                            
CVE-2016-7434  cpe:2.3:a:hpe:hpux-ntp:*:*:*:*:*:*:*:*  nvd:cpe    >= b.11.31, < c.4.2.8.2.0                     
CVE-2016-7434  cpe:2.3:a:ntp:ntp:*:*:*:*:*:*:*:*       nvd:cpe    >= 4.2.7p22, < 4.2.8p9 || >= 4.3.0, < 4.3.94

@willmurphyscode willmurphyscode moved this to In Review in OSS Aug 1, 2025
@willmurphyscode willmurphyscode self-assigned this Aug 1, 2025
@ayham291
Copy link

ayham291 commented Aug 1, 2025

Grype has trouble with NTP and its CPE. The official documentation on how to complete your CPEs states that it should look like this:

      "cpe" : "cpe:2.3:a:ntp:ntp:4.2.8:p18:*:*:*:*:*:*",

Where the p18 is after the version in the update field cpe:<cpe_version>:<part>:<vendor>:<product>:<version>:<update>:..... Maybe the fix would also consider this!

When I move the p18 to the version like 4.2.8p18, it works fine, but it is not how it is supposed to be!

@willmurphyscode
Copy link
Contributor Author

Hi @ayham291 thanks for the input!

Do you have a specific example where grype is having trouble with the CPE you mention?

❯ grype 'cpe:2.3:a:ntp:ntp:4.2.8:p18:*:*:*:*:*:*' | rg -e NAME -e CVE-2016-7434
 ✔ Scanned for vulnerabilities     [0 vulnerability matches]
   ├── by severity: 2 critical, 23 high, 26 medium, 1 low, 0 negligible
   └── by status:   32 fixed, 20 not-fixed, 0 ignored
NAME  INSTALLED  FIXED IN          VULNERABILITY   SEVERITY  EPSS          RISK
ntp   4.2.8      *4.2.8p9, 4.3.94  CVE-2016-7434   High      61.2% (98th)  41.0

seems to be working for me (and that's a released build of grype, not including this change).

@ayham291
Copy link

ayham291 commented Aug 4, 2025

Hey @willmurphyscode thanks for your fast reply

If you run the command without rg you will get many false positves because grype does not handle the "patch version" correctly in the CPE.

❯ grype 'cpe:2.3:a:ntp:ntp:4.2.8:p18:*:*:*:*:*:*' | rg -e NAME -e CVE-2016-7434
 ✔ Scanned for vulnerabilities     [0 vulnerability matches]
   ├── by severity: 2 critical, 23 high, 26 medium, 1 low, 0 negligible
   └── by status:   32 fixed, 20 not-fixed, 0 ignored
NAME  INSTALLED  FIXED IN          VULNERABILITY   SEVERITY  EPSS          RISK
ntp   4.2.8      *4.2.8p9, 4.3.94  CVE-2016-7434   High      61.2% (98th)  41.0

I opened the following PR #2845 about the issue.

For this CPE: cpe:2.3:a:ntp:ntp:4.2.8:p18:*:*:*:*:*:* I get the following 52 CVEs of which 50 are false positives. I have grype 0.97.1

ayham291@machine:~/$ grype sbom:./bom.json | grep ntp
 ✔ Vulnerability DB                [no update available]
 ✔ Scanned for vulnerabilities     [97 vulnerability matches]
   ├── by severity: 8 critical, 45 high, 39 medium, 5 low, 0 negligible
   └── by status:   53 fixed, 44 not-fixed, 0 ignored
ntp                                            4.2.8p18                                  *4.2.8p9, 4.3.94  UnknownPackage  CVE-2016-7434     High      61.2% (98th)   41.0
ntp                                            4.2.8p18                                  4.2.8, *4.3.77    UnknownPackage  CVE-2015-7704     High      57.0% (98th)   39.2
ntp                                            4.2.8p18                                  4.2.8, *4.3.94    UnknownPackage  CVE-2016-7426     High      47.2% (97th)   31.6
ntp                                            4.2.8p18                                  4.2.8, *4.3.77    UnknownPackage  CVE-2015-7855     Medium    48.4% (97th)   24.8
ntp                                            4.2.8p18                                                    UnknownPackage  CVE-2015-7978     High      33.4% (96th)   23.0
ntp                                            4.2.8p18                                  4.2.8, *4.3.77    UnknownPackage  CVE-2015-7705     Critical  25.7% (96th)   22.7
ntp                                            4.2.8p18                                                    UnknownPackage  CVE-2015-7979     High      22.5% (95th)   15.4
ntp                                            4.2.8p18                                                    UnknownPackage  CVE-2016-7433     Medium    28.3% (96th)   14.4
ntp                                            4.2.8p18                                  4.2.8, *4.3.93    UnknownPackage  CVE-2016-4953     High      19.2% (95th)   13.2
ntp                                            4.2.8p18                                                    UnknownPackage  CVE-2016-2516     Medium    23.4% (95th)   13.1
ntp                                            4.2.8p18                                                    UnknownPackage  CVE-2015-5300     High      17.8% (94th)   12.2
ntp                                            4.2.8p18                                                    UnknownPackage  CVE-2015-8140     Medium    23.5% (95th)   12.1
ntp                                            4.2.8p18                                  4.2.8, *4.3.77    UnknownPackage  CVE-2015-7853     Critical  12.8% (93rd)   11.3
ntp                                            4.2.8p18                                                    UnknownPackage  CVE-2016-9311     Medium    19.4% (95th)   11.2
ntp                                            4.2.8p18                                                    UnknownPackage  CVE-2016-7429     Low       28.5% (96th)   10.0
ntp                                            4.2.8p18                                                    UnknownPackage  CVE-2015-8139     Medium    17.9% (94th)   9.1
ntp                                            4.2.8p18                                                    UnknownPackage  CVE-2015-8158     Medium    17.9% (94th)   9.1
ntp                                            4.2.8p18                                  4.2.8             UnknownPackage  CVE-2014-9750     Medium    11.5% (93rd)   6.2
ntp                                            4.2.8p18                                  4.2.8             UnknownPackage  CVE-2018-7185     High      8.8% (92nd)    6.1
ntp                                            4.2.8p18                                  4.2.8             UnknownPackage  CVE-2019-8936     High      8.7% (92nd)    6.0
ntp                                            4.2.8p18                                  4.3.90            UnknownPackage  CVE-2015-7977     Medium    11.6% (93rd)   5.9
ntp                                            4.2.8p18                                  4.2.8             UnknownPackage  CVE-2014-9751     Medium    9.7% (92nd)    5.7
ntp                                            4.2.8p18                                  4.2.8, *4.3.93    UnknownPackage  CVE-2016-4954     High      8.0% (91st)    5.5
ntp                                            4.2.8p18                                                    UnknownPackage  CVE-2016-9310     Medium    8.7% (92nd)    5.0
ntp                                            4.2.8p18                                  4.2.8, *4.3.77    UnknownPackage  CVE-2015-7701     High      6.3% (90th)    4.3
ntp                                            4.2.8p18                                  4.2.8, *4.3.90    UnknownPackage  CVE-2015-7973     Medium    7.6% (91st)    4.2
ntp                                            4.2.8p18                                  4.2.8, *4.3.77    UnknownPackage  CVE-2015-7691     High      5.7% (90th)    3.9
ntp                                            4.2.8p18                                                    UnknownPackage  CVE-2016-9312     High      5.7% (90th)    3.9
ntp                                            4.2.8p18                                  4.2.8, *4.3.94    UnknownPackage  CVE-2017-6458     High      4.9% (89th)    3.7
ntp                                            4.2.8p18                                                    UnknownPackage  CVE-2016-2519     Medium    7.1% (91st)    3.7
ntp                                            4.2.8p18                                  4.2.8, *4.3.90    UnknownPackage  CVE-2015-7974     High      5.1% (89th)    3.4
ntp                                            4.2.8p18                                  4.2.8, *4.3.77    UnknownPackage  CVE-2015-7849     High      4.4% (88th)    3.3
ntp                                            4.2.8p18                                                    UnknownPackage  CVE-2015-8138     Medium    6.1% (90th)    3.1
ntp                                            4.2.8p18                                  4.2.8, *4.3.77    UnknownPackage  CVE-2015-7692     High      4.2% (88th)    2.9
ntp                                            4.2.8p18                                  4.2.8, *4.3.77    UnknownPackage  CVE-2015-7854     High      3.6% (87th)    2.7
ntp                                            4.2.8p18                                  4.2.8, *4.3.93    UnknownPackage  CVE-2016-4955     Medium    4.7% (88th)    2.4
ntp                                            4.2.8p18                                  4.2.8, *4.3.77    UnknownPackage  CVE-2015-7703     High      3.2% (86th)    2.1
ntp                                            4.2.8p18                                                    UnknownPackage  CVE-2016-2517     Medium    3.8% (87th)    1.9
ntp                                            4.2.8p18                                                    UnknownPackage  CVE-2015-7976     Medium    4.2% (88th)    1.9
ntp                                            4.2.8p18                                  4.2.8, *4.3.77    UnknownPackage  CVE-2015-7852     Medium    3.2% (86th)    1.6
ntp                                            4.2.8p18                                  4.2.8, *4.3.77    UnknownPackage  CVE-2015-7850     Medium    2.6% (85th)    1.3
ntp                                            4.2.8p18                                                    UnknownPackage  CVE-2019-11331    High      1.4% (79th)    1.0
ntp                                            4.2.8p18                                  4.2.8, *4.3.93    UnknownPackage  CVE-2016-4956     Medium    2.0% (83rd)    1.0
ntp                                            4.2.8p18                                                    UnknownPackage  CVE-2015-5146     Medium    1.9% (82nd)    0.9
ntp                                            4.2.8p18                                                    UnknownPackage  CVE-2016-1547     Medium    1.3% (78th)    0.6
ntp                                            4.2.8p18                                  4.2.8, *4.3.92    UnknownPackage  CVE-2018-7170     Medium    1.3% (78th)    0.6
ntp                                            4.2.8p18                                  4.2.8, *4.3.77    UnknownPackage  CVE-2015-7848     High      0.9% (74th)    0.6
ntp                                            4.2.8p18                                  4.2.8, *4.3.77    UnknownPackage  CVE-2015-7702     Medium    1.0% (75th)    0.5
ntp                                            4.2.8p18                                  4.3.100           UnknownPackage  CVE-2020-11868    High      0.6% (68th)    0.4
ntp                                            4.2.8p18                                  4.2.8, *4.3.92    UnknownPackage  CVE-2016-2518     Medium    0.8% (72nd)    0.4
ntp                                            4.2.8p18                                                    UnknownPackage  CVE-2015-7975     Medium    0.6% (69th)    0.3
ntp                                            4.2.8p18                                  4.2.8, *4.3.100   UnknownPackage  CVE-2020-13817    High      0.4% (58th)    0.3
ayham291@machine:~/repos/grype$ ./grype-with-fix sbom:./bom.json | grep ntp
 ✔ Scanned for vulnerabilities     [45 vulnerability matches]
   ├── by severity: 6 critical, 24 high, 11 medium, 4 low, 0 negligible
   └── by status:   21 fixed, 24 not-fixed, 0 ignored
ntp                                            4.2.8p18                                  *4.2.8p9, 4.3.94  UnknownPackage  CVE-2016-7434     High      61.2% (98th)   41.0
ntp                                            4.2.8p18                                                    UnknownPackage  CVE-2019-11331    High      1.4% (79th)    1.0

// Test case for fuzzy version comparison bug with patch numbers
// This should pass: 4.2.8p9 < 4.2.8p15 (p9 comes before p15 numerically)
// But currently fails due to lexicographic fallback where "p9" > "p15" (string comparison)
{"4.2.8p9", "4.2.8p15", -1},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did I read in the discussion that openssl uses the fuzzy matcher; do you happen to know if that's accurate? If so, are any of these version strings testing openssl versions? if not, that might be the only suggestion I have for improving the coverage here to give me a warmer fuzzy, for example I see openssl 1.1.1p

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add a test case that 1.1.1w is > 1.1.1v and > than 1.1.1.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kzantow I've added test cases for some old openssl versions.

This makes version numbers that mix alphabetic and numeric components,
like 4.2.8p14 and 4.2.8p2 compare correctly, e.g. 4.2.8p2 < 4.2.8p14
because 2 < 14. Previously, they would compare lexicogrpahically,
occasionally resulting in a false positive or false negative.

Add unit tests for old openssl patch versions to ensure they are not
broken by this change.

Signed-off-by: Will Murphy <[email protected]>
@willmurphyscode willmurphyscode force-pushed the fuzzy-comp-with-patch-number branch from 9d10e60 to f3ca0d1 Compare August 28, 2025 11:07
@willmurphyscode
Copy link
Contributor Author

Hi @ayham291 thanks for the PR! I think probably both this and your change are necessary, but can be merged independently. We will definitely take a look at #2845.

@willmurphyscode willmurphyscode added the bug Something isn't working label Aug 28, 2025
@willmurphyscode willmurphyscode merged commit a7de3ce into main Aug 28, 2025
12 checks passed
@willmurphyscode willmurphyscode deleted the fuzzy-comp-with-patch-number branch August 28, 2025 13:28
@github-project-automation github-project-automation bot moved this from In Review to Done in OSS Aug 28, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

4 participants