@@ -179,19 +179,29 @@ def get_vendor(self, product: str) -> list:
179
179
vendorlist .append ("UNKNOWN" )
180
180
return vendorlist
181
181
182
- def is_valid_purl (self , purl_string : str ) :
182
+ def is_valid_string (self , string_type : str , ref_string : str ) -> bool :
183
183
"""
184
- Validate the PURL string is the correct form.
184
+ Validate the PURL, CPE string is the correct form.
185
185
186
186
Args:
187
- - purl_string (str): Package URL string
187
+ - ref_string (str): PURL, CPE strings
188
+ - string_type (str): ref_string type. (purl, cpe22 or cpe23)
188
189
189
190
Returns:
190
- - bool: True if the purl_string parameter is a valid purl string, False otherwise.
191
+ - bool: True if the ref_string parameter is a valid purl or cpe string, False otherwise.
191
192
192
193
"""
193
- purl_pattern = r"^(?P<scheme>.+):(?P<type>.+)/(?P<namespace>.+)/(?P<name>.+)@(?P<version>.+)\??(?P<qualifiers>.*)#?(?P<subpath>.*)$"
194
- return re .match (purl_pattern , purl_string ) is not None
194
+ string_pattern : str
195
+ if string_type == "purl" :
196
+ string_pattern = r"^(?P<scheme>.+):(?P<type>.+)/(?P<namespace>.+)/(?P<name>.+)@(?P<version>.+)\??(?P<qualifiers>.*)#?(?P<subpath>.*)$"
197
+
198
+ elif string_type == "cpe23" :
199
+ string_pattern = r"^cpe:2\.3:[aho\*\-](:(((\?*|\*?)([a-zA-Z0-9\-\._]|(\\[\\\*\?\!\"#\$%&'\(\)\+,\-\.\/:;<=>@\[\]\^`\{\|}~]))+(\?*|\*?))|[\*\-])){5}(:(([a-zA-Z]{2,3}(-([a-zA-Z]{2}|[0-9]{3}))?)|[\*\-]))(:(((\?*|\*?)([a-zA-Z0-9\-\._]|(\\[\\\*\?\!\"#\$%&'\(\)\+,\-\.\/:;<=>@\[\]\^`\{\|}~]))+(\?*|\*?))|[\*\-])){4}"
200
+
201
+ elif string_type == "cpe22" :
202
+ string_pattern = r"^[c][pP][eE]:/[AHOaho]?(:[A-Za-z0-9\._\-~%]*){0,6}"
203
+
204
+ return re .match (string_pattern , ref_string ) is not None
195
205
196
206
def parse_sbom (self ) -> [(str , str , str )]:
197
207
"""
@@ -271,14 +281,16 @@ def parse_ext_ref(self, ext_ref) -> (str | None, str | None, str | None):
271
281
"""
272
282
decoded = {}
273
283
for ref in ext_ref :
274
- if ref [1 ] == "cpe23Type" :
275
- decoded ["cpe23Type" ] = self .decode_cpe23 (ref [2 ])
284
+ ref_type = ref [1 ]
285
+ ref_string = ref [2 ]
286
+ if ref_type == "cpe23Type" and self .is_valid_string ("cpe23" , ref_string ):
287
+ decoded ["cpe23Type" ] = self .decode_cpe23 (ref_string )
276
288
277
- elif ref [ 1 ] == "cpe22Type" :
278
- decoded ["cpe22Type" ] = self .decode_cpe22 (ref [ 2 ] )
289
+ elif ref_type == "cpe22Type" and self . is_valid_string ( "cpe22" , ref_string ) :
290
+ decoded ["cpe22Type" ] = self .decode_cpe22 (ref_string )
279
291
280
- elif ref [ 1 ] == "purl" :
281
- decoded ["purl" ] = self .decode_purl (ref [ 2 ] )
292
+ elif ref_type == "purl" and self . is_valid_string ( "purl" , ref_string ) :
293
+ decoded ["purl" ] = self .decode_purl (ref_string )
282
294
283
295
# No ext-ref matches, return none
284
296
return decoded .get (
@@ -298,6 +310,7 @@ def decode_cpe22(self, cpe22) -> (str | None, str | None, str | None):
298
310
information extracted from the CPE 2.2 string, or None if the information is incomplete.
299
311
300
312
"""
313
+
301
314
cpe = cpe22 .split (":" )
302
315
vendor , product , version = cpe [2 ], cpe [3 ], cpe [4 ]
303
316
# Return available data, convert empty fields to None
@@ -315,6 +328,7 @@ def decode_cpe23(self, cpe23) -> (str | None, str | None, str | None):
315
328
information extracted from the CPE 2.3 string, or None if the information is incomplete.
316
329
317
330
"""
331
+
318
332
cpe = cpe23 .split (":" )
319
333
vendor , product , version = cpe [3 ], cpe [4 ], cpe [5 ]
320
334
# Return available data, convert empty fields to None
@@ -335,10 +349,9 @@ def decode_purl(self, purl) -> (str | None, str | None, str | None):
335
349
vendor = None # Because the vendor and product identifiers in the purl don't always align
336
350
product = None # with the CVE DB, only the version is parsed.
337
351
version = None
338
- if self .is_valid_purl (purl ):
339
- # Process purl identifier
340
- purl_info = PackageURL .from_string (purl ).to_dict ()
341
- version = purl_info .get ("version" )
352
+ # Process purl identifier
353
+ purl_info = PackageURL .from_string (purl ).to_dict ()
354
+ version = purl_info .get ("version" )
342
355
343
356
return [vendor or None , product or None , version or None ]
344
357
0 commit comments