diff --git a/CHANGELOG.md b/CHANGELOG.md index 5bc723fc302..83aac2ef3fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,19 @@ # CHANGELOG -## [Unreleased](https://github.com/bridgecrewio/checkov/compare/3.0.16...HEAD) +## [Unreleased](https://github.com/bridgecrewio/checkov/compare/3.0.19...HEAD) + +## [3.0.19](https://github.com/bridgecrewio/checkov/compare/3.0.16...3.0.19) - 2023-11-02 + +### Feature + +- **sca:** adjusting the cli-output to support indicating of reachable functions - [#5713](https://github.com/bridgecrewio/checkov/pull/5713) +- **terraform:** Adding YAML based build time policies for corresponding PC runtime policies - [#5637](https://github.com/bridgecrewio/checkov/pull/5637) +- **terraform:** bigtable deletion protection [depends on #5625] - [#5626](https://github.com/bridgecrewio/checkov/pull/5626) +- **terraform:** drop and deletion checks for spanner - [#5625](https://github.com/bridgecrewio/checkov/pull/5625) + +### Bug Fix + +- **sast:** add cveid to reachability report - [#5708](https://github.com/bridgecrewio/checkov/pull/5708) ## [3.0.16](https://github.com/bridgecrewio/checkov/compare/3.0.15...3.0.16) - 2023-11-01 diff --git a/checkov/common/bridgecrew/integration_features/features/vulnerabilities_integration.py b/checkov/common/bridgecrew/integration_features/features/vulnerabilities_integration.py index 8c0a72c30f0..785f49f1474 100644 --- a/checkov/common/bridgecrew/integration_features/features/vulnerabilities_integration.py +++ b/checkov/common/bridgecrew/integration_features/features/vulnerabilities_integration.py @@ -2,7 +2,7 @@ import os from collections import defaultdict -from typing import TYPE_CHECKING, Optional, List, Dict, Any, Tuple +from typing import TYPE_CHECKING, Optional, List, Dict, Any, Tuple, Set from checkov.common.bridgecrew.check_type import CheckType from checkov.common.bridgecrew.integration_features.base_integration_feature import BaseIntegrationFeature @@ -94,11 +94,11 @@ def merge_sca_and_sast_reports(self, merged_reports: list[Report]) -> None: continue # Create maps with the relevant structure for the enrichment step - sast_files_by_packages_map = self.create_file_by_package_map(filtered_imports_entries) - sast_reachable_data_by_packages_map = self.create_reachable_data_by_package_map(filtered_reachability_entries) + sast_files_by_package_map = self.create_file_by_package_map(filtered_imports_entries) + sast_reachable_cves_by_package_map = self.create_reachable_cves_by_package_map(filtered_reachability_entries) # Enrich the CVEs - self.enrich_cves_with_sast_data(current_cves, sast_files_by_packages_map, sast_reachable_data_by_packages_map) + self.enrich_cves_with_sast_data(current_cves, sast_files_by_package_map, sast_reachable_cves_by_package_map) ''' Each SCA report check has file_path, we want to getter same file_path so we won't have to calculate SAST language more then once @@ -139,40 +139,41 @@ def create_file_by_package_map(self, filtered_entries: List[Tuple[Any, Any]]) -> return sast_files_by_packages_map - def create_reachable_data_by_package_map(self, filtered_reachability_entries: List[Tuple[Any, Any]]) -> Dict[str, Dict[str, List[str]]]: - reachable_data_by_packages_map: Dict[str, Dict[str, List[str]]] = defaultdict(dict) - for code_file_path, file_data in filtered_reachability_entries: + def create_reachable_cves_by_package_map(self, filtered_reachability_entries: List[Tuple[Any, Any]]) -> Dict[str, Set[str]]: + reachable_cves_by_packages_map: Dict[str, Set[str]] = defaultdict(set) + for _, file_data in filtered_reachability_entries: packages = file_data.packages for package_name, package_data in packages.items(): - reachable_data_by_packages_map[package_name][code_file_path] = package_data.functions - return reachable_data_by_packages_map + for function_item in package_data.functions: + reachable_cves_by_packages_map[package_name].add(function_item.cve_id) + return reachable_cves_by_packages_map ####################################################################################################################### ''' enrich each CVE with the risk factor of IsUsed - which means there is a file the use the package of that CVE ''' - def _is_package_used_for_cve(self, cve_vulnerability_details: Dict[str, Any], sast_files_by_packages_map: Dict[str, List[str]]) -> bool: + def _is_package_used_for_cve(self, cve_vulnerability_details: Dict[str, Any], sast_files_by_package_map: Dict[str, List[str]]) -> bool: package_name = cve_vulnerability_details.get('package_name', '') normalize_package_name = self.normalize_package_name(package_name) - return package_name in sast_files_by_packages_map or normalize_package_name in sast_files_by_packages_map + return package_name in sast_files_by_package_map or normalize_package_name in sast_files_by_package_map - def _is_reachable_function_for_cve(self, cve_vulnerability_details: Dict[str, Any], sast_reachable_data_by_packages_map: Dict[str, Dict[str, List[str]]]) -> bool: + def _is_reachable_function_for_cve(self, cve_vulnerability_details: Dict[str, Any], sast_reachable_cves_by_package_map: Dict[str, Set[str]]) -> bool: package_name = cve_vulnerability_details.get('package_name', '') - return package_name in sast_reachable_data_by_packages_map + return cve_vulnerability_details.get('id') in sast_reachable_cves_by_package_map.get(package_name, set()) def enrich_cves_with_sast_data( self, current_cves: List[Record], - sast_files_by_packages_map: Dict[str, List[str]], - sast_reachable_data_by_packages_map: Dict[str, Dict[str, List[str]]] + sast_files_by_package_map: Dict[str, List[str]], + sast_reachable_cves_by_package_map: Dict[str, Set[str]] ) -> None: for cve_check in current_cves: if cve_check.vulnerability_details: - is_package_used = self._is_package_used_for_cve(cve_check.vulnerability_details, sast_files_by_packages_map) + is_package_used = self._is_package_used_for_cve(cve_check.vulnerability_details, sast_files_by_package_map) cve_check.vulnerability_details.get('risk_factors', {})['IsUsed'] = is_package_used - is_reachable_function = self._is_reachable_function_for_cve(cve_check.vulnerability_details, sast_reachable_data_by_packages_map) + is_reachable_function = self._is_reachable_function_for_cve(cve_check.vulnerability_details, sast_reachable_cves_by_package_map) cve_check.vulnerability_details.get('risk_factors', {})['ReachableFunction'] = is_reachable_function ####################################################################################################################### diff --git a/checkov/version.py b/checkov/version.py index 7e600147832..278602a8044 100644 --- a/checkov/version.py +++ b/checkov/version.py @@ -1 +1 @@ -version = '3.0.19' +version = '3.0.20' diff --git a/kubernetes/requirements.txt b/kubernetes/requirements.txt index 308540688ad..4795cefcd79 100644 --- a/kubernetes/requirements.txt +++ b/kubernetes/requirements.txt @@ -1 +1 @@ -checkov==3.0.19 +checkov==3.0.20 diff --git a/tests/common/integration_features/test_vulnerabilities_integration.py b/tests/common/integration_features/test_vulnerabilities_integration.py index 8737dcbbe88..c0553f10895 100644 --- a/tests/common/integration_features/test_vulnerabilities_integration.py +++ b/tests/common/integration_features/test_vulnerabilities_integration.py @@ -194,23 +194,24 @@ def test_normalized_package_name_case_simple(self): result = vul_integration.normalize_package_name(original) self.assertTrue(result, expected) - def test_create_reachable_data_by_package_map(self): - filtered_reachability_entries = [('/index.js', File(packages={'axios': Package(alias='ax', functions=[Function(name='trim', alias='hopa', line_number=4, code_block='hopa()', cve_id='cve-11')]), 'lodash': Package(alias='', functions=[Function(name='template', alias='', line_number=1, code_block='template()', cve_id='cve-11'), Function(name='toNumber', alias='', line_number=4, code_block='hopa()', cve_id='cve-11')])}))] + def test_create_reachable_cves_by_package_map(self): + filtered_reachability_entries = [ + ('/index.js', File(packages={ + 'axios': Package(alias='ax', functions=[ + Function(name='trim', alias='hopa', line_number=4, code_block='hopa()', cve_id='cve-11') + ]), + 'lodash': Package(alias='', functions=[ + Function(name='template', alias='', line_number=1, code_block='template()', cve_id='cve-12'), + Function(name='toNumber', alias='', line_number=4, code_block='hopa()', cve_id='cve-13') + ]) + })) + ] instance = BcPlatformIntegration() vul_integration = VulnerabilitiesIntegration(instance) - reachable_data_by_package_map = vul_integration.create_reachable_data_by_package_map(filtered_reachability_entries) + reachable_data_by_package_map = vul_integration.create_reachable_cves_by_package_map(filtered_reachability_entries) assert reachable_data_by_package_map == { - 'axios': { - '/index.js': [ - Function(name='trim', alias='hopa', line_number=4, code_block='hopa()', cve_id="cve-11") - ] - }, - 'lodash': { - '/index.js': [ - Function(name='template', alias='', line_number=1, code_block='template()', cve_id="cve-11"), - Function(name='toNumber', alias='', line_number=4, code_block='hopa()', cve_id="cve-11") - ] - } + 'axios': {'cve-11'}, + 'lodash': {'cve-12', 'cve-13'} }