Skip to content

Commit e863019

Browse files
committed
Add proper method to update and set the risk_score
Signed-off-by: tdruez <[email protected]>
1 parent fc61ad3 commit e863019

File tree

3 files changed

+48
-9
lines changed

3 files changed

+48
-9
lines changed

product_portfolio/models.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -756,7 +756,7 @@ def update_license_unknown(self):
756756
product_package.update_license_unknown()
757757

758758
def annotate_weighted_risk_score(self):
759-
"""Annotate the Queeryset with the weighted_risk_score computed value."""
759+
"""Annotate the Queryset with the weighted_risk_score computed value."""
760760
purpose = ProductItemPurpose.objects.filter(productpackage=OuterRef("pk"))
761761
package = Package.objects.filter(productpackages=OuterRef("pk"))
762762

vulnerabilities/models.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,15 @@ class Meta:
428428
def is_vulnerable(self):
429429
return self.affected_by_vulnerabilities.exists()
430430

431+
def update_risk_score(self):
432+
"""Calculate and save the maximum risk score from all affected vulnerabilities."""
433+
qs = self.affected_by_vulnerabilities.aggregate(models.Max("risk_score"))
434+
max_score = qs["risk_score__max"]
435+
436+
self.risk_score = max_score
437+
self.save(update_fields=["risk_score"])
438+
return self.risk_score
439+
431440
def get_entry_for_package(self, vulnerablecode):
432441
if not self.package_url:
433442
return
@@ -495,8 +504,7 @@ def create_vulnerabilities(self, vulnerabilities_data):
495504
through_defaults = {"dataspace_id": self.dataspace_id}
496505
self.affected_by_vulnerabilities.add(*vulnerabilities, through_defaults=through_defaults)
497506

498-
# TODO: Looks like a bug....
499-
self.update(risk_score=vulnerability_data["risk_score"])
507+
self.update_risk_score()
500508
if isinstance(self, Package):
501509
self.productpackages.update_weighted_risk_score()
502510

vulnerabilities/tests/test_models.py

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,19 +82,50 @@ def test_vulnerability_mixin_create_vulnerabilities(self):
8282
response_file = self.data / "vulnerabilities" / "idna_3.6_response.json"
8383
response_json = json.loads(response_file.read_text())
8484
vulnerabilities_data = response_json["results"][0]["affected_by_vulnerabilities"]
85+
vulnerabilities_data.append({"vulnerability_id": "VCID-0002", "risk_score": 5.0})
8586

8687
package1 = make_package(self.dataspace, package_url="pkg:pypi/[email protected]")
8788
product1 = make_product(self.dataspace, inventory=[package1])
8889
package1.create_vulnerabilities(vulnerabilities_data)
8990

90-
self.assertEqual(1, Vulnerability.objects.scope(self.dataspace).count())
91-
self.assertEqual(1, package1.affected_by_vulnerabilities.count())
92-
vulnerability = package1.affected_by_vulnerabilities.get()
93-
self.assertEqual("VCID-j3au-usaz-aaag", vulnerability.vulnerability_id)
94-
95-
self.assertEqual(8.4, package1.risk_score)
91+
self.assertEqual(2, Vulnerability.objects.scope(self.dataspace).count())
92+
self.assertEqual("8.4", str(package1.risk_score))
9693
self.assertEqual("8.4", str(product1.productpackages.get().weighted_risk_score))
9794

95+
def test_vulnerability_mixin_update_risk_score(self):
96+
package1 = make_package(self.dataspace)
97+
98+
# Test with no vulnerabilities
99+
package1.update_risk_score()
100+
self.assertIsNone(package1.risk_score)
101+
102+
# Test with one vulnerability with risk score
103+
vulnerability1 = make_vulnerability(dataspace=self.dataspace, risk_score=7.5)
104+
vulnerability1.add_affected(package1)
105+
package1.update_risk_score()
106+
self.assertEqual("7.5", str(package1.risk_score))
107+
108+
# Test with multiple vulnerabilities, should use max
109+
vulnerability2 = make_vulnerability(dataspace=self.dataspace, risk_score=9.2)
110+
vulnerability2.add_affected(package1)
111+
package1.update_risk_score()
112+
self.assertEqual("9.2", str(package1.risk_score))
113+
114+
# Test with vulnerability with lower risk score, should keep max
115+
vulnerability3 = make_vulnerability(dataspace=self.dataspace, risk_score=3.1)
116+
vulnerability3.add_affected(package1)
117+
package1.update_risk_score()
118+
self.assertEqual("9.2", str(package1.risk_score))
119+
120+
# Test with all vulnerabilities having NULL risk scores
121+
package2 = make_package(self.dataspace)
122+
vulnerability4 = make_vulnerability(dataspace=self.dataspace, risk_score=None)
123+
vulnerability5 = make_vulnerability(dataspace=self.dataspace, risk_score=None)
124+
vulnerability4.add_affected(package2)
125+
vulnerability5.add_affected(package2)
126+
package2.update_risk_score()
127+
self.assertIsNone(package2.risk_score)
128+
98129
def test_vulnerability_model_affected_packages_m2m(self):
99130
package1 = make_package(self.dataspace)
100131
vulnerability1 = make_vulnerability(dataspace=self.dataspace, affecting=package1)

0 commit comments

Comments
 (0)