From b7fcf4583ec107dbdb80edd1fe17613a64e53bf2 Mon Sep 17 00:00:00 2001 From: David G Date: Tue, 25 Aug 2026 06:33:56 +0100 Subject: [PATCH 1/2] fix: skip unresolvable cpematch SWIDs --- arango_cve_processor/managers/cpe_match.py | 19 ++++-- tests/unit/managers/test_cpematch.py | 73 ++++++++++++++++++++++ 2 files changed, 87 insertions(+), 5 deletions(-) diff --git a/arango_cve_processor/managers/cpe_match.py b/arango_cve_processor/managers/cpe_match.py index 53d010d..cde2c88 100644 --- a/arango_cve_processor/managers/cpe_match.py +++ b/arango_cve_processor/managers/cpe_match.py @@ -81,13 +81,22 @@ def relate_single(self, indicator): retval = [] for x_cpe_item in itertools.chain(*indicator['x_cpes'].values()): if match_data := self.groupings.get(x_cpe_item['matchCriteriaId']): - objects = cpe.parse_objects_for_criteria(match_data) - grouping_object = objects[0] - relationships = cpe.relate_indicator(grouping_object, indicator) - deprecations = cpe.parse_deprecations(objects[1:]) + try: + objects = cpe.parse_objects_for_criteria(match_data) + grouping_object = objects[0] + relationships = cpe.relate_indicator(grouping_object, indicator) + deprecations = cpe.parse_deprecations(objects[1:]) + except ValueError as exc: + logging.error( + "skipping unresolvable CPE match %s for %s: %s", + x_cpe_item["matchCriteriaId"], + indicator["name"], + exc, + ) + continue for r in relationships: r['_from'] = indicator['_id'] retval.extend(objects) retval.extend(relationships) retval.extend(deprecations) - return stix2python(retval) \ No newline at end of file + return stix2python(retval) diff --git a/tests/unit/managers/test_cpematch.py b/tests/unit/managers/test_cpematch.py index f3ca4d9..2318da3 100644 --- a/tests/unit/managers/test_cpematch.py +++ b/tests/unit/managers/test_cpematch.py @@ -188,6 +188,79 @@ def test_relate_single(cpematch_manager): } +def test_relate_single_skips_one_unresolvable_match(cpematch_manager, caplog): + indicator = { + "_id": "nvd_cve_vertex_collection/indicator--broken+2025-09-12T11:25:34.563706Z", + "created": "2025-01-02T15:15:18.650Z", + "external_references": [ + { + "source_name": "cve", + "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-45830", + "external_id": "CVE-2022-45830", + } + ], + "id": "indicator--broken", + "modified": "2025-06-05T21:01:15.860Z", + "name": "CVE-2022-45830", + "x_cpes": { + "not_vulnerable": [], + "vulnerable": [ + { + "criteria": "cpe:2.3:a:broken:broken:*:*:*:*:*:*:*:*", + "matchCriteriaId": "BROKEN-SWID", + }, + { + "criteria": "cpe:2.3:a:good:good:*:*:*:*:*:*:*:*", + "matchCriteriaId": "GOOD-SWID", + }, + ], + }, + } + cpematch_manager.groupings = { + "BROKEN-SWID": {"matchCriteriaId": "BROKEN-SWID"}, + "GOOD-SWID": {"matchCriteriaId": "GOOD-SWID"}, + } + grouping = { + "id": "grouping--good", + "name": "good", + "external_references": [{"external_id": "GOOD-SWID"}], + } + software = {"id": "software--good"} + + with ( + patch( + "arango_cve_processor.managers.cpe_match.cpe.parse_objects_for_criteria", + side_effect=[ValueError("SWID missing from NVD"), [grouping, software]], + ), + patch( + "arango_cve_processor.managers.cpe_match.cpe.relate_indicator", + return_value=[{"type": "relationship", "id": "relationship--good"}], + ), + patch( + "arango_cve_processor.managers.cpe_match.cpe.parse_deprecations", + return_value=[{"type": "relationship", "id": "relationship--deprecation"}], + ), + patch( + "arango_cve_processor.managers.cpe_match.stix2python", + side_effect=lambda objects: objects, + ), + ): + objects = cpematch_manager.relate_single(indicator) + + assert objects == [ + grouping, + software, + { + "type": "relationship", + "id": "relationship--good", + "_from": indicator["_id"], + }, + {"type": "relationship", "id": "relationship--deprecation"}, + ] + assert "skipping unresolvable CPE match BROKEN-SWID" in caplog.text + assert indicator["name"] in caplog.text + + @pytest.fixture def mocked_updates(): c1 = { From 5104843cc8a2d61d7d8f143740af834ef457e49e Mon Sep 17 00:00:00 2001 From: David G Date: Tue, 25 Aug 2026 06:35:04 +0100 Subject: [PATCH 2/2] Update pyproject.toml --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 4951f94..fa40ec7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "arango_cve_processor" -version = "1.4.14" +version = "1.4.15" authors = [ { name = "dogesec" } ]