Skip to content

Commit 08ecc57

Browse files
committed
CM-48075 - Update pre-commit hook to work with compact output
1 parent 1eb7f74 commit 08ecc57

File tree

6 files changed

+93
-39
lines changed

6 files changed

+93
-39
lines changed

.pre-commit-hooks.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@
99
language: python
1010
language_version: python3
1111
entry: cycode
12-
args: [ '--no-progress-meter', 'scan', '-t', 'sca', 'pre-commit' ]
12+
args: [ '-o', 'text', '--no-progress-meter', 'scan', '-t', 'sca', 'pre-commit' ]

cycode/cli/printers/console_printer.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,8 @@ class ConsolePrinter:
2828
'text': TextPrinter,
2929
'json': JsonPrinter,
3030
'table': TablePrinter,
31-
# overrides
31+
# overrides:
3232
'table_sca': ScaTablePrinter,
33-
'text_sca': ScaTablePrinter,
3433
}
3534

3635
def __init__(

cycode/cli/printers/rich_printer.py

Lines changed: 55 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -54,47 +54,69 @@ def _get_details_table(self, detection: 'Detection') -> Table:
5454
severity_icon = SeverityOption.get_member_emoji(severity.lower())
5555
details_table.add_row('Severity', f'{severity_icon} {SeverityOption(severity).__rich__()}')
5656

57-
detection_details = detection.detection_details
58-
5957
path = str(get_detection_file_path(self.scan_type, detection))
6058
shorten_path = f'...{path[-self.MAX_PATH_LENGTH :]}' if len(path) > self.MAX_PATH_LENGTH else path
6159
details_table.add_row('In file', f'[link=file://{path}]{shorten_path}[/]')
6260

63-
if self.scan_type == consts.SECRET_SCAN_TYPE:
64-
details_table.add_row('Secret SHA', detection_details.get('sha512'))
65-
elif self.scan_type == consts.SCA_SCAN_TYPE:
66-
details_table.add_row('CVEs', get_detection_clickable_cwe_cve(self.scan_type, detection))
67-
details_table.add_row('Package', detection_details.get('package_name'))
68-
details_table.add_row('Version', detection_details.get('package_version'))
69-
70-
is_package_vulnerability = 'alert' in detection_details
71-
if is_package_vulnerability:
72-
details_table.add_row(
73-
'First patched version', detection_details['alert'].get('first_patched_version', 'Not fixed')
74-
)
75-
76-
details_table.add_row('Dependency path', detection_details.get('dependency_paths', 'N/A'))
77-
78-
if not is_package_vulnerability:
79-
details_table.add_row('License', detection_details.get('license'))
80-
elif self.scan_type == consts.IAC_SCAN_TYPE:
81-
details_table.add_row('IaC Provider', detection_details.get('infra_provider'))
82-
elif self.scan_type == consts.SAST_SCAN_TYPE:
83-
details_table.add_row('CWE', get_detection_clickable_cwe_cve(self.scan_type, detection))
84-
details_table.add_row('Subcategory', detection_details.get('category'))
85-
details_table.add_row('Language', ', '.join(detection_details.get('languages', [])))
86-
87-
engine_id_to_display_name = {
88-
'5db84696-88dc-11ec-a8a3-0242ac120002': 'Semgrep OSS (Orchestrated by Cycode)',
89-
'560a0abd-d7da-4e6d-a3f1-0ed74895295c': 'Bearer (Powered by Cycode)',
90-
}
91-
engine_id = detection.detection_details.get('external_scanner_id')
92-
details_table.add_row('Security Tool', engine_id_to_display_name.get(engine_id, 'N/A'))
61+
self._add_scan_related_rows(details_table, detection)
9362

9463
details_table.add_row('Rule ID', detection.detection_rule_id)
9564

9665
return details_table
9766

67+
def _add_scan_related_rows(self, details_table: Table, detection: 'Detection') -> None:
68+
scan_type_details_handlers = {
69+
consts.SECRET_SCAN_TYPE: self.__add_secret_scan_related_rows,
70+
consts.SCA_SCAN_TYPE: self.__add_sca_scan_related_rows,
71+
consts.IAC_SCAN_TYPE: self.__add_iac_scan_related_rows,
72+
consts.SAST_SCAN_TYPE: self.__add_sast_scan_related_rows,
73+
}
74+
75+
if self.scan_type not in scan_type_details_handlers:
76+
raise ValueError(f'Unknown scan type: {self.scan_type}')
77+
78+
scan_enricher_function = scan_type_details_handlers[self.scan_type]
79+
scan_enricher_function(details_table, detection)
80+
81+
@staticmethod
82+
def __add_secret_scan_related_rows(details_table: Table, detection: 'Detection') -> None:
83+
details_table.add_row('Secret SHA', detection.detection_details.get('sha512'))
84+
85+
@staticmethod
86+
def __add_sca_scan_related_rows(details_table: Table, detection: 'Detection') -> None:
87+
detection_details = detection.detection_details
88+
89+
details_table.add_row('CVEs', get_detection_clickable_cwe_cve(consts.SCA_SCAN_TYPE, detection))
90+
details_table.add_row('Package', detection_details.get('package_name'))
91+
details_table.add_row('Version', detection_details.get('package_version'))
92+
93+
if detection.has_alert:
94+
patched_version = detection_details['alert'].get('patched_version')
95+
details_table.add_row('First patched version', patched_version or 'Not fixed')
96+
97+
dependency_path = detection_details.get('dependency_paths')
98+
details_table.add_row('Dependency path', dependency_path or 'N/A')
99+
100+
if not detection.has_alert:
101+
details_table.add_row('License', detection_details.get('license'))
102+
103+
@staticmethod
104+
def __add_iac_scan_related_rows(details_table: Table, detection: 'Detection') -> None:
105+
details_table.add_row('IaC Provider', detection.detection_details.get('infra_provider'))
106+
107+
@staticmethod
108+
def __add_sast_scan_related_rows(details_table: Table, detection: 'Detection') -> None:
109+
details_table.add_row('CWE', get_detection_clickable_cwe_cve(consts.SAST_SCAN_TYPE, detection))
110+
details_table.add_row('Subcategory', detection.detection_details.get('category'))
111+
details_table.add_row('Language', ', '.join(detection.detection_details.get('languages', [])))
112+
113+
engine_id_to_display_name = {
114+
'5db84696-88dc-11ec-a8a3-0242ac120002': 'Semgrep OSS (Orchestrated by Cycode)',
115+
'560a0abd-d7da-4e6d-a3f1-0ed74895295c': 'Bearer (Powered by Cycode)',
116+
}
117+
engine_id = detection.detection_details.get('external_scanner_id')
118+
details_table.add_row('Security Tool', engine_id_to_display_name.get(engine_id, 'N/A'))
119+
98120
def _print_violation_card(
99121
self, document: 'Document', detection: 'Detection', detection_number: int, detections_count: int
100122
) -> None:
@@ -117,8 +139,7 @@ def _print_violation_card(
117139
title=':computer: Code Snippet',
118140
)
119141

120-
is_sca_package_vulnerability = self.scan_type == consts.SCA_SCAN_TYPE and 'alert' in detection.detection_details
121-
if is_sca_package_vulnerability:
142+
if detection.has_alert:
122143
summary = detection.detection_details['alert'].get('description')
123144
else:
124145
summary = detection.detection_details.get('description') or detection.message

cycode/cli/printers/text_printer.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from typing import TYPE_CHECKING, Optional
22

3+
from cycode.cli import consts
34
from cycode.cli.cli_types import SeverityOption
45
from cycode.cli.models import CliError, CliResult, Document
56
from cycode.cli.printers.printer_base import PrinterBase
@@ -66,10 +67,34 @@ def __print_detection_summary(self, detection: 'Detection', document_path: str)
6667
self.console.print(
6768
severity_icon,
6869
severity,
69-
f'violation: [b bright_red]{title}[/]{detection_commit_id_message}\n'
70+
f'violation: [b bright_red]{title}[/]{detection_commit_id_message}\n',
71+
*self.__get_intermediate_summary_lines(detection),
7072
f'[dodger_blue1]File: {clickable_document_path}[/]',
7173
)
7274

75+
def __get_intermediate_summary_lines(self, detection: 'Detection') -> list[str]:
76+
intermediate_summary_lines = []
77+
78+
if self.scan_type == consts.SCA_SCAN_TYPE:
79+
intermediate_summary_lines.extend(self.__get_sca_related_summary_lines(detection))
80+
81+
return intermediate_summary_lines
82+
83+
@staticmethod
84+
def __get_sca_related_summary_lines(detection: 'Detection') -> list[str]:
85+
summary_lines = []
86+
87+
if detection.has_alert:
88+
patched_version = detection.detection_details['alert'].get('first_patched_version')
89+
patched_version = patched_version or 'Not fixed'
90+
91+
summary_lines.append(f'First patched version: [cyan]{patched_version}[/]\n')
92+
else:
93+
package_license = detection.detection_details.get('license', 'N/A')
94+
summary_lines.append(f'License: [cyan]{package_license}[/]\n')
95+
96+
return summary_lines
97+
7398
def __print_detection_code_segment(self, detection: 'Detection', document: Document) -> None:
7499
self.console.print(
75100
get_code_snippet_syntax(

cycode/cli/printers/utils/detection_data.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ def get_detection_title(scan_type: str, detection: 'Detection') -> str:
8383
elif scan_type == consts.SECRET_SCAN_TYPE:
8484
title = f'Hardcoded {detection.type} is used'
8585

86-
is_sca_package_vulnerability = scan_type == consts.SCA_SCAN_TYPE and 'alert' in detection.detection_details
86+
is_sca_package_vulnerability = scan_type == consts.SCA_SCAN_TYPE and detection.has_alert
8787
if is_sca_package_vulnerability:
8888
title = detection.detection_details['alert'].get('summary', 'N/A')
8989

cycode/cyclient/models.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,15 @@ def __repr__(self) -> str:
3333
f'detection_rule_id:{self.detection_rule_id}'
3434
)
3535

36+
@property
37+
def has_alert(self) -> bool:
38+
"""Check if the detection has an alert.
39+
40+
For example, for SCA, it means that the detection is a package vulnerability.
41+
Otherwise, it is a license.
42+
"""
43+
return 'alert' in self.detection_details
44+
3645

3746
class DetectionSchema(Schema):
3847
class Meta:

0 commit comments

Comments
 (0)