Skip to content

Commit

Permalink
fix(sca): Setting only relevant cves for the extracted reachable func…
Browse files Browse the repository at this point in the history
…tions with risk factor of ReachableFunction as True (#5715)

* Setting only relevant cves for the extracted reachable-functions with risk factor of ReachableFunction as True - checkov

* Setting only relevant cves for the extracted reachable-functions with risk factor of ReachableFunction as True - checkov

* Setting only relevant cves for the extracted reachable-functions with risk factor of ReachableFunction as True - checkov

---------

Co-authored-by: ipeleg <[email protected]>
  • Loading branch information
itai1357 and ipeleg authored Nov 5, 2023
1 parent c5a35d0 commit f99bc35
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
#######################################################################################################################

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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'}
}


Expand Down

0 comments on commit f99bc35

Please sign in to comment.