Skip to content

Commit 48f1029

Browse files
committed
Resolve merge conflict
Signed-off-by: ziad hany <ziadhany2016@gmail.com>
1 parent a5ea9ed commit 48f1029

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

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

21162
def clean_downloads(self):
21263
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)