Skip to content

Commit a538b86

Browse files
committed
Resolve merge conflict
Signed-off-by: ziad hany <ziadhany2016@gmail.com>
1 parent 76782a4 commit a538b86

13 files changed

Lines changed: 67 additions & 198 deletions

vulnerabilities/importers/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
from vulnerabilities.pipelines.v2_importers import archlinux_importer as archlinux_importer_v2
4848
from vulnerabilities.pipelines.v2_importers import collect_fix_commits as collect_fix_commits_v2
4949
from vulnerabilities.pipelines.v2_importers import curl_importer as curl_importer_v2
50+
from vulnerabilities.pipelines.v2_importers import cvelistv5_importer as cvelistv5_importer_v2
5051
from vulnerabilities.pipelines.v2_importers import debian_importer as debian_importer_v2
5152
from vulnerabilities.pipelines.v2_importers import (
5253
elixir_security_importer as elixir_security_importer_v2,
@@ -92,6 +93,7 @@
9293
elixir_security_importer_v2.ElixirSecurityImporterPipeline,
9394
npm_importer_v2.NpmImporterPipeline,
9495
vulnrichment_importer_v2.VulnrichImporterPipeline,
96+
cvelistv5_importer_v2.CVEListV5ImporterPipeline,
9597
apache_httpd_v2.ApacheHTTPDImporterPipeline,
9698
pypa_importer_v2.PyPaImporterPipeline,
9799
gitlab_importer_v2.GitLabImporterPipeline,

vulnerabilities/importers/cve_schema.py renamed to vulnerabilities/pipelines/v2_importers/cve_schema.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
import dateparser
1313

14-
from vulnerabilities.importer import AdvisoryData
14+
from vulnerabilities.importer import AdvisoryDataV2
1515
from vulnerabilities.importer import ReferenceV2
1616
from vulnerabilities.importer import VulnerabilitySeverity
1717
from vulnerabilities.models import VulnerabilityReference
@@ -21,9 +21,10 @@
2121
from vulnerabilities.utils import ssvc_calculator
2222

2323

24-
def parse_cve_v5_advisory(raw_data, advisory_url):
24+
def parse_cve_advisory(raw_data, advisory_url):
2525
cve_metadata = raw_data.get("cveMetadata", {})
2626
cve_id = cve_metadata.get("cveId")
27+
state = cve_metadata.get("state")
2728

2829
date_published = cve_metadata.get("datePublished")
2930
if date_published:
@@ -55,7 +56,7 @@ def parse_cve_v5_advisory(raw_data, advisory_url):
5556
adp_metrics for data in adp_data for adp_metrics in data.get("metrics", [])
5657
]
5758

58-
cve_scoring_system = {
59+
vulnrichment_scoring_system = {
5960
"cvssV4_0": SCORING_SYSTEMS["cvssv4"],
6061
"cvssV3_1": SCORING_SYSTEMS["cvssv3.1"],
6162
"cvssV3_0": SCORING_SYSTEMS["cvssv3"],
@@ -67,15 +68,15 @@ def parse_cve_v5_advisory(raw_data, advisory_url):
6768

6869
for metric in metrics:
6970
for metric_type, metric_value in metric.items():
70-
if metric_type not in cve_scoring_system:
71+
if metric_type not in vulnrichment_scoring_system:
7172
continue
7273

7374
if metric_type == "other":
7475
other_types = metric_value.get("type")
7576
if other_types == "ssvc":
7677
content = metric_value.get("content", {})
7778
vector_string, decision = ssvc_calculator(content)
78-
scoring_system = cve_scoring_system[metric_type][other_types]
79+
scoring_system = vulnrichment_scoring_system[metric_type][other_types]
7980
severity = VulnerabilitySeverity(
8081
system=scoring_system, value=decision, scoring_elements=vector_string
8182
)
@@ -84,7 +85,7 @@ def parse_cve_v5_advisory(raw_data, advisory_url):
8485
else:
8586
vector_string = metric_value.get("vectorString")
8687
base_score = metric_value.get("baseScore")
87-
scoring_system = cve_scoring_system[metric_type]
88+
scoring_system = vulnrichment_scoring_system[metric_type]
8889
severity = VulnerabilitySeverity(
8990
system=scoring_system, value=base_score, scoring_elements=vector_string
9091
)
@@ -149,11 +150,11 @@ def parse_cve_v5_advisory(raw_data, advisory_url):
149150
if match:
150151
weaknesses.add(int(match.group(1)))
151152

152-
return AdvisoryData(
153+
return AdvisoryDataV2(
153154
advisory_id=cve_id,
154155
aliases=[],
155156
summary=summary,
156-
references_v2=references,
157+
references=references,
157158
date_published=date_published,
158159
weaknesses=sorted(weaknesses),
159160
url=advisory_url,

vulnerabilities/pipelines/v2_importers/cvelistv5_importer.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
from fetchcode.vcs import fetch_via_vcs
1515

1616
from vulnerabilities.importer import AdvisoryData
17-
from vulnerabilities.importers.cve_schema import parse_cve_v5_advisory
1817
from vulnerabilities.pipelines import VulnerableCodeBaseImporterPipelineV2
18+
from vulnerabilities.pipelines.v2_importers.cve_schema import parse_cve_advisory
1919
from vulnerabilities.utils import get_advisory_url
2020

2121
logger = logging.getLogger(__name__)
@@ -60,7 +60,7 @@ def collect_advisories(self) -> Iterable[AdvisoryData]:
6060

6161
with open(file) as f:
6262
raw_data = json.load(f)
63-
yield parse_cve_v5_advisory(raw_data, advisory_url)
63+
yield parse_cve_advisory(raw_data, advisory_url)
6464

6565
def clean_downloads(self):
6666
if self.vcs_response:

vulnerabilities/pipelines/v2_importers/vulnrichment_importer.py

Lines changed: 2 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,14 @@
11
import json
22
import logging
3-
import re
43
from pathlib import Path
54
from typing import Iterable
65

7-
import dateparser
86
from fetchcode.vcs import fetch_via_vcs
97

108
from vulnerabilities.importer import AdvisoryDataV2
11-
from vulnerabilities.importer import ReferenceV2
12-
from vulnerabilities.importer import VulnerabilitySeverity
13-
from vulnerabilities.models import VulnerabilityReference
149
from vulnerabilities.pipelines import VulnerableCodeBaseImporterPipelineV2
15-
from vulnerabilities.severity_systems import SCORING_SYSTEMS
10+
from vulnerabilities.pipelines.v2_importers.cve_schema import parse_cve_advisory
1611
from vulnerabilities.utils import get_advisory_url
17-
from vulnerabilities.utils import get_cwe_id
18-
from vulnerabilities.utils import get_reference_id
19-
from vulnerabilities.utils import ssvc_calculator
2012

2113
logger = logging.getLogger(__name__)
2214

@@ -63,148 +55,7 @@ def collect_advisories(self) -> Iterable[AdvisoryDataV2]:
6355
base_path=base_path,
6456
url="https://github.com/cisagov/vulnrichment/blob/develop/",
6557
)
66-
yield self.parse_cve_advisory(raw_data, advisory_url)
67-
68-
def parse_cve_advisory(self, raw_data, advisory_url):
69-
cve_metadata = raw_data.get("cveMetadata", {})
70-
cve_id = cve_metadata.get("cveId")
71-
state = cve_metadata.get("state")
72-
73-
date_published = cve_metadata.get("datePublished")
74-
if date_published:
75-
date_published = dateparser.parse(
76-
date_published,
77-
settings={
78-
"TIMEZONE": "UTC",
79-
"RETURN_AS_TIMEZONE_AWARE": True,
80-
"TO_TIMEZONE": "UTC",
81-
},
82-
)
83-
84-
# Extract containers
85-
containers = raw_data.get("containers", {})
86-
cna_data = containers.get("cna", {})
87-
adp_data = containers.get("adp", {})
88-
89-
# Extract descriptions
90-
summary = ""
91-
description_list = cna_data.get("descriptions", [])
92-
for description_dict in description_list:
93-
if not description_dict.get("lang") in ["en", "en-US"]:
94-
continue
95-
summary = description_dict.get("value")
96-
97-
# Extract metrics
98-
severities = []
99-
metrics = cna_data.get("metrics", []) + [
100-
adp_metrics for data in adp_data for adp_metrics in data.get("metrics", [])
101-
]
102-
103-
vulnrichment_scoring_system = {
104-
"cvssV4_0": SCORING_SYSTEMS["cvssv4"],
105-
"cvssV3_1": SCORING_SYSTEMS["cvssv3.1"],
106-
"cvssV3_0": SCORING_SYSTEMS["cvssv3"],
107-
"cvssV2_0": SCORING_SYSTEMS["cvssv2"],
108-
"other": {
109-
"ssvc": SCORING_SYSTEMS["ssvc"],
110-
}, # ignore kev
111-
}
112-
113-
for metric in metrics:
114-
for metric_type, metric_value in metric.items():
115-
if metric_type not in vulnrichment_scoring_system:
116-
continue
117-
118-
if metric_type == "other":
119-
other_types = metric_value.get("type")
120-
if other_types == "ssvc":
121-
content = metric_value.get("content", {})
122-
vector_string, decision = ssvc_calculator(content)
123-
scoring_system = vulnrichment_scoring_system[metric_type][other_types]
124-
severity = VulnerabilitySeverity(
125-
system=scoring_system, value=decision, scoring_elements=vector_string
126-
)
127-
severities.append(severity)
128-
# ignore kev
129-
else:
130-
vector_string = metric_value.get("vectorString")
131-
base_score = metric_value.get("baseScore")
132-
scoring_system = vulnrichment_scoring_system[metric_type]
133-
severity = VulnerabilitySeverity(
134-
system=scoring_system, value=base_score, scoring_elements=vector_string
135-
)
136-
severities.append(severity)
137-
138-
# Extract references cpes and ignore affected products
139-
cpes = set()
140-
for affected_product in cna_data.get("affected", []):
141-
if type(affected_product) != dict:
142-
continue
143-
cpes.update(affected_product.get("cpes") or [])
144-
145-
references = []
146-
for ref in cna_data.get("references", []):
147-
# https://github.com/CVEProject/cve-schema/blob/main/schema/tags/reference-tags.json
148-
# We removed all unwanted reference types and set the default reference type to 'OTHER'.
149-
ref_type = VulnerabilityReference.OTHER
150-
vul_ref_types = {
151-
"exploit": VulnerabilityReference.EXPLOIT,
152-
"issue-tracking": VulnerabilityReference.BUG,
153-
"mailing-list": VulnerabilityReference.MAILING_LIST,
154-
"third-party-advisory": VulnerabilityReference.ADVISORY,
155-
"vendor-advisory": VulnerabilityReference.ADVISORY,
156-
"vdb-entry": VulnerabilityReference.ADVISORY,
157-
}
158-
159-
for tag_type in ref.get("tags", []):
160-
if tag_type in vul_ref_types:
161-
ref_type = vul_ref_types.get(tag_type)
162-
163-
url = ref.get("url")
164-
reference = ReferenceV2(
165-
reference_id=get_reference_id(url),
166-
url=url,
167-
reference_type=ref_type,
168-
)
169-
170-
references.append(reference)
171-
172-
cpes_ref = [
173-
ReferenceV2(
174-
reference_id=cpe,
175-
reference_type=VulnerabilityReference.OTHER,
176-
url=f"https://nvd.nist.gov/vuln/search/results?adv_search=true&isCpeNameSearch=true&query={cpe}",
177-
)
178-
for cpe in sorted(list(cpes))
179-
]
180-
references.extend(cpes_ref)
181-
182-
weaknesses = set()
183-
for problem_type in cna_data.get("problemTypes", []):
184-
descriptions = problem_type.get("descriptions", [])
185-
for description in descriptions:
186-
cwe_id = description.get("cweId")
187-
if cwe_id:
188-
weaknesses.add(get_cwe_id(cwe_id))
189-
190-
description_text = description.get("description")
191-
if description_text:
192-
pattern = r"CWE-(\d+)"
193-
match = re.search(pattern, description_text)
194-
if match:
195-
weaknesses.add(int(match.group(1)))
196-
197-
return AdvisoryDataV2(
198-
advisory_id=cve_id,
199-
aliases=[],
200-
summary=summary,
201-
references=references,
202-
date_published=date_published,
203-
weaknesses=sorted(weaknesses),
204-
url=advisory_url,
205-
severities=severities,
206-
original_advisory_text=json.dumps(raw_data, indent=2, ensure_ascii=False),
207-
)
58+
yield parse_cve_advisory(raw_data, advisory_url)
20859

20960
def clean_downloads(self):
21061
if self.vcs_response:

vulnerabilities/tests/pipelines/v2_importers/test_cvelistv5_importer_v2.py

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@
1313

1414
import pytest
1515

16-
from vulnerabilities.importer import AdvisoryData
16+
from vulnerabilities.importer import AdvisoryDataV2
17+
from vulnerabilities.importer import ReferenceV2
1718
from vulnerabilities.importer import VulnerabilitySeverity
18-
from vulnerabilities.importers.cve_schema import parse_cve_v5_advisory
19+
from vulnerabilities.pipelines.v2_importers.cve_schema import parse_cve_advisory
1920
from vulnerabilities.pipelines.v2_importers.cvelistv5_importer import CVEListV5ImporterPipeline
21+
from vulnerabilities.severity_systems import Cvssv4ScoringSystem
2022

2123

2224
@pytest.fixture
@@ -98,17 +100,22 @@ def test_collect_advisories(mock_pathlib, mock_vcs_response, mock_fetch_via_vcs,
98100
with patch(
99101
"vulnerabilities.pipelines.v2_importers.cvelistv5_importer.CVEListV5ImporterPipeline"
100102
) as mock_parse:
101-
mock_parse.return_value = AdvisoryData(
103+
mock_parse.return_value = AdvisoryDataV2(
102104
advisory_id="CVE-2021-1234",
103105
summary="Sample PyPI vulnerability",
104-
references_v2=[{"url": "https://example.com"}],
106+
references=[ReferenceV2(url="https://example.com")],
105107
affected_packages=[],
106108
weaknesses=[],
107109
url="https://github.com/CVEProject/cvelistV5/blob/cves/2021/1xxx/CVE-2021-1234.json",
108110
severities=[
109111
VulnerabilitySeverity(
110-
system="cvssv4",
111-
value=7.5,
112+
system=Cvssv4ScoringSystem(
113+
identifier="cvssv4",
114+
name="CVSSv4 Base Score",
115+
url="https://www.first.org/cvss/v4-0/",
116+
notes="CVSSv4 base score and vector",
117+
),
118+
value="7.5",
112119
scoring_elements="AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
113120
)
114121
],
@@ -118,7 +125,6 @@ def test_collect_advisories(mock_pathlib, mock_vcs_response, mock_fetch_via_vcs,
118125
pipeline.clone()
119126
advisories = list(pipeline.collect_advisories())
120127

121-
# Ensure that advisories are parsed correctly
122128
assert len(advisories) == 1
123129
advisory = advisories[0]
124130
assert advisory.advisory_id == "CVE-2021-1234"
@@ -176,13 +182,13 @@ def test_parse_cve_advisory(mock_pathlib, mock_vcs_response, mock_fetch_via_vcs)
176182

177183
pipeline = CVEListV5ImporterPipeline()
178184
pipeline.clone()
179-
advisory = parse_cve_v5_advisory(raw_data, advisory_url)
185+
advisory = parse_cve_advisory(raw_data, advisory_url)
180186

181187
assert advisory.advisory_id == "CVE-2021-1234"
182188
assert advisory.summary == "Sample PyPI vulnerability"
183189
assert advisory.url == advisory_url
184190
assert len(advisory.severities) == 1
185-
assert advisory.severities[0].value == 7.5
191+
assert advisory.severities[0].value == "7.5"
186192

187193

188194
def test_collect_advisories_with_invalid_json(

0 commit comments

Comments
 (0)