From 68abbbf28ede8e1656002c7b82d36dc427decaf8 Mon Sep 17 00:00:00 2001 From: ziad hany Date: Fri, 13 Feb 2026 20:04:48 +0200 Subject: [PATCH] Add advisory_id to the inputs of AdvisoryDataV2 compute_content_id_v2 so it produces different hashes for different advisory IDs. Signed-off-by: ziad hany --- vulnerabilities/pipes/advisory.py | 8 +++-- vulnerabilities/tests/test_models.py | 47 ++++++++++++++++++++++++++++ vulnerabilities/utils.py | 1 + 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/vulnerabilities/pipes/advisory.py b/vulnerabilities/pipes/advisory.py index 54521cc2a..b571b2871 100644 --- a/vulnerabilities/pipes/advisory.py +++ b/vulnerabilities/pipes/advisory.py @@ -304,7 +304,7 @@ def insert_advisory_v2( patches = get_or_create_advisory_patches(patches=advisory.patches) weaknesses = get_or_create_advisory_weaknesses(weaknesses=advisory.weaknesses) content_id = compute_content_id_v2(advisory_data=advisory) - + created = False try: default_data = { "datasource_id": pipeline_id, @@ -314,11 +314,13 @@ def insert_advisory_v2( "date_published": advisory.date_published, "date_collected": datetime.now(timezone.utc), "original_advisory_text": advisory.original_advisory_text, + "url": advisory.url, } advisory_obj, created = AdvisoryV2.objects.get_or_create( + advisory_id=advisory.advisory_id, + datasource_id=pipeline_id, unique_content_id=content_id, - url=advisory.url, defaults=default_data, ) related_fields = { @@ -334,7 +336,7 @@ def insert_advisory_v2( getattr(advisory_obj, field_name).add(*values) except Advisory.MultipleObjectsReturned: - logger.error( + logger( f"Multiple Advisories returned: unique_content_id: {content_id}, url: {advisory.url}, advisory: {advisory!r}" ) raise diff --git a/vulnerabilities/tests/test_models.py b/vulnerabilities/tests/test_models.py index adc603158..96dc9b0ff 100644 --- a/vulnerabilities/tests/test_models.py +++ b/vulnerabilities/tests/test_models.py @@ -30,12 +30,15 @@ from vulnerabilities.importer import PatchData from vulnerabilities.importer import Reference from vulnerabilities.importer import ReferenceV2 +from vulnerabilities.importer import VulnerabilitySeverity from vulnerabilities.models import AdvisorySeverity from vulnerabilities.models import Alias from vulnerabilities.models import Package from vulnerabilities.models import Patch from vulnerabilities.models import Vulnerability +from vulnerabilities.severity_systems import CVSSV3 from vulnerabilities.severity_systems import CVSSV4 +from vulnerabilities.severity_systems import ScoringSystem from vulnerabilities.utils import compute_content_id @@ -771,3 +774,47 @@ def test_advisoryv2_to_advisory_data_patch_seralization(self): result = models.AdvisoryV2.objects.first().to_advisory_data() self.assertEqual(result, self.advisoryv2_data1) + + +class TestAdvisoryV2ModelDuplication(DjangoTestCase): + def setUp(self): + self.advisoryv2_data1 = AdvisoryDataV2( + advisory_id="CVE-2023-0401", + aliases=[], + summary="", + affected_packages=[], + severities=[ + VulnerabilitySeverity( + system=CVSSV3, + value="7.5", + scoring_elements="CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H", + ) + ], + patches=[], + url="https://test.com", + ) + + self.advisoryv2_data2 = AdvisoryDataV2( + advisory_id="CVE-2023-0662", + aliases=[], + summary="", + affected_packages=[], + severities=[ + VulnerabilitySeverity( + system=CVSSV3, + value="7.5", + scoring_elements="CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H", + ) + ], + patches=[], + url="https://test.com", + ) + + def test_advisoryv2_duplication_data(self): + from vulnerabilities.pipes.advisory import insert_advisory_v2 + + insert_advisory_v2(advisory=self.advisoryv2_data1, pipeline_id="test_pipeline") + insert_advisory_v2(advisory=self.advisoryv2_data2, pipeline_id="test_pipeline") + result = models.AdvisoryV2.objects.count() + + self.assertEqual(result, 2) diff --git a/vulnerabilities/utils.py b/vulnerabilities/utils.py index 5e09a9cf9..465348288 100644 --- a/vulnerabilities/utils.py +++ b/vulnerabilities/utils.py @@ -689,6 +689,7 @@ def compute_content_id_v2(advisory_data): elif isinstance(advisory_data, AdvisoryDataV2): normalized_data = { + "advisory_id": normalize_text(advisory_data.advisory_id), "aliases": normalize_list(advisory_data.aliases), "summary": normalize_text(advisory_data.summary), "affected_packages": [