anchore / grype

A vulnerability scanner for container images and filesystems
Apache License 2.0
8.86k stars 574 forks source link

Merge indirect matches with direct matches #2241

Closed wagoodman closed 2 weeks ago

wagoodman commented 2 weeks ago

Today if a vulnerability is matched for an artifact both directly and indirectly (using a source/origin package instead of the downstream/original package) then we raise up both matches separately:

$ grype 'pkg:rpm/ol/perl-Errno@1.28-417.el8_3?arch=x86_64&epoch=0&upstream=perl-5.26.3-417.el8_3.src.rpm&distro=ol-8.3' -q -o json | jq '.matches[] | select(.artifact.name == "perl-Errno" and .vulnerability.id == "ELSA-2021-1678") | .matchDetails'
[
  {
    "type": "exact-direct-match",
    "matcher": "rpm-matcher",
    "searchedBy": {
      "distro": {
        "type": "oraclelinux",
        "version": "8.3"
      },
      "namespace": "oracle:distro:oraclelinux:8",
      "package": {
        "name": "perl-Errno",
        "version": "0:1.28-417.el8_3"
      }
    },
    "found": {
      "versionConstraint": "< 0:1.28-419.el8 (rpm)",
      "vulnerabilityID": "ELSA-2021-1678"
    }
  }
]
[
  {
    "type": "exact-indirect-match",
    "matcher": "rpm-matcher",
    "searchedBy": {
      "distro": {
        "type": "oraclelinux",
        "version": "8.3"
      },
      "namespace": "oracle:distro:oraclelinux:8",
      "package": {
        "name": "perl",
        "version": "5.26.3-417.el8_3"
      }
    },
    "found": {
      "versionConstraint": "< 4:5.26.3-419.el8 (rpm)",
      "vulnerabilityID": "ELSA-2021-1678"
    }
  }
]

This PR changes this behavior such that any direct match for a package-vuln pairing and similar indirect match for that same package-vuln are merged into a single match, preserving the indirect .matchDetails on the direct match (running the same command):

[
  {
    "type": "exact-direct-match",
    "matcher": "rpm-matcher",
    "searchedBy": {
      "distro": {
        "type": "oraclelinux",
        "version": "8.3"
      },
      "namespace": "oracle:distro:oraclelinux:8",
      "package": {
        "name": "perl-Errno",
        "version": "0:1.28-417.el8_3"
      }
    },
    "found": {
      "versionConstraint": "< 0:1.28-419.el8 (rpm)",
      "vulnerabilityID": "ELSA-2021-1678"
    }
  },
  {
    "type": "exact-indirect-match",
    "matcher": "rpm-matcher",
    "searchedBy": {
      "distro": {
        "type": "oraclelinux",
        "version": "8.3"
      },
      "namespace": "oracle:distro:oraclelinux:8",
      "package": {
        "name": "perl",
        "version": "5.26.3-417.el8_3"
      }
    },
    "found": {
      "versionConstraint": "< 4:5.26.3-419.el8 (rpm)",
      "vulnerabilityID": "ELSA-2021-1678"
    }
  }
]

(note the same match details but in a single array entry instead of two)

Along the way additional tests were added to existing code that was previously untested (and some code, such as sorting, was either tweaked or refactored for either additional functionality or to satisfy linting rules).

Fixes #1931