Skip to content

Commit 5847f65

Browse files
committed
Add pipeline for adding advisory ID and tests
Signed-off-by: Tushar Goel <tushar.goel.dav@gmail.com>
1 parent 23a1989 commit 5847f65

17 files changed

+131
-22
lines changed

vulnerabilities/importer.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ def get_advisory_id(self, aliases: list[str]) -> str:
382382
Return the Advisory ID for the given aliases.
383383
"""
384384
raise NotImplementedError
385-
385+
386386
def get_cve_id(self, aliases: list[str]) -> str:
387387
"""
388388
Return the CVE ID for the given aliases.

vulnerabilities/importers/apache_kafka.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ class ApacheKafkaImporter(Importer):
101101
def fetch_advisory_page(self):
102102
page = requests.get(self.GH_PAGE_URL)
103103
return page.content
104-
104+
105105
def get_advisory_id(self, aliases: list[str]) -> str:
106106
"""
107107
Return the Advisory ID for the given aliases.

vulnerabilities/importers/elixir_security.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def advisory_data(self) -> Set[AdvisoryData]:
4040
finally:
4141
if self.vcs_response:
4242
self.vcs_response.delete()
43-
43+
4444
def get_advisory_id(self, aliases: list[str]) -> str:
4545
"""
4646
Return the Advisory ID for the given aliases.

vulnerabilities/importers/postgresql.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def get_advisory_id(self, aliases: list[str]) -> str:
3434
"""
3535
Return the Advisory ID for the given aliases.
3636
"""
37-
return self.get_cve_id(aliases)
37+
return self.get_cve_id(aliases)
3838

3939
def advisory_data(self):
4040
known_urls = {self.root_url}

vulnerabilities/importers/retiredotnet.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def advisory_data(self) -> Iterable[AdvisoryData]:
4343
finally:
4444
if self.vcs_response:
4545
self.vcs_response.delete()
46-
46+
4747
def get_advisory_id(self, aliases: list[str]) -> str:
4848
"""
4949
Return the Advisory ID for the given aliases.

vulnerabilities/importers/ruby.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ def advisory_data(self) -> Iterable[AdvisoryData]:
7171
finally:
7272
if self.vcs_response:
7373
self.vcs_response.delete()
74-
74+
7575
def get_advisory_id(self, aliases: list[str]) -> str:
7676
"""
7777
Return the Advisory ID for the given aliases.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Generated by Django 4.2.17 on 2025-03-28 06:22
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
("vulnerabilities", "0090_migrate_advisory_aliases"),
10+
]
11+
12+
operations = [
13+
migrations.AddField(
14+
model_name="advisory",
15+
name="advisory_id",
16+
field=models.CharField(
17+
blank=True,
18+
help_text="An advisory id, such as CVE-123-345 when available",
19+
max_length=100,
20+
),
21+
),
22+
]

vulnerabilities/models.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1323,6 +1323,16 @@ class Advisory(models.Model):
13231323
null=False,
13241324
help_text="A 64 character unique identifier for the content of the advisory since we use sha256 as hex",
13251325
)
1326+
1327+
advisory_id = models.CharField(
1328+
max_length=100,
1329+
blank=True,
1330+
help_text="An advisory id, such as CVE-123-345 when available",
1331+
)
1332+
url = models.URLField(
1333+
blank=True,
1334+
help_text="Link to the advisory on the upstream website",
1335+
)
13261336
aliases = models.ManyToManyField(
13271337
Alias,
13281338
through="AdvisoryRelatedAlias",
@@ -1354,10 +1364,6 @@ class Advisory(models.Model):
13541364
"module name importing the advisory. Eg:"
13551365
"vulnerabilities.pipeline.nginx_importer.NginxImporterPipeline",
13561366
)
1357-
url = models.URLField(
1358-
blank=True,
1359-
help_text="Link to the advisory on the upstream website",
1360-
)
13611367

13621368
objects = AdvisoryQuerySet.as_manager()
13631369

vulnerabilities/pipelines/__init__.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -131,14 +131,16 @@ def collect_advisories(self) -> Iterable[AdvisoryData]:
131131
Populate the `self.collected_advisories_count` field and yield AdvisoryData
132132
"""
133133
raise NotImplementedError
134-
135-
def get_advisory_id(self, aliases: list[str]) -> str:
134+
135+
@classmethod
136+
def get_advisory_id(cls, aliases: list[str]) -> str:
136137
"""
137138
Return the Advisory ID for the given aliases.
138139
"""
139140
raise NotImplementedError
140-
141-
def get_cve_id(self, aliases: list[str]) -> str:
141+
142+
@classmethod
143+
def get_cve_id(cls, aliases: list[str]) -> str:
142144
"""
143145
Return the CVE ID for the given aliases.
144146
"""
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Copyright (c) nexB Inc. and others. All rights reserved.
2+
# VulnerableCode is a trademark of nexB Inc.
3+
# SPDX-License-Identifier: Apache-2.0
4+
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
5+
# See https://github.com/aboutcode-org/vulnerablecode for support or download.
6+
# See https://aboutcode.org for more information about nexB OSS projects.
7+
#
8+
9+
from aboutcode.pipeline import LoopProgress
10+
from django.db import transaction
11+
12+
from vulnerabilities.importers import IMPORTERS_REGISTRY
13+
from vulnerabilities.models import Advisory
14+
from vulnerabilities.models import Alias
15+
from vulnerabilities.pipelines import VulnerableCodePipeline
16+
17+
18+
class AddAdvisoryID(VulnerableCodePipeline):
19+
"""
20+
Pipeline to map CVEs from VulnerabilitySeverity to corresponding Advisories with CVSS3.1 scores.
21+
"""
22+
23+
pipeline_id = "add_advisory_id"
24+
25+
@classmethod
26+
def steps(cls):
27+
return (cls.add_advisory_id,)
28+
29+
def add_advisory_id(self):
30+
31+
advisories = Advisory.objects.all()
32+
33+
advisories_to_update = []
34+
35+
batch_size = 500
36+
37+
progress = LoopProgress(total_iterations=advisories.count(), logger=self.log)
38+
39+
for advisory in progress.iter(advisories.iterator(chunk_size=batch_size)):
40+
importer_name = advisory.created_by
41+
aliases = Alias.objects.filter(advisories=advisory).values_list("alias", flat=True)
42+
advisory_id = IMPORTERS_REGISTRY[importer_name].get_advisory_id(aliases=aliases)
43+
advisory.advisory_id = advisory_id
44+
advisories_to_update.append(advisory)
45+
if len(advisories_to_update) >= batch_size:
46+
self.do_bulk_update(advisories_to_update)
47+
advisories_to_update = []
48+
self.do_bulk_update(advisories_to_update)
49+
self.log(f"Pipeline [{self.pipeline_name}] completed.")
50+
51+
def do_bulk_update(self, advisories_to_update):
52+
Advisory.objects.bulk_update(advisories_to_update, ["advisory_id"])
53+
self.log(f"Updated {len(advisories_to_update)} advisories with advisory_id.")

0 commit comments

Comments
 (0)