diff --git a/pyproject.toml b/pyproject.toml index afee8ee..9409ea1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "appthreat-vulnerability-db" -version = "6.0.5" +version = "6.0.6" description = "AppThreat's vulnerability database and package search library with a built-in sqlite based storage. OSV, CVE, GitHub, npm are the primary sources of vulnerabilities." authors = [ {name = "Team AppThreat", email = "cloud@appthreat.com"}, diff --git a/test/test_utils.py b/test/test_utils.py index 4c55d20..a7f484d 100644 --- a/test/test_utils.py +++ b/test/test_utils.py @@ -1,4 +1,4 @@ -from vdb.lib import utils as utils +from vdb.lib import utils def test_normalise(): @@ -225,7 +225,7 @@ def test_version_build_compare(): def test_version_build_compare1(): - sver, srest = utils.convert_to_semver("2.1.5.1-r3") + sver, _ = utils.convert_to_semver("2.1.5.1-r3") assert sver res = utils.version_compare("2.1.5.1-r3", "1.2.1-r0", "2.1.5.1-r1") assert not res @@ -631,7 +631,7 @@ def test_redhat_build_compare(): def test_parse_uri(): - vendor, package, version, cve_type = utils.parse_cpe( + vendor, package, version, _ = utils.parse_cpe( "cpe:2.3:o:google:android:9.0:*:*:*:*:*:*:*" ) assert vendor == "google" @@ -888,6 +888,18 @@ def test_purl_vers_convert(): ], "vers:deb/53.5", ), + ( + "generic", + [ + { + "version": "0.0.0", + "status": "affected", + "versionType": "generic", + "lessThan": "001a3278b5572e52c0ecac0bd1157bf2599502b7", + } + ], + "vers:generic/<001a3278b5572e52c0ecac0bd1157bf2599502b7", + ), ] for tt in test_tuples: assert utils.to_purl_vers(tt[0], tt[1]) == tt[2] @@ -992,6 +1004,16 @@ def test_url_to_purl(): "qualifiers": None, "subpath": None, } + assert utils.url_to_purl( + "https://www.github.com/kiwitcms/kiwi/commit/ffb00450be52fe11a82a2507632c2328cae4ec9d" + ) == { + "type": "github", + "namespace": "kiwitcms", + "name": "kiwi", + "version": "ffb00450be52fe11a82a2507632c2328cae4ec9d", + "qualifiers": None, + "subpath": None, + } def test_vers_compare(): diff --git a/vdb/lib/utils.py b/vdb/lib/utils.py index bbc4347..24edfb2 100644 --- a/vdb/lib/utils.py +++ b/vdb/lib/utils.py @@ -59,8 +59,11 @@ def __init__(self, msg): def load(d): - """Parses a python object from a JSON string. Every Object which should be loaded needs a constuctor that doesn't need any Arguments. - Arguments: Dict object; the module which contains the class, the parsed object is instance of. + """ + Parses a python object from a JSON string. + Every Object which should be loaded needs a constuctor that doesn't need any Arguments. + Arguments: Dict object; the module which contains the class, + the parsed object is instance of. """ def _load(d1): @@ -610,9 +613,11 @@ def version_compare( return False if mae: if VersionInfo.is_valid(compare_ver) and VersionInfo.is_valid(mae): - cmp_value = VersionInfo.parse(compare_ver, optional_minor_and_patch=True).compare(mae) + cmp_value = VersionInfo.parse( + compare_ver, optional_minor_and_patch=True + ).compare(mae) return cmp_value < 0 - elif "." not in compare_ver and "." not in mae: + if "." not in compare_ver and "." not in mae: compare_ver = re.split(r"[+~]", compare_ver)[0] mae = re.split(r"[+~]", mae)[0] exnum = list(filter(str.isdigit, compare_ver)) @@ -651,8 +656,12 @@ def version_compare( # Perform semver match once we have all the required versions if compare_ver and min_version and max_version: if semver_compatible(compare_ver, min_version, max_version): - min_value = VersionInfo.parse(compare_ver, optional_minor_and_patch=True).compare(min_version) - max_value = VersionInfo.parse(compare_ver, optional_minor_and_patch=True).compare(max_version) + min_value = VersionInfo.parse( + compare_ver, optional_minor_and_patch=True + ).compare(min_version) + max_value = VersionInfo.parse( + compare_ver, optional_minor_and_patch=True + ).compare(max_version) min_check = min_value > 0 if is_min_exclude else min_value >= 0 max_check = max_value < 0 if is_max_exclude else max_value <= 0 return min_check and max_check @@ -1099,7 +1108,11 @@ def to_purl_vers(vendor: str, versions: list) -> str: else: vers_list.append(f">={version}") if less_than and less_than != "*" and not less_than_or_equal: - vers_list.append(f"<{less_than}") + # Fix for #142 + if version == "0.0.0" and check_hex(less_than): + vers_list = [f"<{less_than}"] + else: + vers_list.append(f"<{less_than}") if not less_than and less_than_or_equal: if less_than_or_equal == "*": vers_list.append("*") @@ -1152,9 +1165,10 @@ def url_to_purl(url: str) -> dict | None: url_obj = urlparse(f"https://{git_repo_name}") # Fix for #112 pkg_type = "generic" - hostname = url_obj.hostname - if url_obj.hostname in ("github.com", "gitlab.com"): - pkg_type = url_obj.hostname.removesuffix(".com") + # Fix for #143 + hostname = url_obj.hostname.removeprefix("www.") + if hostname in ("github.com", "gitlab.com"): + pkg_type = hostname.removesuffix(".com") git_repo_name = url_obj.path hostname = None # Filter repo names without a path