def test_from_with_nvd(self, test_input):
        match = VulnerabilityMatch(
            artifact=Artifact(
                name="blah",
                location="/usr/local/java/blah",
                pkg_type="java",
                version="1.2.3maven",
            ),
            vulnerability=Vulnerability(
                feed="vulnerabilities",
                feed_group="whatever:hello",
                vulnerability_id="meh",
            ),
        )
        match.nvd = test_input
        identity_objects = VulnerabilityIdentity.from_match(match)

        assert identity_objects
        assert isinstance(identity_objects, list) and len(identity_objects) == len(
            test_input
        )
        for identity_object, input_nvd in zip(identity_objects, test_input):
            assert identity_object.vuln_id == input_nvd.vulnerability_id
            assert identity_object.pkg_name == match.artifact.name
            assert identity_object.pkg_type == match.artifact.pkg_type
            assert identity_object.pkg_version == match.artifact.version
            assert identity_object.pkg_path == match.artifact.location
    def test_transfer_vulnerability_timestamps_fix_observed_at(
        self, test_source, test_destination, expected
    ):
        random = VulnerabilityMatch(
            artifact=Artifact(
                name="blah",
                location="/usr/local/java/blah",
                pkg_type="java",
                version="1.2.3maven",
            ),
            vulnerability=Vulnerability(
                feed="vulnerabilities",
                feed_group="whatever:hello",
                vulnerability_id="meh",
            ),
            match=Match(detected_at=datetime.datetime.utcnow()),
        )

        source = copy.deepcopy(random)
        source.fix = test_source

        destination = copy.deepcopy(random)
        destination.fix = test_destination

        results = transfer_vulnerability_timestamps(
            source=[source], destination=[destination]
        )

        assert results and len(results) == 1
        assert results[0].fix.observed_at == expected
    def test_transfer_vulnerability_timestamps_single(
        self, test_source, test_destination
    ):
        random = VulnerabilityMatch(
            artifact=Artifact(
                name="blah",
                location="/usr/local/java/blah",
                pkg_type="java",
                version="1.2.3maven",
            ),
            vulnerability=Vulnerability(
                feed="vulnerabilities",
                feed_group="whatever:hello",
                vulnerability_id="meh",
            ),
            fix=FixedArtifact(),
        )

        source = copy.deepcopy(random)
        source.match = Match(detected_at=test_source)

        destination = copy.deepcopy(random)
        destination.match = Match(detected_at=test_destination)

        results = transfer_vulnerability_timestamps(
            source=[source], destination=[destination]
        )

        assert results and len(results) == 1
        assert results[0].match.detected_at == test_source
    def test_from(self):
        match = VulnerabilityMatch(
            artifact=Artifact(
                name="blah",
                location="/usr/local/java/blah",
                pkg_type="java",
                version="1.2.3maven",
            ),
            vulnerability=Vulnerability(
                feed="vulnerabilities",
                feed_group="whatever:hello",
                vulnerability_id="meh",
            ),
            nvd=[NVDReference(vulnerability_id="CVE-abc")],
        )
        rank_strategy = FeedGroupRank()
        ranked_match = RankedVulnerabilityMatch.from_match(match, FeedGroupRank())

        assert ranked_match
        assert ranked_match.vuln_id == match.vulnerability.vulnerability_id
        assert ranked_match.vuln_namespace == match.vulnerability.feed_group
        assert ranked_match.pkg_name == match.artifact.name
        assert ranked_match.pkg_type == match.artifact.pkg_type
        assert ranked_match.pkg_version == match.artifact.version
        assert ranked_match.pkg_path == match.artifact.location
        assert ranked_match.rank == rank_strategy.__default__
Example #5
0
    def to_engine(
        self,
        result: Dict,
        package_mapper: PackageMapper,
        now: datetime.datetime,
    ):
        artifact_dict = result.get("artifact")
        vuln_dict = result.get("vulnerability")

        # parse cvss fields
        cvss_objs = VulnerabilityMapper._try_parse_cvss(
            vuln_dict.get("cvss", []))

        # parse fix details
        fix_dict = vuln_dict.get("fix")
        fix_obj = FixedArtifact(versions=[],
                                wont_fix=False,
                                observed_at=None,
                                advisories=[])
        if fix_dict:
            fix_obj.versions = fix_dict.get("versions", [])
            fix_obj.wont_fix = (fix_dict.get("state").lower() == "wont-fix"
                                )  # TODO format check with toolbox
            fix_obj.observed_at = now if fix_obj.versions else None
            fix_obj.advisories = VulnerabilityMapper._try_parse_advisories(
                fix_dict.get("advisories", []))

        # parse nvd references
        nvd_objs = VulnerabilityMapper._try_parse_related_vulnerabilities(
            result.get("relatedVulnerabilities", []))

        # parse package path
        pkg_path = (artifact_dict.get("locations")[0].get("path")
                    if artifact_dict.get("locations") else "NA")

        vuln_match = VulnerabilityMatch(
            vulnerability=Vulnerability(
                vulnerability_id=vuln_dict.get("id"),
                description=vuln_dict.get("description"),
                severity=vuln_dict.get("severity"),
                link=vuln_dict.get("dataSource"),
                feed="grypedb",
                feed_group=vuln_dict.get("namespace"),
                cvss=cvss_objs,
            ),
            artifact=Artifact(
                name=artifact_dict.get("name"),
                version=artifact_dict.get("version"),
                pkg_type=package_mapper.engine_type,
                location=pkg_path,
                cpe=None,  # vestige of the old system
                cpes=self._try_parse_matched_cpes(result),
            ),
            fix=fix_obj,
            match=Match(detected_at=now),
            nvd=nvd_objs,
        )

        return vuln_match
    def test_hash_empty_match(self, count):
        record = RankedVulnerabilityMatch(
            vuln_id="meh",
            vuln_namespace="trusty:chameleon",
            pkg_name="blah",
            pkg_version="1.2.3maven",
            pkg_type="java",
            pkg_path="blah",
            rank=100,
            match_obj=VulnerabilityMatch(),
        )

        test_input = [record for x in range(count)]
        result = set(test_input)
        assert result and len(result) == 1
Example #7
0
    def test_filter_vulnerability_matches_namespace(self, test_input,
                                                    test_filter,
                                                    expected_output):
        vuln_match = VulnerabilityMatch(
            vulnerability=Vulnerability(vulnerability_id="CVE-xyz",
                                        feed_group=test_input),
            artifact=Artifact(name="foo"),
        )

        results = GrypeProvider._filter_vulnerability_matches(
            matches=[vuln_match],
            vulnerability_id="CVE-xyz",
            severity_filter=None,
            namespace_filter=test_filter,
            affected_package_filter=None,
            vendor_only=None,
        )

        assert results == expected_output
Example #8
0
    def test_filter_vulnerability_matches_no_optional_filters(
            self, test_input, expected_output):
        vuln_match = VulnerabilityMatch(
            vulnerability=test_input,
            artifact=Artifact(
                name="foo",
                version="0.0",
                pkg_type="bar",
                location="/usr/local/lib",
            ),
        )

        results = GrypeProvider._filter_vulnerability_matches(
            matches=[vuln_match],
            vulnerability_id="CVE-xyz",
            severity_filter=None,
            namespace_filter=None,
            affected_package_filter=None,
            vendor_only=None,
        )

        assert results == expected_output
    def test_execute_absolute_duplicates(self, count):
        a = VulnerabilityMatch(
            artifact=Artifact(
                name="blah",
                location="/usr/local/java/blah",
                pkg_type="java",
                version="1.2.3maven",
            ),
            vulnerability=Vulnerability(
                feed="vulnerabilities",
                feed_group="whatever:hello",
                vulnerability_id="meh",
            ),
            nvd=[NVDReference(vulnerability_id="CVE-2019-12904")],
        )

        input_matches = [a for x in range(count)]

        results = ImageVulnerabilitiesDeduplicator(FeedGroupRank()).execute(
            input_matches
        )
        assert len(results) == 1
Example #10
0
 [
     VulnerabilityMatch.from_json({
         "artifact": {
             "cpe": None,
             "cpes": [],
             "location": "/usr/lib/python3.8/site-packages/aiohttp",
             "name": "aiohttp",
             "pkg_type": "python",
             "version": "3.7.3",
         },
         "fix": {
             "advisories": [],
             "observed_at": "2021-03-31T17:30:49Z",
             "versions": ["3.7.4"],
             "wont_fix": False,
         },
         "match": {
             "detected_at": "2021-06-07T20:20:47Z"
         },
         "nvd": [],
         "vulnerability": {
             "cvss": [],
             "description": None,
             "feed": "vulnerabilities",
             "feed_group": "github:python",
             "link":
             "https://github.com/advisories/GHSA-v6wp-4m6f-gcjg",
             "severity": "Low",
             "vulnerability_id": "GHSA-v6wp-4m6f-gcjg",
         },
     })
 ],
Example #11
0
class TestGrypeProvider:
    @pytest.mark.parametrize(
        "test_input",
        [
            pytest.param(
                [VulnerabilityMatch(fix=FixedArtifact(wont_fix="true"))],
                id="str",
            ),
            pytest.param(
                [VulnerabilityMatch(fix=FixedArtifact(wont_fix="  "))],
                id="whitespace",
            ),
            pytest.param(
                [VulnerabilityMatch(fix=FixedArtifact(wont_fix=""))],
                id="blank",
            ),
            pytest.param(
                [VulnerabilityMatch(fix=FixedArtifact(wont_fix=False))],
                id="boolean_false",
            ),
            pytest.param(
                [VulnerabilityMatch(fix=None)],
                id="fix_none",
            ),
        ],
    )
    def test_exclude_wont_fix_false(self, test_input):
        assert len(GrypeProvider._exclude_wont_fix(test_input)) == 1

    @pytest.mark.parametrize(
        "test_input",
        [
            pytest.param(
                [VulnerabilityMatch(fix=FixedArtifact(wont_fix=True))],
                id="boolean_true",
            ),
        ],
    )
    def test_exclude_wont_fix_true(self, test_input):
        assert len(GrypeProvider._exclude_wont_fix(test_input)) == 0

    @pytest.mark.parametrize(
        "test_input, expected_output",
        [
            pytest.param(
                Vulnerability(vulnerability_id="CVE-xyz"),
                [{
                    "name": "foo",
                    "version": "0.0",
                    "type": "bar",
                    "namespace": None,
                    "severity": None,
                }],
                id="match-1",
            ),
            pytest.param(
                Vulnerability(vulnerability_id="CVE-xyz",
                              severity="Critical",
                              feed_group="meh"),
                [{
                    "name": "foo",
                    "version": "0.0",
                    "type": "bar",
                    "namespace": "meh",
                    "severity": "Critical",
                }],
                id="match-2",
            ),
            pytest.param(
                Vulnerability(vulnerability_id="CVE-pqr",
                              severity="Critical",
                              feed_group="meh"),
                [],
                id="no-match",
            ),
        ],
    )
    def test_filter_vulnerability_matches_no_optional_filters(
            self, test_input, expected_output):
        vuln_match = VulnerabilityMatch(
            vulnerability=test_input,
            artifact=Artifact(
                name="foo",
                version="0.0",
                pkg_type="bar",
                location="/usr/local/lib",
            ),
        )

        results = GrypeProvider._filter_vulnerability_matches(
            matches=[vuln_match],
            vulnerability_id="CVE-xyz",
            severity_filter=None,
            namespace_filter=None,
            affected_package_filter=None,
            vendor_only=None,
        )

        assert results == expected_output

    @pytest.mark.parametrize(
        "test_input, test_filter, expected_output",
        [
            pytest.param(
                True,
                False,
                [{
                    "name": "foo",
                    "version": None,
                    "type": None,
                    "namespace": None,
                    "severity": None,
                }],
                id="wontfix-true_vendoronly_false",
            ),
            pytest.param(
                False,
                False,
                [{
                    "name": "foo",
                    "version": None,
                    "type": None,
                    "namespace": None,
                    "severity": None,
                }],
                id="wontfix-false_vendoronly_false",
            ),
            pytest.param(
                False,
                True,
                [{
                    "name": "foo",
                    "version": None,
                    "type": None,
                    "namespace": None,
                    "severity": None,
                }],
                id="wontfix-false_vendoronly_true",
            ),
            pytest.param(
                True,
                True,
                [],
                id="wontfix-true_vendoronly_true",
            ),
        ],
    )
    def test_filter_vulnerability_matches_vendor_only(self, test_input,
                                                      test_filter,
                                                      expected_output):
        vuln_match = VulnerabilityMatch(
            vulnerability=Vulnerability(vulnerability_id="CVE-xyz"),
            artifact=Artifact(name="foo"),
            fix=FixedArtifact(wont_fix=test_input),
        )

        results = GrypeProvider._filter_vulnerability_matches(
            matches=[vuln_match],
            vulnerability_id="CVE-xyz",
            severity_filter=None,
            namespace_filter=None,
            affected_package_filter=None,
            vendor_only=test_filter,
        )

        assert results == expected_output

    @pytest.mark.parametrize(
        "test_input, test_filter, expected_output",
        [
            pytest.param(
                "High",
                "Critical",
                [],
                id="no-match",
            ),
            pytest.param(
                "High",
                "High",
                [{
                    "name": "foo",
                    "version": None,
                    "type": None,
                    "namespace": None,
                    "severity": "High",
                }],
                id="match",
            ),
        ],
    )
    def test_filter_vulnerability_matches_severity(self, test_input,
                                                   test_filter,
                                                   expected_output):
        vuln_match = VulnerabilityMatch(
            vulnerability=Vulnerability(vulnerability_id="CVE-xyz",
                                        severity=test_input),
            artifact=Artifact(name="foo"),
        )

        results = GrypeProvider._filter_vulnerability_matches(
            matches=[vuln_match],
            vulnerability_id="CVE-xyz",
            severity_filter=test_filter,
            namespace_filter=None,
            affected_package_filter=None,
            vendor_only=None,
        )

        assert results == expected_output

    @pytest.mark.parametrize(
        "test_input, test_filter, expected_output",
        [
            pytest.param(
                "foo",
                "bar",
                [],
                id="no-match",
            ),
            pytest.param(
                "meh",
                "meh",
                [{
                    "name": "foo",
                    "version": None,
                    "type": None,
                    "namespace": "meh",
                    "severity": None,
                }],
                id="match",
            ),
        ],
    )
    def test_filter_vulnerability_matches_namespace(self, test_input,
                                                    test_filter,
                                                    expected_output):
        vuln_match = VulnerabilityMatch(
            vulnerability=Vulnerability(vulnerability_id="CVE-xyz",
                                        feed_group=test_input),
            artifact=Artifact(name="foo"),
        )

        results = GrypeProvider._filter_vulnerability_matches(
            matches=[vuln_match],
            vulnerability_id="CVE-xyz",
            severity_filter=None,
            namespace_filter=test_filter,
            affected_package_filter=None,
            vendor_only=None,
        )

        assert results == expected_output
Example #12
0
    def test_transfer_vulnerability_timestamps_multiple(self):
        dest_ts = datetime.datetime.utcnow()
        src_ts = datetime.datetime.utcnow() - datetime.timedelta(days=1)

        destination = [
            VulnerabilityMatch(
                artifact=Artifact(
                    name="blah",
                    location="/usr/local/java/blah",
                    pkg_type="java",
                    version="1.2.3maven",
                ),
                vulnerability=Vulnerability(
                    feed="vulnerabilities",
                    feed_group="whatever:hello",
                    vulnerability_id="meh",
                ),
                match=Match(detected_at=dest_ts),
                fix=FixedArtifact(),
            ),
            VulnerabilityMatch(
                artifact=Artifact(
                    name="blah",
                    location="/usr/local/java/blah",
                    pkg_type="java",
                    version="1.2.3maven",
                ),
                vulnerability=Vulnerability(
                    feed="vulnerabilities",
                    feed_group="whatever:hello",
                    vulnerability_id="foo",
                ),
                match=Match(detected_at=dest_ts),
                fix=FixedArtifact(),
            ),
        ]

        source = [
            VulnerabilityMatch(
                artifact=Artifact(
                    name="blah",
                    location="/usr/local/java/blah",
                    pkg_type="java",
                    version="1.2.3maven",
                ),
                vulnerability=Vulnerability(
                    feed="vulnerabilities",
                    feed_group="whatever:hello",
                    vulnerability_id="meh",
                ),
                match=Match(detected_at=src_ts),
                fix=FixedArtifact(),
            )
        ]

        results = transfer_vulnerability_timestamps(
            source=source, destination=destination
        )

        assert results and len(results) == 2
        for result in results:
            if (
                result.vulnerability.vulnerability_id
                == source[0].vulnerability.vulnerability_id
            ):
                assert result.match.detected_at == src_ts
            else:
                assert result.match.detected_at == dest_ts
Example #13
0
class TestImageVulnerabilitiesDeduplicator:
    @pytest.mark.parametrize(
        "test_input, expected_index",
        [
            pytest.param(
                [
                    VulnerabilityMatch(
                        vulnerability=Vulnerability(
                            feed="vulnerabilities",
                            feed_group="nvdv2:cves",
                            vulnerability_id="CVE-2019-12904",
                        ),
                        nvd=[NVDReference(vulnerability_id="CVE-2019-12904")],
                    ),
                    VulnerabilityMatch(
                        vulnerability=Vulnerability(
                            feed="vulnerabilities",
                            feed_group="ubuntu:20.04",
                            vulnerability_id="CVE-2019-12904",
                        ),
                        nvd=[NVDReference(vulnerability_id="CVE-2019-12904")],
                    ),
                ],
                1,
                id="different-namespaces",
            ),
            pytest.param(
                [
                    VulnerabilityMatch(
                        vulnerability=Vulnerability(
                            feed="vulnerabilities",
                            feed_group="nvdv2:cves",
                            vulnerability_id="CVE-2019-12904",
                        ),
                        nvd=[NVDReference(vulnerability_id="CVE-2019-12904")],
                    ),
                    VulnerabilityMatch(
                        vulnerability=Vulnerability(
                            feed="vulnerabilities",
                            feed_group="github:java",
                            vulnerability_id="GHSA-foobar",
                        ),
                        nvd=[NVDReference(vulnerability_id="CVE-2019-12904")],
                    ),
                ],
                1,
                id="different-identifiers",
            ),
            pytest.param(
                [
                    VulnerabilityMatch(
                        vulnerability=Vulnerability(
                            feed="vulnerabilities",
                            feed_group="github:java",
                            vulnerability_id="GHSA-foobar",
                        ),
                        nvd=[NVDReference(vulnerability_id="CVE-2019-12904")],
                    ),
                    VulnerabilityMatch(
                        vulnerability=Vulnerability(
                            feed="vulnerabilities",
                            feed_group="ubuntu:20.04",
                            vulnerability_id="CVE-2019-12904",
                        ),
                        nvd=[NVDReference(vulnerability_id="CVE-2019-12904")],
                    ),
                ],
                1,
                id="non-nvd-namespaces",
            ),
            pytest.param(
                [
                    VulnerabilityMatch(
                        vulnerability=Vulnerability(
                            feed="vulnerabilities",
                            feed_group="nvdv2:cves",
                            vulnerability_id="CVE-2019-12904",
                        ),
                        nvd=[NVDReference(vulnerability_id="CVE-2019-12904")],
                    ),
                    VulnerabilityMatch(
                        vulnerability=Vulnerability(
                            feed="vulnerabilities",
                            feed_group="ubuntu:20.04",
                            vulnerability_id="CVE-2019-12904",
                        ),
                        nvd=[],
                    ),
                ],
                1,
                id="no-nvd-refs",
            ),
            pytest.param(
                [
                    VulnerabilityMatch(
                        vulnerability=Vulnerability(
                            feed="vulnerabilities",
                            feed_group="nvdv2:cves",
                            vulnerability_id="CVE-2019-12904",
                        ),
                        nvd=[NVDReference(vulnerability_id="CVE-2019-12345")],
                    ),
                    VulnerabilityMatch(
                        vulnerability=Vulnerability(
                            feed="vulnerabilities",
                            feed_group="nvdv2:cves",
                            vulnerability_id="CVE-2019-12904",
                        ),
                        nvd=[NVDReference(vulnerability_id="CVE-2019-12904")],
                    ),
                    VulnerabilityMatch(
                        vulnerability=Vulnerability(
                            feed="vulnerabilities",
                            feed_group="github:java",
                            vulnerability_id="GHSA-foobar",
                        ),
                        nvd=[
                            NVDReference(vulnerability_id="CVE-2019-12904"),
                            NVDReference(vulnerability_id="CVE-2019-12345"),
                        ],
                    ),
                ],
                2,
                id="multiple-nvd-refs",
            ),
        ],
    )
    def test_execute(self, test_input, expected_index):
        artifact = Artifact(
            name="blah",
            location="/usr/local/java/blah",
            pkg_type="java",
            version="1.2.3maven",
        )
        for item in test_input:
            item.artifact = artifact

        results = ImageVulnerabilitiesDeduplicator(FeedGroupRank()).execute(test_input)
        assert len(results) == 1

        actual = results[0].vulnerability
        expected = test_input[expected_index]
        assert actual.vulnerability_id == expected.vulnerability.vulnerability_id
        assert actual.feed_group == expected.vulnerability.feed_group

    @pytest.mark.parametrize("count", [1, 2, 3, 4, 5])
    def test_execute_absolute_duplicates(self, count):
        a = VulnerabilityMatch(
            artifact=Artifact(
                name="blah",
                location="/usr/local/java/blah",
                pkg_type="java",
                version="1.2.3maven",
            ),
            vulnerability=Vulnerability(
                feed="vulnerabilities",
                feed_group="whatever:hello",
                vulnerability_id="meh",
            ),
            nvd=[NVDReference(vulnerability_id="CVE-2019-12904")],
        )

        input_matches = [a for x in range(count)]

        results = ImageVulnerabilitiesDeduplicator(FeedGroupRank()).execute(
            input_matches
        )
        assert len(results) == 1

    @pytest.mark.parametrize(
        "test_input",
        [pytest.param([], id="empty-list"), pytest.param(None, id="none")],
    )
    def test_execute_invalid_input(self, test_input):
        assert (
            ImageVulnerabilitiesDeduplicator(FeedGroupRank()).execute(test_input)
            == list()
        )
Example #14
0
class TestVulnerabilityIdentity:
    @pytest.mark.parametrize(
        "test_input",
        [
            pytest.param(
                [NVDReference(vulnerability_id="CVE-abc")],
                id="single-nvd",
            ),
            pytest.param(
                [
                    NVDReference(vulnerability_id="CVE-abc"),
                    NVDReference(vulnerability_id="CVE-def"),
                    NVDReference(vulnerability_id="CVE-ghi"),
                ],
                id="multiple-nvd",
            ),
        ],
    )
    def test_from_with_nvd(self, test_input):
        match = VulnerabilityMatch(
            artifact=Artifact(
                name="blah",
                location="/usr/local/java/blah",
                pkg_type="java",
                version="1.2.3maven",
            ),
            vulnerability=Vulnerability(
                feed="vulnerabilities",
                feed_group="whatever:hello",
                vulnerability_id="meh",
            ),
        )
        match.nvd = test_input
        identity_objects = VulnerabilityIdentity.from_match(match)

        assert identity_objects
        assert isinstance(identity_objects, list) and len(identity_objects) == len(
            test_input
        )
        for identity_object, input_nvd in zip(identity_objects, test_input):
            assert identity_object.vuln_id == input_nvd.vulnerability_id
            assert identity_object.pkg_name == match.artifact.name
            assert identity_object.pkg_type == match.artifact.pkg_type
            assert identity_object.pkg_version == match.artifact.version
            assert identity_object.pkg_path == match.artifact.location

    def test_from_without_nvd(self):
        match = VulnerabilityMatch(
            artifact=Artifact(
                name="blah",
                location="/usr/local/java/blah",
                pkg_type="java",
                version="1.2.3maven",
            ),
            vulnerability=Vulnerability(
                feed="vulnerabilities",
                feed_group="whatever:hello",
                vulnerability_id="meh",
            ),
            nvd=[],
        )
        identity_objects = VulnerabilityIdentity.from_match(match)

        assert identity_objects
        assert isinstance(identity_objects, list) and len(identity_objects) == 1

        identity_object = identity_objects[0]
        assert identity_object.vuln_id == match.vulnerability.vulnerability_id
        assert identity_object.pkg_name == match.artifact.name
        assert identity_object.pkg_type == match.artifact.pkg_type
        assert identity_object.pkg_version == match.artifact.version
        assert identity_object.pkg_path == match.artifact.location

    @pytest.mark.parametrize(
        "lhs, rhs, expected",
        [
            pytest.param(
                VulnerabilityMatch(
                    vulnerability=Vulnerability(
                        feed="trusty",
                        feed_group="trusty:chameleon",
                        vulnerability_id="meh",
                    ),
                    nvd=[NVDReference(vulnerability_id="CVE-abc")],
                ),
                VulnerabilityMatch(
                    Vulnerability(
                        feed="hedgehog",
                        feed_group="hedgy:thorny",
                        vulnerability_id="foo",
                    ),
                    nvd=[NVDReference(vulnerability_id="CVE-abc")],
                ),
                True,
                id="equal-different-namespaces",
            ),
            pytest.param(
                VulnerabilityMatch(
                    vulnerability=Vulnerability(
                        feed="trusty",
                        feed_group="trusty:chameleon",
                        vulnerability_id="meh",
                    ),
                    nvd=[
                        NVDReference(vulnerability_id="CVE-abc"),
                        NVDReference(vulnerability_id="CVE-def"),
                        NVDReference(vulnerability_id="CVE-ghi"),
                    ],
                ),
                VulnerabilityMatch(
                    vulnerability=Vulnerability(
                        feed="hedgehog",
                        feed_group="hedgy:thorny",
                        vulnerability_id="foo",
                    ),
                    nvd=[
                        NVDReference(vulnerability_id="CVE-abc"),
                        NVDReference(vulnerability_id="CVE-def"),
                        NVDReference(vulnerability_id="CVE-ghi"),
                    ],
                ),
                True,
                id="equal-multiple-cvss",
            ),
            pytest.param(
                VulnerabilityMatch(
                    vulnerability=Vulnerability(
                        feed="trusty",
                        feed_group="trusty:chameleon",
                        vulnerability_id="meh",
                    ),
                    nvd=[NVDReference(vulnerability_id="CVE-abc")],
                ),
                VulnerabilityMatch(
                    vulnerability=Vulnerability(
                        feed="hedgehog",
                        feed_group="hedgy:thorny",
                        vulnerability_id="foo",
                    ),
                    nvd=[NVDReference(vulnerability_id="CVE-def")],
                ),
                False,
                id="not-equal",
            ),
        ],
    )
    def test_equality_constant_artifact(self, lhs, rhs, expected):
        artifact = Artifact(
            name="blah",
            location="/usr/local/java/blah",
            pkg_type="java",
            version="1.2.3maven",
        )
        lhs.artifact = artifact

        rhs.artifact = artifact

        assert (
            VulnerabilityIdentity.from_match(lhs)
            == VulnerabilityIdentity.from_match(rhs)
        ) == expected

    @pytest.mark.parametrize("count", [1, 2, 3, 4, 5])
    def test_hash(self, count):
        record = VulnerabilityIdentity(
            vuln_id="meh",
            pkg_name="blah",
            pkg_version="1.2.3maven",
            pkg_type="java",
            pkg_path="blah",
        )

        test_input = [record for x in range(count)]
        result = set(test_input)
        assert result and len(result) == 1
Example #15
0
class TestRankedVulnerabilityMatch:
    def test_from(self):
        match = VulnerabilityMatch(
            artifact=Artifact(
                name="blah",
                location="/usr/local/java/blah",
                pkg_type="java",
                version="1.2.3maven",
            ),
            vulnerability=Vulnerability(
                feed="vulnerabilities",
                feed_group="whatever:hello",
                vulnerability_id="meh",
            ),
            nvd=[NVDReference(vulnerability_id="CVE-abc")],
        )
        rank_strategy = FeedGroupRank()
        ranked_match = RankedVulnerabilityMatch.from_match(match, FeedGroupRank())

        assert ranked_match
        assert ranked_match.vuln_id == match.vulnerability.vulnerability_id
        assert ranked_match.vuln_namespace == match.vulnerability.feed_group
        assert ranked_match.pkg_name == match.artifact.name
        assert ranked_match.pkg_type == match.artifact.pkg_type
        assert ranked_match.pkg_version == match.artifact.version
        assert ranked_match.pkg_path == match.artifact.location
        assert ranked_match.rank == rank_strategy.__default__

    @pytest.mark.parametrize(
        "lhs, rhs, expected",
        [
            pytest.param(
                VulnerabilityMatch(
                    vulnerability=Vulnerability(
                        feed="trusty",
                        feed_group="trusty:chameleon",
                        vulnerability_id="meh",
                    ),
                    nvd=[NVDReference(vulnerability_id="CVE-abc")],
                ),
                VulnerabilityMatch(
                    vulnerability=Vulnerability(
                        feed="hedgehog",
                        feed_group="hedgy:thorny",
                        vulnerability_id="foo",
                    ),
                    nvd=[NVDReference(vulnerability_id="CVE-abc")],
                ),
                False,
                id="not-equal-different-ids",
            ),
            pytest.param(
                VulnerabilityMatch(
                    vulnerability=Vulnerability(
                        feed="trusty",
                        feed_group="trusty:chameleon",
                        vulnerability_id="meh",
                    ),
                    nvd=[
                        NVDReference(vulnerability_id="CVE-abc"),
                        NVDReference(vulnerability_id="CVE-def"),
                        NVDReference(vulnerability_id="CVE-ghi"),
                    ],
                ),
                VulnerabilityMatch(
                    vulnerability=Vulnerability(
                        feed="trusty",
                        feed_group="trusty:chameleon",
                        vulnerability_id="meh",
                    ),
                    nvd=[NVDReference(vulnerability_id="CVE-abc")],
                ),
                True,
                id="equal-different-cvss",
            ),
            pytest.param(
                VulnerabilityMatch(
                    vulnerability=Vulnerability(
                        feed="trusty",
                        feed_group="trusty:chameleon",
                        vulnerability_id="meh",
                    ),
                    nvd=[NVDReference(vulnerability_id="CVE-abc")],
                ),
                VulnerabilityMatch(
                    vulnerability=Vulnerability(
                        feed="trusty",
                        feed_group="trusty:python",
                        vulnerability_id="meh",
                    ),
                    nvd=[NVDReference(vulnerability_id="CVE-abc")],
                ),
                False,
                id="not-equal-different-namespaces",
            ),
        ],
    )
    def test_equality_constant_artifact(self, lhs, rhs, expected):
        artifact = Artifact(
            name="blah",
            location="/usr/local/java/blah",
            pkg_type="java",
            version="1.2.3maven",
        )
        lhs.artifact = artifact

        rhs.artifact = artifact

        assert (
            RankedVulnerabilityMatch.from_match(lhs, FeedGroupRank())
            == RankedVulnerabilityMatch.from_match(rhs, FeedGroupRank())
        ) == expected

    @pytest.mark.parametrize("count", [1, 2, 3, 4, 5])
    def test_hash_empty_match(self, count):
        record = RankedVulnerabilityMatch(
            vuln_id="meh",
            vuln_namespace="trusty:chameleon",
            pkg_name="blah",
            pkg_version="1.2.3maven",
            pkg_type="java",
            pkg_path="blah",
            rank=100,
            match_obj=VulnerabilityMatch(),
        )

        test_input = [record for x in range(count)]
        result = set(test_input)
        assert result and len(result) == 1

    @pytest.mark.parametrize(
        "test_input",
        [
            pytest.param(
                [
                    VulnerabilityMatch(
                        artifact=Artifact(
                            name="blah",
                            location="/usr/local/java/blah",
                            pkg_type="java",
                            version="1.2.3maven",
                        ),
                        vulnerability=Vulnerability(
                            feed="twisty",
                            feed_group="twisty:python",
                            vulnerability_id="meh",
                        ),
                        nvd=[NVDReference(vulnerability_id="CVE-abc")],
                    ),
                    VulnerabilityMatch(
                        artifact=Artifact(
                            name="foo",
                            location="/usr/local/java/foo",
                            pkg_type="unknown",
                            version="1.2.3",
                        ),
                        vulnerability=Vulnerability(
                            feed="tricky",
                            feed_group="tricky:chameleon",
                            vulnerability_id="meh",
                        ),
                        nvd=[NVDReference(vulnerability_id="CVE-def")],
                    ),
                ],
                id="different-matches",
            ),
            pytest.param(
                [
                    VulnerabilityMatch(
                        artifact=Artifact(
                            name="blah",
                            location="/usr/local/java/blah",
                            pkg_type="java",
                            version="1.2.3maven",
                        ),
                        vulnerability=Vulnerability(
                            feed="twisty",
                            feed_group="twisty:python",
                            vulnerability_id="meh",
                        ),
                        nvd=[NVDReference(vulnerability_id="CVE-abc")],
                    ),
                ]
                * 3,
                id="same-matches",
            ),
        ],
    )
    def test_hash(self, test_input):
        vuln_rank_objects = [
            RankedVulnerabilityMatch(
                vuln_id="meh",
                vuln_namespace="trusty:chameleon",
                pkg_name="blah",
                pkg_version="1.2.3maven",
                pkg_type="java",
                pkg_path="/usr/local/blah",
                rank=100,
                match_obj=item,
            )
            for item in test_input
        ]
        result = set(vuln_rank_objects)
        assert result and len(result) == 1

        result = list(result)[0]
        assert result.vuln_id == "meh"
        assert result.vuln_namespace == "trusty:chameleon"
        assert result.pkg_name == "blah"
        assert result.pkg_type == "java"
        assert result.pkg_path == "/usr/local/blah"
        assert result.rank == 100