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 9 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
198 changes: 102 additions & 96 deletions cve_bin_tool/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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}")

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

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


class CCppParser(Parser):
Expand Down Expand Up @@ -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
Expand Up @@ -6,6 +6,7 @@
import yaml

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


class DartParser(Parser):
Expand Down Expand Up @@ -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
Expand Up @@ -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",
]
Expand Down Expand Up @@ -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(
Expand Down
15 changes: 12 additions & 3 deletions cve_bin_tool/parsers/go.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import re

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


class GoParser(Parser):
Expand Down Expand Up @@ -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}")
Loading
Loading