Skip to content

Commit 51b5659

Browse files
committed
Add support for ref cpes & fix the tests
Ignore affected packages Signed-off-by: ziadhany <[email protected]>
1 parent def0a87 commit 51b5659

File tree

4 files changed

+199
-162
lines changed

4 files changed

+199
-162
lines changed

vulnerabilities/importers/vulnrichment.py

Lines changed: 24 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,21 @@
11
import json
22
import logging
33
import re
4-
from datetime import datetime
54
from pathlib import Path
65
from typing import Iterable
7-
from typing import List
8-
from typing import Optional
96

107
import dateparser
11-
from packageurl import PackageURL
12-
from univers.version_constraint import VersionConstraint
13-
from univers.version_range import RANGE_CLASS_BY_SCHEMES
14-
from univers.version_range import VersionRange
15-
from univers.versions import AlpineLinuxVersion
16-
from univers.versions import ArchLinuxVersion
17-
from univers.versions import ComposerVersion
18-
from univers.versions import DebianVersion
19-
from univers.versions import GenericVersion
20-
from univers.versions import GentooVersion
21-
from univers.versions import GolangVersion
22-
from univers.versions import InvalidVersion
23-
from univers.versions import LegacyOpensslVersion
24-
from univers.versions import MavenVersion
25-
from univers.versions import NginxVersion
26-
from univers.versions import NugetVersion
27-
from univers.versions import OpensslVersion
28-
from univers.versions import PypiVersion
29-
from univers.versions import RpmVersion
30-
from univers.versions import SemverVersion
31-
from univers.versions import Version
328

339
from vulnerabilities.importer import AdvisoryData
34-
from vulnerabilities.importer import AffectedPackage
3510
from vulnerabilities.importer import Importer
3611
from vulnerabilities.importer import Reference
3712
from vulnerabilities.importer import VulnerabilitySeverity
3813
from vulnerabilities.severity_systems import SCORING_SYSTEMS
39-
from vulnerabilities.utils import build_description
40-
from vulnerabilities.utils import dedupe
4114
from vulnerabilities.utils import get_advisory_url
4215
from vulnerabilities.utils import get_cwe_id
4316

4417
logger = logging.getLogger(__name__)
4518

46-
VULNRICH_VERSION_CLASS_SCHEMES = {
47-
"semver": SemverVersion,
48-
"python": PypiVersion,
49-
"custom": GenericVersion,
50-
"rpm": RpmVersion,
51-
"maven": MavenVersion,
52-
}
53-
5419

5520
class VulnrichImporter(Importer):
5621
spdx_license_expression = "CC0-1.0"
@@ -88,76 +53,14 @@ def parse_cve_advisory(raw_data, advisory_url):
8853
state = cve_metadata.get("state")
8954

9055
date_published = cve_metadata.get("datePublished")
91-
date_published = dateparser.parse(date_published)
56+
if date_published:
57+
date_published = dateparser.parse(date_published)
9258

9359
# Extract containers
9460
containers = raw_data.get("containers", {})
9561
cna_data = containers.get("cna", {})
9662
adp_data = containers.get("adp", {})
9763

98-
# Extract affected products
99-
affected_packages = []
100-
for affected_product in cna_data.get("affected", []):
101-
if type(affected_product) != dict:
102-
continue
103-
cpes = affected_product.get("cpes") # TODO Add references cpes
104-
105-
vendor = affected_product.get("vendor") or ""
106-
collection_url = affected_product.get("collectionURL") or ""
107-
product = affected_product.get("product") or ""
108-
package_name = affected_product.get("packageName") or ""
109-
110-
platforms = affected_product.get("platforms", [])
111-
default_status = affected_product.get("defaultStatus")
112-
113-
affected_packages = []
114-
# purl (vendor, collection_url, product, package_name, platforms)
115-
purl = PackageURL(
116-
type=vendor,
117-
name=product,
118-
namespace=package_name,
119-
)
120-
121-
versions = affected_product.get("versions", [])
122-
for version_data in versions:
123-
# version ≤ V ≤ (lessThanOrEqual/lessThan)
124-
# right_version ≤ V ≤ left_version
125-
version_constraints = []
126-
r_version = version_data.get("version")
127-
version_type = version_data.get("versionType")
128-
version_class = VULNRICH_VERSION_CLASS_SCHEMES.get(version_type)
129-
if not version_class:
130-
logger.error(f"Invalid version_class type: {version_type}")
131-
continue
132-
133-
l_version, l_comparator = None, ""
134-
if "lessThan" in version_data:
135-
l_version = version_data.get("lessThan")
136-
l_comparator = "<"
137-
elif "lessThanOrEqual" in version_data:
138-
l_version = version_data.get("lessThanOrEqual")
139-
l_comparator = "<="
140-
try:
141-
if l_version and l_comparator:
142-
version_constraints.append(
143-
VersionConstraint(comparator=l_comparator, version=version_class(l_version))
144-
)
145-
if r_version:
146-
version_constraints.append(
147-
VersionConstraint(comparator=">", version=version_class(r_version))
148-
)
149-
except InvalidVersion:
150-
logger.error(f"InvalidVersion: {l_version}-{r_version}")
151-
continue
152-
153-
affected_packages.append(
154-
AffectedPackage(
155-
purl,
156-
affected_version_range=VersionRange(constraints=version_constraints),
157-
)
158-
)
159-
status = version_data.get("status")
160-
16164
# Extract descriptions
16265
summary = ""
16366
description_list = cna_data.get("descriptions", [])
@@ -204,35 +107,49 @@ def parse_cve_advisory(raw_data, advisory_url):
204107
)
205108
severities.append(severity)
206109

207-
# Extract references
110+
# Extract references cpes and ignore affected products
111+
cpes = set()
112+
for affected_product in cna_data.get("affected", []):
113+
if type(affected_product) != dict:
114+
continue
115+
cpes.update(affected_product.get("cpes") or []) # TODO Add references cpes
116+
208117
# TODO ADD reference type
209118
references = [
210119
Reference(url=ref.get("url"), severities=severities)
211120
for ref in cna_data.get("references", [])
212121
]
213122

214-
weaknesses = []
123+
cpes_ref = [
124+
Reference(
125+
reference_id=cpe,
126+
url=f"https://nvd.nist.gov/vuln/search/results?adv_search=true&isCpeNameSearch=true&query={cpe}",
127+
)
128+
for cpe in sorted(list(cpes))
129+
]
130+
references.extend(cpes_ref)
131+
132+
weaknesses = set()
215133
for problem_type in cna_data.get("problemTypes", []):
216134
descriptions = problem_type.get("descriptions", [])
217135
for description in descriptions:
218136
cwe_id = description.get("cweId")
219137
if cwe_id:
220-
weaknesses.append(get_cwe_id(cwe_id))
138+
weaknesses.add(get_cwe_id(cwe_id))
221139

222140
description_text = description.get("description")
223141
if description_text:
224-
pattern = r"CWE-(\d{3})"
142+
pattern = r"CWE-(\d+)"
225143
match = re.search(pattern, description_text)
226144
if match:
227-
weaknesses.append(match.group(1))
145+
weaknesses.add(int(match.group(1)))
228146

229147
return AdvisoryData(
230148
aliases=[cve_id],
231149
summary=summary,
232-
affected_packages=affected_packages,
233150
references=references,
234-
# date_published=dateparser.parse(self.cve_item.get("publishedDate")),
235-
weaknesses=weaknesses,
151+
date_published=date_published,
152+
weaknesses=list(weaknesses),
236153
url=advisory_url,
237154
)
238155

vulnerabilities/tests/test_data/vulnrichment/vulnrichment-data1-expected.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
]
3939
}
4040
],
41-
"date_published": null,
41+
"date_published": "2024-03-30T11:17:25.675000+00:00",
4242
"weaknesses": [
4343
"502"
4444
],

0 commit comments

Comments
 (0)