Skip to content

Commit d81ca11

Browse files
authored
feat: added PURL generation to ruby parser (#3939)
Signed-off-by: Meet Soni <[email protected]>
1 parent 8087b86 commit d81ca11

File tree

1 file changed

+47
-3
lines changed

1 file changed

+47
-3
lines changed

cve_bin_tool/parsers/ruby.py

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,54 @@
77

88

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

1356
def run_checker(self, filename):
57+
"""Parse the file and yield valid PURLs."""
1458
self.filename = filename
1559
with open(filename) as fh:
1660
lines = fh.readlines()
@@ -29,7 +73,7 @@ def run_checker(self, filename):
2973
):
3074
product = line.strip().split()[0]
3175
version = line.strip().split("(")[1][:-1]
32-
vendor = self.find_vendor(product, version)
33-
if vendor is not None:
34-
yield from vendor
76+
vendors = self.find_vendor(product, version)
77+
if vendors is not None:
78+
yield from vendors
3579
self.logger.debug(f"Done scanning file: {self.filename}")

0 commit comments

Comments
 (0)