Skip to content

Commit 0828341

Browse files
committed
Test advisory with duplicate content_id
Signed-off-by: Keshav Priyadarshi <[email protected]>
1 parent 7350f59 commit 0828341

10 files changed

+208
-91
lines changed

vulnerabilities/import_runner.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ def process_advisories(
123123
obj.aliases.add(*aliases)
124124
if not obj.date_imported:
125125
advisories.append(obj)
126-
except Advisory.MultipleObjectsReturned as mo:
126+
except Advisory.MultipleObjectsReturned:
127127
logger.error(
128128
f"Multiple Advisories returned: unique_content_id: {content_id}, url: {data.url}, advisory: {advisory!r}"
129129
)

vulnerabilities/tests/conftest.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ def no_rmtree(monkeypatch):
2525
# Step 2: Run test for importer only if it is activated (pytestmark = pytest.mark.skipif(...))
2626
# Step 3: Migrate all the tests
2727
collect_ignore = [
28-
"test_models.py",
2928
"test_rust.py",
3029
"test_suse_backports.py",
3130
"test_suse.py",

vulnerabilities/tests/pipelines/test_populate_vulnerability_summary_pipeline.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ def test_populate_missing_summaries_from_nvd(self):
4343
created_by="nvd_importer",
4444
date_collected=datetime.datetime(2024, 1, 1, tzinfo=pytz.UTC),
4545
unique_content_id="Test",
46+
url="https://test.com",
4647
)
4748
adv.aliases.add(alias)
4849

@@ -110,6 +111,7 @@ def test_non_nvd_advisory_ignored(self):
110111
created_by="other_importer",
111112
date_collected=datetime.datetime(2024, 1, 1, tzinfo=pytz.UTC),
112113
unique_content_id="Test",
114+
url="https://test.com",
113115
)
114116

115117
adv.aliases.add(alias)
@@ -138,6 +140,7 @@ def test_multiple_matching_advisories(self):
138140
created_by="nvd_importer",
139141
date_collected=datetime.datetime(2024, 1, 1, tzinfo=pytz.UTC),
140142
unique_content_id="Test",
143+
url="https://test.com",
141144
)
142145

143146
adv1.aliases.add(alias)
@@ -147,6 +150,7 @@ def test_multiple_matching_advisories(self):
147150
created_by="nvd_importer",
148151
date_collected=datetime.datetime(2024, 1, 2, tzinfo=pytz.UTC),
149152
unique_content_id="Test-1",
153+
url="https://test.com",
150154
)
151155

152156
adv2.aliases.add(alias)

vulnerabilities/tests/pipelines/test_remove_duplicate_advisories.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ def setUp(self):
3232
)
3333
],
3434
references=[Reference(url="https://example.com/vuln1")],
35+
url="https://test.url/",
3536
)
3637

3738
def test_remove_duplicates_keeps_oldest(self):
@@ -49,9 +50,10 @@ def test_remove_duplicates_keeps_oldest(self):
4950
]
5051

5152
advisories = []
52-
for date in dates:
53+
for i, date in enumerate(dates):
5354
advisory = Advisory.objects.create(
54-
unique_content_id=compute_content_id(advisory_data=self.advisory_data),
55+
unique_content_id=f"incorrect-content-id{i}",
56+
url=self.advisory_data.url,
5557
summary=self.advisory_data.summary,
5658
affected_packages=[pkg.to_dict() for pkg in self.advisory_data.affected_packages],
5759
references=[ref.to_dict() for ref in self.advisory_data.references],
@@ -77,6 +79,7 @@ def test_different_content_preserved(self):
7779
# Create two advisories with different content
7880
advisory1 = Advisory.objects.create(
7981
unique_content_id="test-id1",
82+
url="https://test.url/",
8083
summary="Summary 1",
8184
affected_packages=[],
8285
date_collected=datetime.datetime(2024, 1, 1, tzinfo=pytz.UTC),
@@ -87,6 +90,7 @@ def test_different_content_preserved(self):
8790

8891
advisory2 = Advisory.objects.create(
8992
unique_content_id="test-id2",
93+
url="https://test.url/",
9094
summary="Summary 2",
9195
affected_packages=[],
9296
references=[],
@@ -111,6 +115,7 @@ def test_recompute_content_ids(self):
111115
# Create advisory without content ID
112116
advisory = Advisory.objects.create(
113117
unique_content_id="incorrect-content-id",
118+
url=self.advisory_data.url,
114119
summary=self.advisory_data.summary,
115120
affected_packages=[pkg.to_dict() for pkg in self.advisory_data.affected_packages],
116121
references=[ref.to_dict() for ref in self.advisory_data.references],
@@ -125,4 +130,4 @@ def test_recompute_content_ids(self):
125130
# Check that content ID was updated
126131
advisory.refresh_from_db()
127132
expected_content_id = compute_content_id(advisory_data=self.advisory_data)
128-
self.assertNotEqual(advisory.unique_content_id, expected_content_id)
133+
self.assertEqual(advisory.unique_content_id, expected_content_id)

vulnerabilities/tests/pipes/test_advisory.py

Lines changed: 105 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@
77
# See https://aboutcode.org for more information about nexB OSS projects.
88
#
99

10-
import pytest
10+
from datetime import datetime
11+
12+
from django.core.exceptions import ValidationError
13+
from django.test import TestCase
1114
from django.utils import timezone
1215
from packageurl import PackageURL
1316
from univers.version_range import VersionRange
@@ -18,65 +21,116 @@
1821
from vulnerabilities.importer import Reference
1922
from vulnerabilities.pipes.advisory import get_or_create_aliases
2023
from vulnerabilities.pipes.advisory import import_advisory
24+
from vulnerabilities.utils import compute_content_id
2125

22-
advisory_data1 = AdvisoryData(
23-
summary="vulnerability description here",
24-
affected_packages=[
25-
AffectedPackage(
26-
package=PackageURL(type="pypi", name="dummy"),
27-
affected_version_range=VersionRange.from_string("vers:pypi/>=1.0.0|<=2.0.0"),
28-
)
29-
],
30-
references=[Reference(url="https://example.com/with/more/info/CVE-2020-13371337")],
31-
date_published=timezone.now(),
32-
url="https://test.com",
33-
)
3426

27+
class TestPipeAdvisory(TestCase):
28+
def setUp(self):
29+
self.advisory_data1 = AdvisoryData(
30+
summary="vulnerability description here",
31+
affected_packages=[
32+
AffectedPackage(
33+
package=PackageURL(type="pypi", name="dummy"),
34+
affected_version_range=VersionRange.from_string("vers:pypi/>=1.0.0|<=2.0.0"),
35+
)
36+
],
37+
references=[Reference(url="https://example.com/with/more/info/CVE-2020-13371337")],
38+
date_published=timezone.now(),
39+
url="https://test.com",
40+
)
3541

36-
def get_advisory1(created_by="test_pipeline"):
37-
from vulnerabilities.pipes.advisory import insert_advisory
42+
def get_advisory1(self, created_by="test_pipeline"):
43+
from vulnerabilities.pipes.advisory import insert_advisory
3844

39-
return insert_advisory(
40-
advisory=advisory_data1,
41-
pipeline_id=created_by,
42-
)
45+
return insert_advisory(
46+
advisory=self.advisory_data1,
47+
pipeline_id=created_by,
48+
)
4349

50+
def get_all_vulnerability_relationships_objects(self):
51+
return {
52+
"vulnerabilities": list(models.Vulnerability.objects.all()),
53+
"aliases": list(models.Alias.objects.all()),
54+
"references": list(models.VulnerabilityReference.objects.all()),
55+
"advisories": list(models.Advisory.objects.all()),
56+
"packages": list(models.Package.objects.all()),
57+
"references": list(models.VulnerabilityReference.objects.all()),
58+
"severity": list(models.VulnerabilitySeverity.objects.all()),
59+
}
4460

45-
def get_all_vulnerability_relationships_objects():
46-
return {
47-
"vulnerabilities": list(models.Vulnerability.objects.all()),
48-
"aliases": list(models.Alias.objects.all()),
49-
"references": list(models.VulnerabilityReference.objects.all()),
50-
"advisories": list(models.Advisory.objects.all()),
51-
"packages": list(models.Package.objects.all()),
52-
"references": list(models.VulnerabilityReference.objects.all()),
53-
"severity": list(models.VulnerabilitySeverity.objects.all()),
54-
}
61+
def test_vulnerability_pipes_importer_import_advisory(self):
62+
advisory1 = self.get_advisory1(created_by="test_importer_pipeline")
63+
import_advisory(advisory=advisory1, pipeline_id="test_importer_pipeline")
64+
all_vulnerability_relation_objects = self.get_all_vulnerability_relationships_objects()
65+
import_advisory(advisory=advisory1, pipeline_id="test_importer_pipeline")
66+
assert (
67+
all_vulnerability_relation_objects == self.get_all_vulnerability_relationships_objects()
68+
)
5569

70+
def test_vulnerability_pipes_importer_import_advisory_different_pipelines(self):
71+
advisory1 = self.get_advisory1(created_by="test_importer_pipeline")
72+
import_advisory(advisory=advisory1, pipeline_id="test_importer1_pipeline")
73+
all_vulnerability_relation_objects = self.get_all_vulnerability_relationships_objects()
74+
import_advisory(advisory=advisory1, pipeline_id="test_importer2_pipeline")
75+
assert (
76+
all_vulnerability_relation_objects == self.get_all_vulnerability_relationships_objects()
77+
)
5678

57-
@pytest.mark.django_db
58-
def test_vulnerability_pipes_importer_import_advisory():
59-
advisory1 = get_advisory1(created_by="test_importer_pipeline")
60-
import_advisory(advisory=advisory1, pipeline_id="test_importer_pipeline")
61-
all_vulnerability_relation_objects = get_all_vulnerability_relationships_objects()
62-
import_advisory(advisory=advisory1, pipeline_id="test_importer_pipeline")
63-
assert all_vulnerability_relation_objects == get_all_vulnerability_relationships_objects()
79+
def test_vulnerability_pipes_get_or_create_aliases(self):
80+
aliases = ["CVE-TEST-123", "CVE-TEST-124"]
81+
result_aliases_qs = get_or_create_aliases(aliases=aliases)
82+
result_aliases = [i.alias for i in result_aliases_qs]
83+
assert 2 == result_aliases_qs.count()
84+
assert "CVE-TEST-123" in result_aliases
85+
assert "CVE-TEST-124" in result_aliases
6486

87+
def test_advisory_insert_without_url(self):
88+
with self.assertRaises(ValidationError):
89+
date = datetime.now()
90+
models.Advisory.objects.create(
91+
unique_content_id=compute_content_id(advisory_data=self.advisory_data1),
92+
summary=self.advisory_data1.summary,
93+
affected_packages=[pkg.to_dict() for pkg in self.advisory_data1.affected_packages],
94+
references=[ref.to_dict() for ref in self.advisory_data1.references],
95+
date_imported=date,
96+
date_collected=date,
97+
created_by="test_pipeline",
98+
)
6599

66-
@pytest.mark.django_db
67-
def test_vulnerability_pipes_importer_import_advisory_different_pipelines():
68-
advisory1 = get_advisory1(created_by="test_importer_pipeline")
69-
import_advisory(advisory=advisory1, pipeline_id="test_importer1_pipeline")
70-
all_vulnerability_relation_objects = get_all_vulnerability_relationships_objects()
71-
import_advisory(advisory=advisory1, pipeline_id="test_importer2_pipeline")
72-
assert all_vulnerability_relation_objects == get_all_vulnerability_relationships_objects()
100+
def test_advisory_insert_without_content_id(self):
101+
with self.assertRaises(ValidationError):
102+
date = datetime.now()
103+
models.Advisory.objects.create(
104+
url=self.advisory_data1.url,
105+
summary=self.advisory_data1.summary,
106+
affected_packages=[pkg.to_dict() for pkg in self.advisory_data1.affected_packages],
107+
references=[ref.to_dict() for ref in self.advisory_data1.references],
108+
date_imported=date,
109+
date_collected=date,
110+
created_by="test_pipeline",
111+
)
73112

113+
def test_advisory_insert_no_duplicate_content_id(self):
114+
date = datetime.now()
115+
models.Advisory.objects.create(
116+
unique_content_id=compute_content_id(advisory_data=self.advisory_data1),
117+
url=self.advisory_data1.url,
118+
summary=self.advisory_data1.summary,
119+
affected_packages=[pkg.to_dict() for pkg in self.advisory_data1.affected_packages],
120+
references=[ref.to_dict() for ref in self.advisory_data1.references],
121+
date_imported=date,
122+
date_collected=date,
123+
created_by="test_pipeline",
124+
)
74125

75-
@pytest.mark.django_db
76-
def test_vulnerability_pipes_get_or_create_aliases():
77-
aliases = ["CVE-TEST-123", "CVE-TEST-124"]
78-
result_aliases_qs = get_or_create_aliases(aliases=aliases)
79-
result_aliases = [i.alias for i in result_aliases_qs]
80-
assert 2 == result_aliases_qs.count()
81-
assert "CVE-TEST-123" in result_aliases
82-
assert "CVE-TEST-124" in result_aliases
126+
with self.assertRaises(ValidationError):
127+
models.Advisory.objects.create(
128+
unique_content_id=compute_content_id(advisory_data=self.advisory_data1),
129+
url=self.advisory_data1.url,
130+
summary=self.advisory_data1.summary,
131+
affected_packages=[pkg.to_dict() for pkg in self.advisory_data1.affected_packages],
132+
references=[ref.to_dict() for ref in self.advisory_data1.references],
133+
date_imported=date,
134+
date_collected=date,
135+
created_by="test_pipeline",
136+
)

vulnerabilities/tests/test_add_cvsssv31.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ def setUp(self):
2525
advisory = Advisory.objects.create(
2626
created_by="nvd_importer",
2727
unique_content_id="test-unique-content-id",
28+
url="https://nvd.nist.gov/vuln/detail/CVE-2024-1234",
2829
references=[
2930
{
3031
"severities": [

vulnerabilities/tests/test_import_runner.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ def test_advisory_summary_clean_up():
179179

180180
DUMMY_ADVISORY = models.Advisory(
181181
unique_content_id="test-unique-content-id",
182+
url="https://test.url/",
182183
summary="dummy",
183184
created_by="tests",
184185
date_collected=timezone.now(),

0 commit comments

Comments
 (0)