Skip to content

Commit 8087b86

Browse files
authored
feat: added PURL generation for swift parser (#3957)
Signed-off-by: Meet Soni <[email protected]>
1 parent 851f30e commit 8087b86

File tree

1 file changed

+61
-4
lines changed

1 file changed

+61
-4
lines changed

cve_bin_tool/parsers/swift.py

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,80 @@
22
# SPDX-License-Identifier: GPL-3.0-or-later
33

44
import json
5+
import re
6+
from json.decoder import JSONDecodeError
7+
from urllib.parse import urlparse
58

69
from cve_bin_tool.parsers import Parser
710

811

912
class SwiftParser(Parser):
13+
"""
14+
Parser implementation for Swift dependency files (Package.resolved).
15+
16+
This parser is designed to parse Swift dependencies files and generate Package URL (PURL) strings
17+
based on the modules and their dependencies listed in the file.
18+
19+
Attributes:
20+
cve_db (CVEDB): The CVE database instance used for vulnerability information.
21+
logger (Logger): The logger instance for logging messages and debugging information.
22+
23+
Methods:
24+
generate_purl(product, version, vendor):
25+
Generates PURL after normalizing all components.
26+
run_checker(filename):
27+
Parse the Swift dependency file and yield valid PURLs for the modules listed in the file.
28+
29+
"""
30+
1031
def __init__(self, cve_db, logger):
1132
super().__init__(cve_db, logger)
33+
self.purl_pkg_type = "swift"
34+
35+
def generate_purl(self, product, version, vendor, qualifier={}, subpath=None):
36+
"""Generates PURL after normalizing all components."""
37+
38+
product = re.sub(r"[^a-zA-Z0-9_-]", "", product)
39+
version = re.sub(r"[^a-zA-Z0-9.+-]", "", version)
40+
41+
if not re.match(r"[a-zA-Z0-9_-]", product):
42+
return
43+
if not vendor:
44+
vendor = "UNKNOWN"
45+
if not version:
46+
version = "UNKNOWN"
47+
48+
purl = super().generate_purl(
49+
product,
50+
version,
51+
vendor,
52+
qualifier,
53+
subpath,
54+
)
55+
56+
return purl
1257

1358
def run_checker(self, filename):
59+
"""Parse the file and yield valid PURLs."""
1460
self.filename = filename
1561
with open(self.filename) as fh:
1662
# parse the json structure for extracting product version pairs
17-
content = json.load(fh)
63+
try:
64+
content = json.load(fh)
65+
except JSONDecodeError as e:
66+
self.logger.debug(f"Error occurred while parsing {filename}: {e}")
67+
return
1868
for package in content["object"]["pins"]:
1969
product = package["package"]
2070
version = package["state"]["version"]
21-
vendor = self.find_vendor(product, version)
22-
if vendor is not None:
23-
yield from vendor
71+
repository_url = package.get("repositoryURL", None)
72+
domain = None
73+
if repository_url:
74+
parse = urlparse(repository_url)
75+
domain = parse.netloc
76+
self.logger.debug(domain)
77+
78+
vendors = self.find_vendor(product, version)
79+
if vendors is not None:
80+
yield from vendors
2481
self.logger.debug(f"Done scanning file: {self.filename}")

0 commit comments

Comments
 (0)