Skip to content

feat: No Scan SOC for language parsers #5143

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
198 changes: 102 additions & 96 deletions cve_bin_tool/cli.py
Original file line number Diff line number Diff line change
@@ -822,112 +822,113 @@ def main(argv=None):
)
enabled_sources = [source_nvd] + enabled_sources

# Database update related settings
# Connect to the database
cvedb_orig = CVEDB(
sources=enabled_sources,
version_check=not version_check,
error_mode=error_mode,
)

# if OLD_CACHE_DIR (from cvedb.py) exists, print warning
if Path(OLD_CACHE_DIR).exists():
LOGGER.warning(
f"Obsolete cache dir {OLD_CACHE_DIR} is no longer needed and can be removed."
if not args["no_scan"]:
# Database update related settings
# Connect to the database
cvedb_orig = CVEDB(
sources=enabled_sources,
version_check=not version_check,
error_mode=error_mode,
)

# Check database exists if operating in offline mode.
if args["offline"] and not cvedb_orig.check_db_exists():
LOGGER.critical("Database does not exist.")
LOGGER.info(
"Consult the documentation at https://cve-bin-tool.readthedocs.io/en/latest/how_to_guides/offline.html to find out how to setup offline operation."
)
return ERROR_CODES[CVEDBNotExist]
# if OLD_CACHE_DIR (from cvedb.py) exists, print warning
if Path(OLD_CACHE_DIR).exists():
LOGGER.warning(
f"Obsolete cache dir {OLD_CACHE_DIR} is no longer needed and can be removed."
)

if args["use_mirror"] and not args["offline"]:
if (
cvedb_orig.fetch_from_mirror(
mirror=args["use_mirror"],
# Check database exists if operating in offline mode.
if args["offline"] and not cvedb_orig.check_db_exists():
LOGGER.critical("Database does not exist.")
LOGGER.info(
"Consult the documentation at https://cve-bin-tool.readthedocs.io/en/latest/how_to_guides/offline.html to find out how to setup offline operation."
)
return ERROR_CODES[CVEDBNotExist]

if args["use_mirror"] and not args["offline"]:
if (
cvedb_orig.fetch_from_mirror(
mirror=args["use_mirror"],
pubkey=args["verify"],
ignore_signature=args["ignore_sig"],
log_signature_error=args["log_signature_error"],
)
== -1
):
return ERROR_CODES[MirrorError]

# import database from JSON chopped by years
if args["import_json"] and cvedb_orig.check_db_exists():
return_code = cvedb_orig.json_to_db_wrapper(
path=args["import_json"],
pubkey=args["verify"],
ignore_signature=args["ignore_sig"],
log_signature_error=args["log_signature_error"],
)
== -1
):
return ERROR_CODES[MirrorError]

# import database from JSON chopped by years
if args["import_json"] and cvedb_orig.check_db_exists():
return_code = cvedb_orig.json_to_db_wrapper(
path=args["import_json"],
pubkey=args["verify"],
ignore_signature=args["ignore_sig"],
log_signature_error=args["log_signature_error"],
)
# And terminate operation
return return_code

# Export database as JSON chopped by years
if args["export_json"] and cvedb_orig.check_db_exists():
return_code = cvedb_orig.db_to_json(
path=args["export_json"],
private_key=args["pgp_sign"],
passphrase=args["passphrase"],
)
# And terminate operation
return return_code

# Import database if file exists
if args["import"] and Path(args["import"]).exists():
LOGGER.info(f'Import database from {args["import"]}')
cvedb_orig.copy_db(filename=args["import"], export=False)

# Export database if database exists
if args["export"] and cvedb_orig.check_db_exists():
LOGGER.info(f'Export database to {args["export"]}')
cvedb_orig.copy_db(filename=args["export"], export=True)
# And terminate operation
return 0

# Clear data if -u now is set
if db_update == "now":
cvedb_orig.clear_cached_data()
# And terminate operation
return return_code

# Export database as JSON chopped by years
if args["export_json"] and cvedb_orig.check_db_exists():
return_code = cvedb_orig.db_to_json(
path=args["export_json"],
private_key=args["pgp_sign"],
passphrase=args["passphrase"],
)
# And terminate operation
return return_code

# Import database if file exists
if args["import"] and Path(args["import"]).exists():
LOGGER.info(f'Import database from {args["import"]}')
cvedb_orig.copy_db(filename=args["import"], export=False)

# Export database if database exists
if args["export"] and cvedb_orig.check_db_exists():
LOGGER.info(f'Export database to {args["export"]}')
cvedb_orig.copy_db(filename=args["export"], export=True)
# And terminate operation
return 0

if db_update == "latest":
cvedb_orig.refresh_cache_and_update_db()
# Clear data if -u now is set
if db_update == "now":
cvedb_orig.clear_cached_data()

if db_update == "latest":
cvedb_orig.refresh_cache_and_update_db()

# update db if needed
if db_update != "never":
cvedb_orig.get_cvelist_if_stale()
else:
LOGGER.warning("Not verifying CVE DB cache")
if not cvedb_orig.check_cve_entries():
with ErrorHandler(mode=error_mode, logger=LOGGER):
raise EmptyCache(cvedb_orig.cachedir)
if not cvedb_orig.latest_schema():
LOGGER.critical("Database does not have the latest schema.")
LOGGER.info("Please update database, by using --update 'now'")
if args["offline"]:
LOGGER.info(
"Consult the documentation at https://cve-bin-tool.readthedocs.io/en/latest/how_to_guides/offline.html to find out how to setup offline operation."
)
return ERROR_CODES[CVEDBOutdatedSchema]

# update db if needed
if db_update != "never":
cvedb_orig.get_cvelist_if_stale()
else:
LOGGER.warning("Not verifying CVE DB cache")
# CVE Database validation
if not cvedb_orig.check_cve_entries():
with ErrorHandler(mode=error_mode, logger=LOGGER):
raise EmptyCache(cvedb_orig.cachedir)
if not cvedb_orig.latest_schema():
LOGGER.critical("Database does not have the latest schema.")
LOGGER.info("Please update database, by using --update 'now'")
if args["offline"]:
LOGGER.info(
"Consult the documentation at https://cve-bin-tool.readthedocs.io/en/latest/how_to_guides/offline.html to find out how to setup offline operation."
)
return ERROR_CODES[CVEDBOutdatedSchema]
raise CVEDataMissing("No data in CVE Database")

# CVE Database validation
if not cvedb_orig.check_cve_entries():
with ErrorHandler(mode=error_mode, logger=LOGGER):
raise CVEDataMissing("No data in CVE Database")

# Report time of last database update
db_date = time.strftime(
"%d %B %Y at %H:%M:%S", time.localtime(cvedb_orig.get_db_update_date())
)
LOGGER.info(
"CVE database contains CVEs from National Vulnerability Database (NVD), Open Source Vulnerability Database (OSV), Gitlab Advisory Database (GAD) and RedHat"
)
LOGGER.info(f"CVE database last updated on {db_date}")
# Report time of last database update
db_date = time.strftime(
"%d %B %Y at %H:%M:%S", time.localtime(cvedb_orig.get_db_update_date())
)
LOGGER.info(
"CVE database contains CVEs from National Vulnerability Database (NVD), Open Source Vulnerability Database (OSV), Gitlab Advisory Database (GAD) and RedHat"
)
LOGGER.info(f"CVE database last updated on {db_date}")

cvedb_orig.remove_cache_backup()
cvedb_orig.remove_cache_backup()

output_formats = set(args["format"].split(","))
output_formats = [output_format.strip() for output_format in output_formats]
@@ -1083,14 +1084,18 @@ def main(argv=None):
# Root package for generated SBOM. Will be updated to reflect input data
sbom_root = "CVE-SCAN"

if args["no_scan"]:
cvedb_orig = None
disabled_sources = None

with CVEScanner(
score=score,
check_metrics=metrics,
epss_percentile=epss_percentile,
epss_probability=epss_probability,
check_exploits=args["exploits"],
exploits_list=cvedb_orig.get_exploits_list(),
disabled_sources=disabled_sources,
exploits_list=cvedb_orig.get_exploits_list() if cvedb_orig else [],
disabled_sources=disabled_sources or [],
) as cve_scanner:
triage_data: TriageData
total_files: int = 0
@@ -1157,7 +1162,8 @@ def main(argv=None):
LOGGER.debug(f"Triage Data: {triage_data}")
parsed_data[product_info] = triage_data

cve_scanner.get_cves(product_info, triage_data)
if not args["no_scan"]:
cve_scanner.get_cves(product_info, triage_data)
total_files = version_scanner.total_scanned_files
LOGGER.info(f"Total files: {total_files}")

29 changes: 23 additions & 6 deletions cve_bin_tool/parsers/ccpp.py
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@
import re

from cve_bin_tool.parsers import Parser
from cve_bin_tool.util import ProductInfo, ScanInfo


class CCppParser(Parser):
@@ -51,15 +52,31 @@ def run_checker(self, filename):
product = require.split("#")[0].split("/")[0]
version = require.split("#")[0].split("/")[1]
purl = self.generate_purl(product)
vendor = self.get_vendor(purl, product, version)
if vendor is not None:
yield from vendor
if not self.cve_db:
yield from [
ScanInfo(
ProductInfo("UNKNOWN", product, version, purl),
" ",
),
]
else:
vendor = self.get_vendor(purl, product, version)
if vendor is not None:
yield from vendor
if build_requires:
for build_require in build_requires:
product = build_require.split("#")[0].split("/")[0]
version = build_require.split("#")[0].split("/")[1]
purl = self.generate_purl(product)
vendor = self.get_vendor(purl, product, version)
if vendor is not None:
yield from vendor
if not self.cve_db:
yield from [
ScanInfo(
ProductInfo("UNKNOWN", product, version, purl),
" ",
),
]
else:
vendor = self.get_vendor(purl, product, version)
if vendor is not None:
yield from vendor
self.logger.debug(f"Done scanning file: {self.filename}")
16 changes: 13 additions & 3 deletions cve_bin_tool/parsers/dart.py
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@
import yaml

from cve_bin_tool.parsers import Parser
from cve_bin_tool.util import ProductInfo, ScanInfo


class DartParser(Parser):
@@ -54,7 +55,16 @@ def run_checker(self, filename):
product = package_name
version = package_detail.get("version").replace('"', "")
purl = self.generate_purl(product)
vendor = self.get_vendor(purl, product, version)
if vendor:
yield from vendor

if not self.cve_db:
yield from [
ScanInfo(
ProductInfo("UNKNOWN", product, version, purl),
" ",
),
]
else:
vendor = self.get_vendor(purl, product, version)
if vendor:
yield from vendor
self.logger.debug(f"Done scanning file: {self.filename}")
14 changes: 10 additions & 4 deletions cve_bin_tool/parsers/env.py
Original file line number Diff line number Diff line change
@@ -45,6 +45,11 @@ class EnvParser(Parser):
requirements.txt) and generate PURLs (Package URLs) for the listed packages.
"""

def __init__(self, cve_db, logger):
super().__init__(cve_db, logger)
self.cve_db = cve_db
self.logger = logger

PARSER_MATCH_FILENAMES = [
".env",
]
@@ -127,10 +132,11 @@ def run_checker(self, filename):
for _namespace, cve in env_config.namespaces.items()
]

with self.cve_db.with_cursor() as cursor:
self.cve_db.populate_cve_metrics(severity_data, cursor)
self.cve_db.populate_severity(severity_data, cursor, data_source)
self.cve_db.populate_affected(affected_data, cursor, data_source)
if self.cve_db:
with self.cve_db.with_cursor() as cursor:
self.cve_db.populate_cve_metrics(severity_data, cursor)
self.cve_db.populate_severity(severity_data, cursor, data_source)
self.cve_db.populate_affected(affected_data, cursor, data_source)

for _namespace, cve in env_config.namespaces.items():
yield ScanInfo(
15 changes: 12 additions & 3 deletions cve_bin_tool/parsers/go.py
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@
import re

from cve_bin_tool.parsers import Parser
from cve_bin_tool.util import ProductInfo, ScanInfo


class GoParser(Parser):
@@ -75,7 +76,15 @@ def run_checker(self, filename):
product = line.split(" ")[0].split("/")[-1]
version = line.split(" ")[1][1:].split("-")[0].split("+")[0]
purl = self.generate_purl(product)
vendors = self.get_vendor(purl, product, version)
if vendors is not None:
yield from vendors
if not self.cve_db:
yield from [
ScanInfo(
ProductInfo("UNKNOWN", product, version, purl),
" ",
),
]
else:
vendors = self.get_vendor(purl, product, version)
if vendors is not None:
yield from vendors
self.logger.debug(f"Done scanning file: {self.filename}")
48 changes: 33 additions & 15 deletions cve_bin_tool/parsers/java.py
Original file line number Diff line number Diff line change
@@ -99,12 +99,20 @@ def run_checker(self, filename):
product = parent.find(schema + "artifactId").text
if product is not None and version is not None:
purl = self.generate_purl(product)
product_info, result = self.find_vendor_from_purl(purl, version)
if not result:
product_info = self.find_vendor(product, version)
product_info = self.mismatch(purl, product_info)
if product_info is not None:
yield from product_info
if not self.cve_db:
yield from [
ScanInfo(
ProductInfo("UNKNOWN", product, version, purl),
file_path,
),
]
else:
product_info, result = self.find_vendor_from_purl(purl, version)
if not result:
product_info = self.find_vendor(product, version)
product_info = self.mismatch(purl, product_info)
if product_info is not None:
yield from product_info

# Some version strings are defined as properties.
# Build up dictionary of values in same format ${name} : {value}
@@ -136,14 +144,24 @@ def run_checker(self, filename):
if version[0].isdigit():
# Valid version identifier
purl = self.generate_purl(product.text)
product_info, result = self.find_vendor_from_purl(
purl, version
)
if not result:
product_info = self.find_vendor(
product.text, version
if not self.cve_db:
yield from [
ScanInfo(
ProductInfo(
"UNKNOWN", product.text, version, purl
),
file_path,
),
]
else:
product_info, result = self.find_vendor_from_purl(
purl, version
)
product_info = self.mismatch(purl, product_info)
if product_info is not None:
yield from product_info
if not result:
product_info = self.find_vendor(
product.text, version
)
product_info = self.mismatch(purl, product_info)
if product_info is not None:
yield from product_info
self.logger.debug(f"Done scanning file: {filename}")
48 changes: 37 additions & 11 deletions cve_bin_tool/parsers/javascript.py
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@
import re

from cve_bin_tool.parsers import Parser
from cve_bin_tool.util import ProductInfo, ScanInfo


class JavascriptParser(Parser):
@@ -58,7 +59,16 @@ def process_package_lock(self, filename):
product = data["name"]
version = data["version"]
purl = self.generate_purl(product)
vendor = self.get_vendor(purl, product, version)
if not self.cve_db:
vendor = None
yield from [
ScanInfo(
ProductInfo("UNKNOWN", product, version, purl),
" ",
),
]
else:
vendor = self.get_vendor(purl, product, version)
else:
vendor = None
if vendor is not None:
@@ -108,9 +118,17 @@ def process_package_lock(self, filename):

for product, version in product_version_mapping:
purl = self.generate_purl(product, "")
vendor = self.get_vendor(purl, product, version)
if vendor is not None:
yield from vendor
if not self.cve_db:
yield from [
ScanInfo(
ProductInfo("UNKNOWN", product, version, purl),
" ",
),
]
else:
vendor = self.get_vendor(purl, product, version)
if vendor is not None:
yield from vendor

def process_yarn_lock(self, filename):
"""Process yarn.lock file and extract product and dependency details
@@ -136,11 +154,19 @@ def process_yarn_lock(self, filename):
for product, version in product_version_mapping:
# Generate the PURL for the package
purl = self.generate_purl(product, "", version)
vendor, result = self.find_vendor_from_purl(purl, version)
if not self.cve_db:
yield from [
ScanInfo(
ProductInfo("UNKNOWN", product, version, purl),
" ",
),
]
else:
vendor, result = self.find_vendor_from_purl(purl, version)

if not result:
# If no vendor found using PURL, try to find vendor using product and version
vendor = self.find_vendor(product, version)
if vendor is not None:
# Yield vendor information if found
yield from vendor
if not result:
# If no vendor found using PURL, try to find vendor using product and version
vendor = self.find_vendor(product, version)
if vendor is not None:
# Yield vendor information if found
yield from vendor
15 changes: 12 additions & 3 deletions cve_bin_tool/parsers/perl.py
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@
import re

from cve_bin_tool.parsers import Parser
from cve_bin_tool.util import ProductInfo, ScanInfo


class PerlParser(Parser):
@@ -59,7 +60,15 @@ def run_checker(self, filename):
product = dependency[0]
version = dependency[1]
purl = self.generate_purl(product)
vendor = self.get_vendor(purl, product, version)
if vendor is not None:
yield from vendor
if not self.cve_db:
yield from [
ScanInfo(
ProductInfo("UNKNOWN", product, version, purl),
" ",
),
]
else:
vendor = self.get_vendor(purl, product, version)
if vendor is not None:
yield from vendor
self.logger.debug(f"Done scanning file: {self.filename}")
15 changes: 12 additions & 3 deletions cve_bin_tool/parsers/php.py
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@
import re

from cve_bin_tool.parsers import Parser
from cve_bin_tool.util import ProductInfo, ScanInfo


class PhpParser(Parser):
@@ -58,7 +59,15 @@ def run_checker(self, filename):
if "dev" in version:
continue
purl = self.generate_purl(product)
vendor = self.get_vendor(purl, product, version)
if vendor is not None:
yield from vendor
if not self.cve_db:
yield from [
ScanInfo(
ProductInfo("UNKNOWN", product, version, purl),
" ",
),
]
else:
vendor = self.get_vendor(purl, product, version)
if vendor is not None:
yield from vendor
self.logger.debug(f"Done scanning file: {self.filename}")
31 changes: 24 additions & 7 deletions cve_bin_tool/parsers/python.py
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@

from cve_bin_tool.parsers import Parser
from cve_bin_tool.strings import parse_strings
from cve_bin_tool.util import ProductInfo, ScanInfo


class PythonRequirementsParser(Parser):
@@ -100,10 +101,18 @@ def run_checker(self, filename):
product = line["metadata"]["name"]
version = line["metadata"]["version"]
purl = self.generate_purl(product)
vendor = self.get_vendor(purl, product, version)

if vendor is not None:
yield from vendor
if not self.cve_db:
yield from [
ScanInfo(
ProductInfo("UNKNOWN", product, version, purl),
" ",
),
]
else:
vendor = self.get_vendor(purl, product, version)

if vendor is not None:
yield from vendor
self.logger.debug(f"Done scanning file: {self.filename}")


@@ -153,9 +162,17 @@ def run_checker(self, filename):
product = search(compile(r"^Name: (.+)$", MULTILINE), lines).group(1)
version = search(compile(r"^Version: (.+)$", MULTILINE), lines).group(1)
purl = self.generate_purl(product)
vendor = self.get_vendor(purl, product, version)
if vendor is not None:
yield from vendor
if not self.cve_db:
yield from [
ScanInfo(
ProductInfo("UNKNOWN", product, version, purl),
" ",
),
]
else:
vendor = self.get_vendor(purl, product, version)
if vendor is not None:
yield from vendor

# There are packages with a METADATA file in them containing different data from what the tool expects
except AttributeError:
15 changes: 12 additions & 3 deletions cve_bin_tool/parsers/r.py
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@
import re

from cve_bin_tool.parsers import Parser
from cve_bin_tool.util import ProductInfo, ScanInfo


class RParser(Parser):
@@ -61,7 +62,15 @@ def run_checker(self, filename):
product = content["Packages"][package]["Package"]
version = content["Packages"][package]["Version"]
purl = self.generate_purl(product)
vendor = self.get_vendor(purl, product, version)
if vendor is not None:
yield from vendor
if not self.cve_db:
yield from [
ScanInfo(
ProductInfo("UNKNOWN", product, version, purl),
" ",
),
]
else:
vendor = self.get_vendor(purl, product, version)
if vendor is not None:
yield from vendor
self.logger.debug(f"Done scanning file: {self.filename}")
15 changes: 12 additions & 3 deletions cve_bin_tool/parsers/ruby.py
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@
import re

from cve_bin_tool.parsers import Parser
from cve_bin_tool.util import ProductInfo, ScanInfo


class RubyParser(Parser):
@@ -73,7 +74,15 @@ def run_checker(self, filename):
product = line.strip().split()[0]
version = line.strip().split("(")[1][:-1]
purl = self.generate_purl(product)
vendors = self.get_vendor(purl, product, version)
if vendors is not None:
yield from vendors
if not self.cve_db:
yield from [
ScanInfo(
ProductInfo("UNKNOWN", product, version, purl),
" ",
),
]
else:
vendors = self.get_vendor(purl, product, version)
if vendors is not None:
yield from vendors
self.logger.debug(f"Done scanning file: {self.filename}")
15 changes: 12 additions & 3 deletions cve_bin_tool/parsers/rust.py
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@
import re

from cve_bin_tool.parsers import Parser
from cve_bin_tool.util import ProductInfo, ScanInfo


class RustParser(Parser):
@@ -66,9 +67,17 @@ def run_checker(self, filename):
continue

purl = self.generate_purl(product)
vendors = self.get_vendor(purl, product, version)
if vendors is not None:
yield from vendors
if not self.cve_db:
yield from [
ScanInfo(
ProductInfo("UNKNOWN", product, version, purl),
" ",
),
]
else:
vendors = self.get_vendor(purl, product, version)
if vendors is not None:
yield from vendors
product = ""
version = ""
self.logger.debug(f"Done scanning file: {self.filename}")
15 changes: 12 additions & 3 deletions cve_bin_tool/parsers/swift.py
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@
from urllib.parse import urlparse

from cve_bin_tool.parsers import Parser
from cve_bin_tool.util import ProductInfo, ScanInfo


class SwiftParser(Parser):
@@ -74,7 +75,15 @@ def run_checker(self, filename):
self.logger.debug(domain)

purl = self.generate_purl(product)
vendors = self.get_vendor(purl, product, version)
if vendors is not None:
yield from vendors
if not self.cve_db:
yield from [
ScanInfo(
ProductInfo("UNKNOWN", product, version, purl),
" ",
),
]
else:
vendors = self.get_vendor(purl, product, version)
if vendors is not None:
yield from vendors
self.logger.debug(f"Done scanning file: {self.filename}")
11 changes: 7 additions & 4 deletions cve_bin_tool/version_scanner.py
Original file line number Diff line number Diff line change
@@ -68,12 +68,16 @@ def __init__(
self.should_extract = should_extract
self.file_stack: list[str] = []
self.error_mode = error_mode
self.cve_db = CVEDB(sources=sources)
self.validate = validate
self.logger.info("Checkers loaded: %s" % (", ".join(self.checkers.keys())))
self.language_checkers = valid_files
self.language_checkers_names = self.available_language_checkers()

if self.no_scan:
self.cve_db = None
else:
self.cve_db = CVEDB(sources=sources)

@classmethod
def load_checkers(cls) -> dict[str, type[Checker]]:
"""Loads CVE checkers"""
@@ -262,9 +266,8 @@ def scan_file(self, filename: str) -> Iterator[ScanInfo]:
# parse binary file's strings
lines = parse_strings(filename)

if self.no_scan:
yield from self.run_checkers(filename, lines)
return
if not self.no_scan and not self.cve_db:
self.logger.info("No Database Object Found: Fallback to No-Scan Mode")

if output:
valid_file = False
26 changes: 21 additions & 5 deletions test/test_javascript.py
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@
import json

from cve_bin_tool.parsers.javascript import JavascriptParser
from cve_bin_tool.util import ProductInfo, ScanInfo


# Dummy logger to suppress debug output
@@ -18,13 +19,21 @@ def __init__(self):
super().__init__(cve_db=None, logger=DummyLogger())

def get_vendor(self, purl, product, version):
return ["vendor_dummy"]
return [ScanInfo(ProductInfo("UNKNOWN", product, version, purl), " ")]

def find_vendor_from_purl(self, purl, version):
return (["vendor_yarn"], True)
return ([ScanInfo(ProductInfo("UNKNOWN", purl.name, version, purl), " ")], True)

def find_vendor(self, product, version):
return ["vendor_yarn_alt"]
return [ScanInfo(ProductInfo("UNKNOWN", product, version), " ")]

def run_checker(self, filename):
# Override run_checker to bypass no_scan mode check
if filename.endswith("package-lock.json"):
return self.process_package_lock(filename)
elif filename.endswith("yarn.lock"):
return self.process_yarn_lock(filename)
return []


# Test for package-lock.json branch with lockfileVersion>=2
@@ -46,7 +55,11 @@ def test_process_package_lock_lockfile_v2(tmp_path):
# - package "" -> yields vendor_dummy
# - its require "dep1" yields vendor_dummy (skip if version=="*")
# - package "node_modules/dep3" yields vendor_dummy
expected = ["vendor_dummy", "vendor_dummy", "vendor_dummy"]
expected = [
ScanInfo(ProductInfo("UNKNOWN", "", "1.0.0", None), " "),
ScanInfo(ProductInfo("UNKNOWN", "dep1", "1.2.3", None), " "),
ScanInfo(ProductInfo("UNKNOWN", "dep3", "2.3.4", None), " "),
]
assert results == expected


@@ -63,5 +76,8 @@ def test_process_yarn_lock(tmp_path):
parser = DummyJavascriptParser()
results = list(parser.run_checker(str(file_path)))
# Two matches yield vendor from find_vendor_from_purl for each
expected = ["vendor_yarn", "vendor_yarn"]
expected = [
ScanInfo(ProductInfo("UNKNOWN", "somepackage", "1.0.0", None), " "),
ScanInfo(ProductInfo("UNKNOWN", "anotherpkg", "2.0.0", None), " "),
]
assert results == expected