diff --git a/cve_bin_tool/cli.py b/cve_bin_tool/cli.py index c08d8c3dea..db0246e20d 100644 --- a/cve_bin_tool/cli.py +++ b/cve_bin_tool/cli.py @@ -1166,6 +1166,11 @@ def main(argv=None): if not args["no_scan"]: cve_scanner.get_cves(product_info, triage_data) + else: + # In no-scan mode, still populate all_product_data for display + if product_info not in cve_scanner.all_product_data: + cve_scanner.all_product_data[product_info] = 0 + cve_scanner.all_product_data[product_info] = 0 total_files = version_scanner.total_scanned_files LOGGER.info(f"Total files: {total_files}") diff --git a/cve_bin_tool/output_engine/console.py b/cve_bin_tool/output_engine/console.py index 88fdbff08a..a17f400767 100644 --- a/cve_bin_tool/output_engine/console.py +++ b/cve_bin_tool/output_engine/console.py @@ -160,6 +160,8 @@ def _output_console_nowrap( if all_product_data[product_data] != 0 or no_scan: if offline: latest_stable_version = "UNKNOWN (offline mode)" + elif no_scan: + latest_stable_version = "N/A (no-scan mode)" else: latest_stable_version = get_latest_upstream_stable_version( product_data diff --git a/cve_bin_tool/parsers/parse.py b/cve_bin_tool/parsers/parse.py index 91d7b99ced..343d30cfc4 100644 --- a/cve_bin_tool/parsers/parse.py +++ b/cve_bin_tool/parsers/parse.py @@ -93,9 +93,14 @@ def parse(filename, output, cve_db, logger): Parses the given filename using the appropriate parser. """ parsers = [] + filename_basename = os.path.basename(filename) + for file in list(valid_files.keys()): - if file in output: + # Check if this file matches a parser pattern + # Either through output (for binary files) or direct filename match (for language files) + if file in output or file == filename_basename: for valid_file_parser in valid_files[file]: parsers.append(valid_file_parser(cve_db, logger)) + for parser in parsers: yield from parser.run_checker(filename) diff --git a/cve_bin_tool/version_scanner.py b/cve_bin_tool/version_scanner.py index 7ee0686876..4d7ba2489d 100644 --- a/cve_bin_tool/version_scanner.py +++ b/cve_bin_tool/version_scanner.py @@ -262,24 +262,41 @@ def scan_file(self, filename: str) -> Iterator[ScanInfo]: # check if it's a Linux kernel image is_linux_kernel, output = self.is_linux_kernel(filename) - if not is_exec and not is_linux_kernel: + # Check if this file matches any language parser patterns + filename_basename = Path(filename).name + is_language_file = filename_basename in self.language_checkers + + # In no-scan mode, allow language files even if they're not binary + # In normal mode, require the file to be executable or a language file + if not is_exec and not is_linux_kernel and not is_language_file: return None - # parse binary file's strings - lines = parse_strings(filename) + # parse binary file's strings (only for binary files) + lines = "" + if is_exec or is_linux_kernel: + lines = parse_strings(filename) if not self.no_scan and not self.cve_db: self.logger.info("No Database Object Found: Fallback to No-Scan Mode") - if output: + # Check for language parsers first + if output or is_language_file: valid_file = False for file in list(self.language_checkers.keys()): - valid_file = valid_file | (file in output) + valid_file = ( + valid_file | (file in output) + if output + else (file == filename_basename) + ) if valid_file: - for scan_info in parse(filename, output, self.cve_db, self.logger): + for scan_info in parse( + filename, output or "", self.cve_db, self.logger + ): yield ScanInfo(scan_info.product_info, "".join(self.file_stack)) - yield from self.run_checkers(filename, lines) + # Only run binary checkers on binary files + if is_exec or is_linux_kernel: + yield from self.run_checkers(filename, lines) def run_checkers(self, filename: str, lines: str) -> Iterator[ScanInfo]: """process a Set of checker objects, run them on file lines,