Skip to content

Commit e06acee

Browse files
committed
Migrate Xen importer
Signed-off-by: Tushar Goel <tushar.goel.dav@gmail.com>
1 parent 2eb80ba commit e06acee

20 files changed

+184
-19
lines changed

vulnerabilities/importer.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
from typing import Optional
2323
from typing import Set
2424
from typing import Tuple
25+
from typing import Union
2526

2627
import pytz
2728
from dateutil import parser as dateparser
@@ -361,6 +362,7 @@ class AdvisoryData:
361362
weaknesses: List[int] = dataclasses.field(default_factory=list)
362363
severities: List[VulnerabilitySeverity] = dataclasses.field(default_factory=list)
363364
url: Optional[str] = None
365+
original_advisory_text: Optional[str] = None
364366

365367
def __post_init__(self):
366368
if self.date_published and not self.date_published.tzinfo:

vulnerabilities/importers/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,26 +45,26 @@
4545
from vulnerabilities.pipelines.v2_importers import (
4646
elixir_security_importer as elixir_security_importer_v2,
4747
)
48-
from vulnerabilities.pipelines.v2_importers import github_importer as github_importer_v2
4948
from vulnerabilities.pipelines.v2_importers import gitlab_importer as gitlab_importer_v2
5049
from vulnerabilities.pipelines.v2_importers import npm_importer as npm_importer_v2
5150
from vulnerabilities.pipelines.v2_importers import nvd_importer as nvd_importer_v2
5251
from vulnerabilities.pipelines.v2_importers import pypa_importer as pypa_importer_v2
5352
from vulnerabilities.pipelines.v2_importers import pysec_importer as pysec_importer_v2
5453
from vulnerabilities.pipelines.v2_importers import vulnrichment_importer as vulnrichment_importer_v2
54+
from vulnerabilities.pipelines.v2_importers import xen_importer as xen_importer_v2
5555
from vulnerabilities.utils import create_registry
5656

5757
IMPORTERS_REGISTRY = create_registry(
5858
[
5959
nvd_importer_v2.NVDImporterPipeline,
6060
elixir_security_importer_v2.ElixirSecurityImporterPipeline,
61-
github_importer_v2.GitHubAPIImporterPipeline,
6261
npm_importer_v2.NpmImporterPipeline,
6362
vulnrichment_importer_v2.VulnrichImporterPipeline,
6463
apache_httpd_v2.ApacheHTTPDImporterPipeline,
6564
pypa_importer_v2.PyPaImporterPipeline,
6665
gitlab_importer_v2.GitLabImporterPipeline,
6766
pysec_importer_v2.PyPIImporterPipeline,
67+
xen_importer_v2.XenImporterPipeline,
6868
nvd_importer.NVDImporterPipeline,
6969
github_importer.GitHubAPIImporterPipeline,
7070
gitlab_importer.GitLabImporterPipeline,

vulnerabilities/importers/curl.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ def parse_advisory_data(raw_data) -> AdvisoryData:
9797
... ]
9898
... }
9999
>>> parse_advisory_data(raw_data)
100-
AdvisoryData(advisory_id='', aliases=['CVE-2024-2379'], summary='QUIC certificate check bypass with wolfSSL', affected_packages=[AffectedPackage(package=PackageURL(type='generic', namespace='curl.se', name='curl', version=None, qualifiers={}, subpath=None), affected_version_range=GenericVersionRange(constraints=(VersionConstraint(comparator='=', version=SemverVersion(string='8.6.0')),)), fixed_version=SemverVersion(string='8.7.0'))], references=[Reference(reference_id='', reference_type='', url='https://curl.se/docs/CVE-2024-2379.html', severities=[VulnerabilitySeverity(system=Cvssv3ScoringSystem(identifier='cvssv3.1', name='CVSSv3.1 Base Score', url='https://www.first.org/cvss/v3-1/', notes='CVSSv3.1 base score and vector'), value='Low', scoring_elements='', published_at=None, url=None)]), Reference(reference_id='', reference_type='', url='https://hackerone.com/reports/2410774', severities=[])], references_v2=[], date_published=datetime.datetime(2024, 3, 27, 8, 0, tzinfo=datetime.timezone.utc), weaknesses=[297], severities=[], url='https://curl.se/docs/CVE-2024-2379.json')
100+
AdvisoryData(advisory_id='', aliases=['CVE-2024-2379'], summary='QUIC certificate check bypass with wolfSSL', affected_packages=[AffectedPackage(package=PackageURL(type='generic', namespace='curl.se', name='curl', version=None, qualifiers={}, subpath=None), affected_version_range=GenericVersionRange(constraints=(VersionConstraint(comparator='=', version=SemverVersion(string='8.6.0')),)), fixed_version=SemverVersion(string='8.7.0'))], references=[Reference(reference_id='', reference_type='', url='https://curl.se/docs/CVE-2024-2379.html', severities=[VulnerabilitySeverity(system=Cvssv3ScoringSystem(identifier='cvssv3.1', name='CVSSv3.1 Base Score', url='https://www.first.org/cvss/v3-1/', notes='CVSSv3.1 base score and vector'), value='Low', scoring_elements='', published_at=None, url=None)]), Reference(reference_id='', reference_type='', url='https://hackerone.com/reports/2410774', severities=[])], references_v2=[], date_published=datetime.datetime(2024, 3, 27, 8, 0, tzinfo=datetime.timezone.utc), weaknesses=[297], severities=[], url='https://curl.se/docs/CVE-2024-2379.json', original_advisory_text=None)
101101
"""
102102

103103
affected = get_item(raw_data, "affected")[0] if len(get_item(raw_data, "affected")) > 0 else []

vulnerabilities/importers/osv.py

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

10+
import json
1011
import logging
1112
from typing import Iterable
1213
from typing import List
@@ -109,7 +110,7 @@ def parse_advisory_data(
109110

110111

111112
def parse_advisory_data_v2(
112-
raw_data: dict, supported_ecosystems, advisory_url: str
113+
raw_data: dict, supported_ecosystems, advisory_url: str, advisory_text: str
113114
) -> Optional[AdvisoryData]:
114115
"""
115116
Return an AdvisoryData build from a ``raw_data`` mapping of OSV advisory and
@@ -173,6 +174,7 @@ def parse_advisory_data_v2(
173174
date_published=date_published,
174175
weaknesses=weaknesses,
175176
url=advisory_url,
177+
original_advisory_text=advisory_text or json.dumps(raw_data, indent=2, ensure_ascii=False),
176178
)
177179

178180

vulnerabilities/improvers/__init__.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
from vulnerabilities.improvers import valid_versions
1111
from vulnerabilities.improvers import vulnerability_status
1212
from vulnerabilities.pipelines import add_cvss31_to_CVEs
13-
from vulnerabilities.pipelines import collect_commits
1413
from vulnerabilities.pipelines import compute_advisory_todo
1514
from vulnerabilities.pipelines import compute_package_risk
1615
from vulnerabilities.pipelines import compute_package_version_rank
@@ -20,7 +19,6 @@
2019
from vulnerabilities.pipelines import flag_ghost_packages
2120
from vulnerabilities.pipelines import populate_vulnerability_summary_pipeline
2221
from vulnerabilities.pipelines import remove_duplicate_advisories
23-
from vulnerabilities.pipelines.v2_improvers import collect_commits as collect_commits_v2
2422
from vulnerabilities.pipelines.v2_improvers import compute_package_risk as compute_package_risk_v2
2523
from vulnerabilities.pipelines.v2_improvers import (
2624
computer_package_version_rank as compute_version_rank_v2,
@@ -58,7 +56,6 @@
5856
enhance_with_exploitdb.ExploitDBImproverPipeline,
5957
compute_package_risk.ComputePackageRiskPipeline,
6058
compute_package_version_rank.ComputeVersionRankPipeline,
61-
collect_commits.CollectFixCommitsPipeline,
6259
add_cvss31_to_CVEs.CVEAdvisoryMappingPipeline,
6360
remove_duplicate_advisories.RemoveDuplicateAdvisoriesPipeline,
6461
populate_vulnerability_summary_pipeline.PopulateVulnerabilitySummariesPipeline,
@@ -68,7 +65,6 @@
6865
enhance_with_metasploit_v2.MetasploitImproverPipeline,
6966
compute_package_risk_v2.ComputePackageRiskPipeline,
7067
compute_version_rank_v2.ComputeVersionRankPipeline,
71-
collect_commits_v2.CollectFixCommitsPipeline,
7268
compute_advisory_todo.ComputeToDo,
7369
]
7470
)
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Generated by Django 4.2.22 on 2025-07-16 08:39
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
("vulnerabilities", "0098_alter_advisory_options_alter_advisoryalias_options_and_more"),
10+
]
11+
12+
operations = [
13+
migrations.AddField(
14+
model_name="advisoryv2",
15+
name="original_advisory_text",
16+
field=models.TextField(
17+
blank=True,
18+
help_text="Raw advisory data as collected from the upstream datasource.",
19+
null=True,
20+
),
21+
),
22+
]

vulnerabilities/models.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2744,6 +2744,12 @@ class AdvisoryV2(models.Model):
27442744
blank=True, null=True, help_text="UTC Date on which the advisory was imported"
27452745
)
27462746

2747+
original_advisory_text = models.TextField(
2748+
blank=True,
2749+
null=True,
2750+
help_text="Raw advisory data as collected from the upstream datasource.",
2751+
)
2752+
27472753
affecting_packages = models.ManyToManyField(
27482754
"PackageV2",
27492755
related_name="affected_by_advisories",

vulnerabilities/pipelines/__init__.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -303,13 +303,20 @@ def collect_and_store_advisories(self):
303303
if advisory is None:
304304
self.log("Advisory is None, skipping")
305305
continue
306-
if _obj := insert_advisory_v2(
307-
advisory=advisory,
308-
pipeline_id=self.pipeline_id,
309-
get_advisory_packages=self.get_advisory_packages,
310-
logger=self.log,
311-
):
312-
collected_advisory_count += 1
306+
try:
307+
if _obj := insert_advisory_v2(
308+
advisory=advisory,
309+
pipeline_id=self.pipeline_id,
310+
get_advisory_packages=self.get_advisory_packages,
311+
logger=self.log,
312+
):
313+
collected_advisory_count += 1
314+
except Exception as e:
315+
self.log(
316+
f"Failed to import advisory: {advisory!r} with error {e!r}:\n{traceback_format_exc()}",
317+
level=logging.ERROR,
318+
)
319+
continue
313320

314321
self.log(f"Successfully collected {collected_advisory_count:,d} advisories")
315322

vulnerabilities/pipelines/v2_importers/apache_httpd_importer.py

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

10+
import json
1011
import logging
1112
import re
1213
import urllib.parse
1314
from typing import Iterable
1415

1516
import requests
1617
from bs4 import BeautifulSoup
18+
from dateutil import parser as date_parser
1719
from packageurl import PackageURL
1820
from univers.version_constraint import VersionConstraint
1921
from univers.version_range import ApacheVersionRange
@@ -272,8 +274,11 @@ def to_advisory(self, data):
272274
versions_data.append(version_data)
273275

274276
fixed_versions = []
277+
date_published = None
275278
for timeline_object in data.get("timeline") or []:
276279
timeline_value = timeline_object.get("value")
280+
if timeline_value == "public":
281+
date_published = timeline_object.get("time")
277282
if "release" in timeline_value:
278283
split_timeline_value = timeline_value.split(" ")
279284
if "never" in timeline_value:
@@ -307,6 +312,8 @@ def to_advisory(self, data):
307312
weaknesses=weaknesses,
308313
url=reference.url,
309314
severities=severities,
315+
original_advisory_text=json.dumps(data, indent=2, ensure_ascii=False),
316+
date_published=date_parser.parse(date_published) if date_published else None,
310317
)
311318

312319
def to_version_ranges(self, versions_data, fixed_versions):

vulnerabilities/pipelines/v2_importers/elixir_security_importer.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ def process_file(self, file, base_path) -> Iterable[AdvisoryData]:
7373
advisory_url = (
7474
f"https://github.com/dependabot/elixir-security-advisories/blob/master/{relative_path}"
7575
)
76+
advisory_text = None
77+
with open(str(file)) as f:
78+
advisory_text = f.read()
79+
7680
yaml_file = load_yaml(str(file))
7781

7882
summary = yaml_file.get("description") or ""
@@ -129,4 +133,5 @@ def process_file(self, file, base_path) -> Iterable[AdvisoryData]:
129133
affected_packages=affected_packages,
130134
url=advisory_url,
131135
date_published=date_published,
136+
original_advisory_text=advisory_text or str(yaml_file),
132137
)

0 commit comments

Comments
 (0)