grype icon indicating copy to clipboard operation
grype copied to clipboard

False flagging

Open cpendery opened this issue 3 years ago • 4 comments

What happened: Grype is shadowing the Redis databases's vulnerabilities over the pypi redis package

What you expected to happen: No vulnerabilities should be reported since the package isn't vulnerable.

How to reproduce it (as minimally and precisely as possible):

File

{
    "components": [
        {
            "bom-ref": "pkg:pypi/[email protected]",
            "name": "redis",
            "purl": "pkg:pypi/[email protected]",
            "type": "library",
            "version": "2.10.6"
        }
    ],
    "bomFormat": "CycloneDX",
    "serialNumber": "urn:uuid:",
    "version": 1,
    "specVersion": "1.4"
}

Command

grype sbom:sbom.json --add-cpes-if-none

Output

cpendery@macbook dir % grype sbom:sbom.json --add-cpes-if-none                                                              
 ✔ Vulnerability DB        [no update available]
 ✔ Scanned image           [4 vulnerabilities]

NAME   INSTALLED  FIXED-IN  TYPE    VULNERABILITY   SEVERITY 
redis  2.10.6               python  CVE-2021-32626  High      
redis  2.10.6               python  CVE-2022-0543   Critical  
redis  2.10.6               python  CVE-2022-24735  High      
redis  2.10.6               python  CVE-2022-24736  Medium

Anything else we need to know?:

Environment:

  • Output of grype version: 40.0
  • OS (e.g: cat /etc/os-release or similar):
System Version: macOS 11.6 (20G165)
Kernel Version: Darwin 20.6.0
Model Name: MacBook Pro
Model Identifier: MacBookPro16,1
Processor Name: 6-Core Intel Core i7

cpendery avatar Jun 24 '22 16:06 cpendery

Nice catch @cpendery - I guess this is another case of the CPE being too losely formed since pypi/redis is distinct from redis/redis

cpe:2.3:a:redis:redis:*:*:*:*:*:*:*:* This is what I expect should be doing the matching.

Is there another CPE generated that's something like cpe:2.3:a:*:redis:*:*:*:*:*:*:*:*?

Can you add the CPE generated that's resulting in this bad match?

spiffcs avatar Jun 24 '22 16:06 spiffcs

@spiffcs here are the cpes. It looks like the last one is the one causing the bad match

     "cpe:2.3:a:python-redis:python-redis:2.10.6:*:*:*:*:*:*:*",
     "cpe:2.3:a:python-redis:python_redis:2.10.6:*:*:*:*:*:*:*",
     "cpe:2.3:a:python_redis:python-redis:2.10.6:*:*:*:*:*:*:*",
     "cpe:2.3:a:python_redis:python_redis:2.10.6:*:*:*:*:*:*:*",
     "cpe:2.3:a:python:python-redis:2.10.6:*:*:*:*:*:*:*",
     "cpe:2.3:a:python:python_redis:2.10.6:*:*:*:*:*:*:*",
     "cpe:2.3:a:python-redis:redis:2.10.6:*:*:*:*:*:*:*",
     "cpe:2.3:a:python_redis:redis:2.10.6:*:*:*:*:*:*:*",
     "cpe:2.3:a:redis:python-redis:2.10.6:*:*:*:*:*:*:*",
     "cpe:2.3:a:redis:python_redis:2.10.6:*:*:*:*:*:*:*",
     "cpe:2.3:a:python:redis:2.10.6:*:*:*:*:*:*:*",
     "cpe:2.3:a:redis:redis:2.10.6:*:*:*:*:*:*:*"

cpendery avatar Jun 24 '22 16:06 cpendery

Based on my analysis of the database, there will never be a case where the vendor and the product have the same name. In addition, viewing the cpe database from NVD shows that the same is true for all cpes in the database. As a result, I think we can safely remove the case where the vendor and product name are identical, which will resolve this false positive. I'll make a PR and link this issue in Syft

DB script

import sqlite3
import re
import json

con = sqlite3.connect("vulnerability.db")
cur = con.cursor()
cur.execute("SELECT v.id, v.cpes FROM vulnerability as v;")
results = cur.fetchall()
cur.close()

match_regex = re.compile(rf".*:([A-z_]+):([A-z_]+)")


for result_id, cpes_str in results:
    if cpes_str == "null":
        continuefrom bs4 import BeautifulSoup
soup = BeautifulSoup(html_doc, 'html.parser')

    cpes = json.loads(cpes_str)
    for cpe in cpes:
        matches = match_regex.findall(cpe)
        if len(matches) == 2 and matches[0] == matches[1]:
            print(cpe, result_id)

Dictionary script

import xml.etree.ElementTree as ET
import re

match_regex = re.compile(rf".*:([A-z_]+):([A-z_]+)")

with open("official-cpe-dictionary_v2.3.xml", "r", encoding="utf-8") as input_file:
    tree = ET.parse(input_file)
    root = tree.getroot()
    for child in root:
        if "cpe-item" in child.tag:
            for item in child.items():
                if len(item) == 2 and item[0] == "name":
                    matches = match_regex.findall(item[1])
                    if len(matches) == 2 and matches[0] == matches[1]:
                        print(item[1])

cpendery avatar Jun 25 '22 13:06 cpendery

As @westonsteimel pointed out, the cpe dictionary isn't cumulative, so I missed cases where this does in fact occur, closed the pr as it isn't a fix for the issue and worsens overall accuracy and will look for other potential fixes

cpendery avatar Jun 27 '22 14:06 cpendery