From 07b0592e13248a6f32bae8fe49bee542e6926d74 Mon Sep 17 00:00:00 2001 From: ziad hany Date: Fri, 2 Jan 2026 17:17:17 +0200 Subject: [PATCH 1/2] Migrate Suse Score importer v2 Signed-off-by: ziad hany --- vulnerabilities/importers/__init__.py | 2 + .../v2_importers/suse_score_importer.py | 74 +++++++++++++++++++ .../test_suse_score_importer_v2.py | 33 +++++++++ .../suse-cvss-scores-expected.json | 66 +++++++++++++++++ .../suse_scores_v2/suse-cvss-scores.yaml | 22 ++++++ 5 files changed, 197 insertions(+) create mode 100644 vulnerabilities/pipelines/v2_importers/suse_score_importer.py create mode 100644 vulnerabilities/tests/pipelines/v2_importers/test_suse_score_importer_v2.py create mode 100644 vulnerabilities/tests/test_data/suse_scores_v2/suse-cvss-scores-expected.json create mode 100644 vulnerabilities/tests/test_data/suse_scores_v2/suse-cvss-scores.yaml diff --git a/vulnerabilities/importers/__init__.py b/vulnerabilities/importers/__init__.py index 8aa9961d5..b65bab937 100644 --- a/vulnerabilities/importers/__init__.py +++ b/vulnerabilities/importers/__init__.py @@ -63,6 +63,7 @@ from vulnerabilities.pipelines.v2_importers import pysec_importer as pysec_importer_v2 from vulnerabilities.pipelines.v2_importers import redhat_importer as redhat_importer_v2 from vulnerabilities.pipelines.v2_importers import ruby_importer as ruby_importer_v2 +from vulnerabilities.pipelines.v2_importers import suse_score_importer as suse_score_importer_v2 from vulnerabilities.pipelines.v2_importers import vulnrichment_importer as vulnrichment_importer_v2 from vulnerabilities.pipelines.v2_importers import xen_importer as xen_importer_v2 from vulnerabilities.utils import create_registry @@ -90,6 +91,7 @@ ruby_importer_v2.RubyImporterPipeline, epss_importer_v2.EPSSImporterPipeline, mattermost_importer_v2.MattermostImporterPipeline, + suse_score_importer_v2.SUSESeverityScoreImporterPipeline, nvd_importer.NVDImporterPipeline, github_importer.GitHubAPIImporterPipeline, gitlab_importer.GitLabImporterPipeline, diff --git a/vulnerabilities/pipelines/v2_importers/suse_score_importer.py b/vulnerabilities/pipelines/v2_importers/suse_score_importer.py new file mode 100644 index 000000000..ccd8585a8 --- /dev/null +++ b/vulnerabilities/pipelines/v2_importers/suse_score_importer.py @@ -0,0 +1,74 @@ +# +# Copyright (c) nexB Inc. and others. All rights reserved. +# VulnerableCode is a trademark of nexB Inc. +# SPDX-License-Identifier: Apache-2.0 +# See http://www.apache.org/licenses/LICENSE-2.0 for the license text. +# See https://github.com/aboutcode-org/vulnerablecode for support or download. +# See https://aboutcode.org for more information about nexB OSS projects. +# + +from typing import Iterable + +from vulnerabilities import severity_systems +from vulnerabilities.importer import AdvisoryData +from vulnerabilities.importer import VulnerabilitySeverity +from vulnerabilities.management.commands.commit_export import logger +from vulnerabilities.pipelines import VulnerableCodeBaseImporterPipelineV2 +from vulnerabilities.utils import fetch_yaml +from vulnerabilities.utils import is_cve + + +class SUSESeverityScoreImporterPipeline(VulnerableCodeBaseImporterPipelineV2): + spdx_license_expression = "CC-BY-4.0" + license_url = "https://ftp.suse.com/pub/projects/security/yaml/LICENSE" + pipeline_id = "suse_importer_v2" + url = "https://ftp.suse.com/pub/projects/security/yaml/suse-cvss-scores.yaml" + + @classmethod + def steps(cls): + return ( + cls.fetch_advisories, + cls.collect_and_store_advisories, + ) + + def fetch_advisories(self): + self.score_data = fetch_yaml(self.url) + + def advisories_count(self): + return sum(1 for _ in self.score_data) + + def collect_advisories(self) -> Iterable[AdvisoryData]: + systems_by_version = { + "2.0": severity_systems.CVSSV2, + "3": severity_systems.CVSSV3, + "3.1": severity_systems.CVSSV31, + "4": severity_systems.CVSSV4, + } + + for cve_id in self.score_data or []: + severities = [] + for cvss_score in self.score_data[cve_id].get("cvss") or []: + cvss_version = cvss_score.get("version") or "" + scoring_system = systems_by_version.get(cvss_version) + if not scoring_system: + logger.error(f"Unsupported CVSS version: {cvss_version}") + continue + base_score = str(cvss_score.get("score") or "") + vector = str(cvss_score.get("vector") or "") + score = VulnerabilitySeverity( + system=scoring_system, + value=base_score, + scoring_elements=vector, + ) + severities.append(score) + + if not is_cve(cve_id): + continue + + yield AdvisoryData( + advisory_id=cve_id, + aliases=[], + summary="", + severities=severities, + url=self.url, + ) diff --git a/vulnerabilities/tests/pipelines/v2_importers/test_suse_score_importer_v2.py b/vulnerabilities/tests/pipelines/v2_importers/test_suse_score_importer_v2.py new file mode 100644 index 000000000..f98bbcc24 --- /dev/null +++ b/vulnerabilities/tests/pipelines/v2_importers/test_suse_score_importer_v2.py @@ -0,0 +1,33 @@ +# +# Copyright (c) nexB Inc. and others. All rights reserved. +# VulnerableCode is a trademark of nexB Inc. +# SPDX-License-Identifier: Apache-2.0 +# See http://www.apache.org/licenses/LICENSE-2.0 for the license text. +# See https://github.com/aboutcode-org/vulnerablecode for support or download. +# See https://aboutcode.org for more information about nexB OSS projects. +# + +from pathlib import Path + +import saneyaml + +from vulnerabilities.pipelines.v2_importers.suse_score_importer import ( + SUSESeverityScoreImporterPipeline, +) +from vulnerabilities.tests import util_tests + +TEST_DATA = Path(__file__).parent.parent.parent / "test_data" / "suse_scores_v2" + +TEST_YAML_DB = TEST_DATA / "suse-cvss-scores.yaml" + + +def test_suse_score_advisories(): + pipeline = SUSESeverityScoreImporterPipeline() + + with open(TEST_YAML_DB) as f: + pipeline.score_data = saneyaml.load(f) + + result = [adv.to_dict() for adv in pipeline.collect_advisories()] + + expected_file = TEST_DATA / "suse-cvss-scores-expected.json" + util_tests.check_results_against_json(result, expected_file) diff --git a/vulnerabilities/tests/test_data/suse_scores_v2/suse-cvss-scores-expected.json b/vulnerabilities/tests/test_data/suse_scores_v2/suse-cvss-scores-expected.json new file mode 100644 index 000000000..5d6c805ec --- /dev/null +++ b/vulnerabilities/tests/test_data/suse_scores_v2/suse-cvss-scores-expected.json @@ -0,0 +1,66 @@ +[ + { + "advisory_id": "CVE-2004-0230", + "aliases": [], + "summary": "", + "affected_packages": [], + "references_v2": [], + "patches": [], + "severities": [ + { + "system": "cvssv2", + "value": "4.3", + "scoring_elements": "AV:N/AC:M/Au:N/C:N/I:N/A:P" + }, + { + "system": "cvssv3.1", + "value": "3.7", + "scoring_elements": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L" + } + ], + "date_published": null, + "weaknesses": [], + "url": "https://ftp.suse.com/pub/projects/security/yaml/suse-cvss-scores.yaml" + }, + { + "advisory_id": "CVE-2003-1605", + "aliases": [], + "summary": "", + "affected_packages": [], + "references_v2": [], + "patches": [], + "severities": [ + { + "system": "cvssv3", + "value": "8.6", + "scoring_elements": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N" + } + ], + "date_published": null, + "weaknesses": [], + "url": "https://ftp.suse.com/pub/projects/security/yaml/suse-cvss-scores.yaml" + }, + { + "advisory_id": "CVE-2010-20103", + "aliases": [], + "summary": "", + "affected_packages": [], + "references_v2": [], + "patches": [], + "severities": [ + { + "system": "cvssv3.1", + "value": "9.8", + "scoring_elements": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H" + }, + { + "system": "cvssv4", + "value": "9.3", + "scoring_elements": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N" + } + ], + "date_published": null, + "weaknesses": [], + "url": "https://ftp.suse.com/pub/projects/security/yaml/suse-cvss-scores.yaml" + } +] \ No newline at end of file diff --git a/vulnerabilities/tests/test_data/suse_scores_v2/suse-cvss-scores.yaml b/vulnerabilities/tests/test_data/suse_scores_v2/suse-cvss-scores.yaml new file mode 100644 index 000000000..c03bb8780 --- /dev/null +++ b/vulnerabilities/tests/test_data/suse_scores_v2/suse-cvss-scores.yaml @@ -0,0 +1,22 @@ +--- +CVE-2004-0230: + cvss: + - version: 2.0 + score: 4.3 + vector: AV:N/AC:M/Au:N/C:N/I:N/A:P + - version: 3.1 + score: 3.7 + vector: CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L +CVE-2003-1605: + cvss: + - version: 3 + score: 8.6 + vector: CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N +CVE-2010-20103: + cvss: + - version: 3.1 + score: 9.8 + vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H + - version: 4 + score: 9.3 + vector: CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N \ No newline at end of file From 46914e82391128d0f59fe8ad7ae2f9db988658df Mon Sep 17 00:00:00 2001 From: ziad hany Date: Fri, 2 Jan 2026 20:39:23 +0200 Subject: [PATCH 2/2] Add a reference URL to ensure the advisory is created Signed-off-by: ziad hany --- .../v2_importers/suse_score_importer.py | 6 ++--- .../suse-cvss-scores-expected.json | 24 ++++++++++++++++--- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/vulnerabilities/pipelines/v2_importers/suse_score_importer.py b/vulnerabilities/pipelines/v2_importers/suse_score_importer.py index ccd8585a8..d5c1da768 100644 --- a/vulnerabilities/pipelines/v2_importers/suse_score_importer.py +++ b/vulnerabilities/pipelines/v2_importers/suse_score_importer.py @@ -11,11 +11,11 @@ from vulnerabilities import severity_systems from vulnerabilities.importer import AdvisoryData +from vulnerabilities.importer import ReferenceV2 from vulnerabilities.importer import VulnerabilitySeverity from vulnerabilities.management.commands.commit_export import logger from vulnerabilities.pipelines import VulnerableCodeBaseImporterPipelineV2 from vulnerabilities.utils import fetch_yaml -from vulnerabilities.utils import is_cve class SUSESeverityScoreImporterPipeline(VulnerableCodeBaseImporterPipelineV2): @@ -62,13 +62,11 @@ def collect_advisories(self) -> Iterable[AdvisoryData]: ) severities.append(score) - if not is_cve(cve_id): - continue - yield AdvisoryData( advisory_id=cve_id, aliases=[], summary="", severities=severities, + references_v2=[ReferenceV2(reference_id=cve_id, url=self.url)], url=self.url, ) diff --git a/vulnerabilities/tests/test_data/suse_scores_v2/suse-cvss-scores-expected.json b/vulnerabilities/tests/test_data/suse_scores_v2/suse-cvss-scores-expected.json index 5d6c805ec..a68ace5b9 100644 --- a/vulnerabilities/tests/test_data/suse_scores_v2/suse-cvss-scores-expected.json +++ b/vulnerabilities/tests/test_data/suse_scores_v2/suse-cvss-scores-expected.json @@ -4,7 +4,13 @@ "aliases": [], "summary": "", "affected_packages": [], - "references_v2": [], + "references_v2": [ + { + "reference_id": "CVE-2004-0230", + "reference_type": "", + "url": "https://ftp.suse.com/pub/projects/security/yaml/suse-cvss-scores.yaml" + } + ], "patches": [], "severities": [ { @@ -27,7 +33,13 @@ "aliases": [], "summary": "", "affected_packages": [], - "references_v2": [], + "references_v2": [ + { + "reference_id": "CVE-2003-1605", + "reference_type": "", + "url": "https://ftp.suse.com/pub/projects/security/yaml/suse-cvss-scores.yaml" + } + ], "patches": [], "severities": [ { @@ -45,7 +57,13 @@ "aliases": [], "summary": "", "affected_packages": [], - "references_v2": [], + "references_v2": [ + { + "reference_id": "CVE-2010-20103", + "reference_type": "", + "url": "https://ftp.suse.com/pub/projects/security/yaml/suse-cvss-scores.yaml" + } + ], "patches": [], "severities": [ {