Skip to content

Commit d312c17

Browse files
authored
CM-32255, CM-35768 - Fix scan errors during commit history scans with --report option (#249)
1 parent 9123b44 commit d312c17

File tree

2 files changed

+44
-28
lines changed

2 files changed

+44
-28
lines changed

cycode/cli/commands/scan/code_scanner.py

Lines changed: 40 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,7 @@ def perform_scan_sync(
525525
logger.debug('Sync scan request has been triggered successfully, %s', {'scan_id': scan_results.id})
526526
return ZippedFileScanResult(
527527
did_detect=True,
528-
detections_per_file=_map_detections_per_file(scan_results.detection_messages),
528+
detections_per_file=_map_detections_per_file_and_commit_id(scan_results.detection_messages),
529529
scan_id=scan_results.id,
530530
)
531531

@@ -870,11 +870,11 @@ def _get_scan_result(
870870
if not scan_details.detections_count:
871871
return init_default_scan_result(cycode_client, scan_id, scan_type, should_get_report)
872872

873-
scan_detections = cycode_client.get_scan_detections(scan_type, scan_id)
873+
scan_raw_detections = cycode_client.get_scan_raw_detections(scan_type, scan_id)
874874

875875
return ZippedFileScanResult(
876876
did_detect=True,
877-
detections_per_file=_map_detections_per_file(scan_detections),
877+
detections_per_file=_map_detections_per_file_and_commit_id(scan_raw_detections),
878878
scan_id=scan_id,
879879
report_url=_try_get_report_url_if_needed(cycode_client, should_get_report, scan_id, scan_type),
880880
)
@@ -904,42 +904,58 @@ def _try_get_report_url_if_needed(
904904
logger.debug('Failed to get report URL', exc_info=e)
905905

906906

907-
def _map_detections_per_file(detections: List[dict]) -> List[DetectionsPerFile]:
907+
def _map_detections_per_file_and_commit_id(raw_detections: List[dict]) -> List[DetectionsPerFile]:
908+
"""Converts list of detections (async flow) to list of DetectionsPerFile objects (sync flow).
909+
910+
Args:
911+
raw_detections: List of detections as is returned from the server.
912+
913+
Note:
914+
This method fakes server response structure
915+
to be able to use the same logic for both async and sync scans.
916+
917+
Note:
918+
Aggregation is performed by file name and commit ID (if available)
919+
"""
908920
detections_per_files = {}
909-
for detection in detections:
921+
for raw_detection in raw_detections:
910922
try:
911-
detection['message'] = detection['correlation_message']
912-
file_name = _get_file_name_from_detection(detection)
913-
if file_name is None:
914-
logger.debug('File name is missing from detection with ID %s', detection.get('id'))
915-
continue
916-
if detections_per_files.get(file_name) is None:
917-
detections_per_files[file_name] = [DetectionSchema().load(detection)]
923+
# FIXME(MarshalX): investigate this field mapping
924+
raw_detection['message'] = raw_detection['correlation_message']
925+
926+
file_name = _get_file_name_from_detection(raw_detection)
927+
detection: Detection = DetectionSchema().load(raw_detection)
928+
commit_id: Optional[str] = detection.detection_details.get('commit_id') # could be None
929+
group_by_key = (file_name, commit_id)
930+
931+
if group_by_key in detections_per_files:
932+
detections_per_files[group_by_key].append(detection)
918933
else:
919-
detections_per_files[file_name].append(DetectionSchema().load(detection))
934+
detections_per_files[group_by_key] = [detection]
920935
except Exception as e:
921936
logger.debug('Failed to parse detection', exc_info=e)
922937
continue
923938

924939
return [
925-
DetectionsPerFile(file_name=file_name, detections=file_detections)
926-
for file_name, file_detections in detections_per_files.items()
940+
DetectionsPerFile(file_name=file_name, detections=file_detections, commit_id=commit_id)
941+
for (file_name, commit_id), file_detections in detections_per_files.items()
927942
]
928943

929944

930-
def _get_file_name_from_detection(detection: dict) -> str:
931-
if detection.get('category') == 'SAST':
932-
return detection['detection_details']['file_path']
945+
def _get_file_name_from_detection(raw_detection: dict) -> str:
946+
category = raw_detection.get('category')
933947

934-
if detection.get('category') == 'SecretDetection':
935-
return _get_secret_file_name_from_detection(detection)
948+
if category == 'SAST':
949+
return raw_detection['detection_details']['file_path']
950+
if category == 'SecretDetection':
951+
return _get_secret_file_name_from_detection(raw_detection)
936952

937-
return detection['detection_details']['file_name']
953+
return raw_detection['detection_details']['file_name']
938954

939955

940-
def _get_secret_file_name_from_detection(detection: dict) -> str:
941-
file_path: str = detection['detection_details']['file_path']
942-
file_name: str = detection['detection_details']['file_name']
956+
def _get_secret_file_name_from_detection(raw_detection: dict) -> str:
957+
file_path: str = raw_detection['detection_details']['file_path']
958+
file_name: str = raw_detection['detection_details']['file_name']
943959
return os.path.join(file_path, file_name)
944960

945961

cycode/cyclient/scan_client.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -225,12 +225,12 @@ def get_scan_detections_list_path_suffix(scan_type: str) -> str:
225225
def get_scan_detections_list_path(self, scan_type: str) -> str:
226226
return f'{self.get_scan_detections_path(scan_type)}{self.get_scan_detections_list_path_suffix(scan_type)}'
227227

228-
def get_scan_detections(self, scan_type: str, scan_id: str) -> List[dict]:
228+
def get_scan_raw_detections(self, scan_type: str, scan_id: str) -> List[dict]:
229229
params = {'scan_id': scan_id}
230230

231231
page_size = 200
232232

233-
detections = []
233+
raw_detections = []
234234

235235
page_number = 0
236236
last_response_size = 0
@@ -243,12 +243,12 @@ def get_scan_detections(self, scan_type: str, scan_id: str) -> List[dict]:
243243
params=params,
244244
hide_response_content_log=self._hide_response_log,
245245
).json()
246-
detections.extend(response)
246+
raw_detections.extend(response)
247247

248248
page_number += 1
249249
last_response_size = len(response)
250250

251-
return detections
251+
return raw_detections
252252

253253
def commit_range_zipped_file_scan(
254254
self, scan_type: str, zip_file: InMemoryZip, scan_id: str

0 commit comments

Comments
 (0)