@@ -179,19 +179,29 @@ def get_vendor(self, product: str) -> list:
179179 vendorlist .append ("UNKNOWN" )
180180 return vendorlist
181181
182- def is_valid_purl (self , purl_string : str ) :
182+ def is_valid_string (self , string_type : str , ref_string : str ) -> bool :
183183 """
184- Validate the PURL string is the correct form.
184+ Validate the PURL, CPE string is the correct form.
185185
186186 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)
188189
189190 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.
191192
192193 """
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
195205
196206 def parse_sbom (self ) -> [(str , str , str )]:
197207 """
@@ -271,14 +281,16 @@ def parse_ext_ref(self, ext_ref) -> (str | None, str | None, str | None):
271281 """
272282 decoded = {}
273283 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 )
276288
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 )
279291
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 )
282294
283295 # No ext-ref matches, return none
284296 return decoded .get (
@@ -298,6 +310,7 @@ def decode_cpe22(self, cpe22) -> (str | None, str | None, str | None):
298310 information extracted from the CPE 2.2 string, or None if the information is incomplete.
299311
300312 """
313+
301314 cpe = cpe22 .split (":" )
302315 vendor , product , version = cpe [2 ], cpe [3 ], cpe [4 ]
303316 # Return available data, convert empty fields to None
@@ -315,6 +328,7 @@ def decode_cpe23(self, cpe23) -> (str | None, str | None, str | None):
315328 information extracted from the CPE 2.3 string, or None if the information is incomplete.
316329
317330 """
331+
318332 cpe = cpe23 .split (":" )
319333 vendor , product , version = cpe [3 ], cpe [4 ], cpe [5 ]
320334 # Return available data, convert empty fields to None
@@ -335,10 +349,9 @@ def decode_purl(self, purl) -> (str | None, str | None, str | None):
335349 vendor = None # Because the vendor and product identifiers in the purl don't always align
336350 product = None # with the CVE DB, only the version is parsed.
337351 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" )
342355
343356 return [vendor or None , product or None , version or None ]
344357
0 commit comments