Skip to content

Commit 9b4470e

Browse files
authored
CM-20753 - flag for excluding detection in deleted lines (#70)
1 parent 7e4c804 commit 9b4470e

File tree

5 files changed

+56
-20
lines changed

5 files changed

+56
-20
lines changed

cli/code_scanner.py

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ def scan_documents(context: click.Context, documents_to_scan: List[Document], is
234234
cycode_client = context.obj["client"]
235235
scan_type = context.obj["scan_type"]
236236
severity_threshold = context.obj["severity_threshold"]
237-
scan_command_type = context.info_name
237+
command_scan_type = context.info_name
238238
error_message = None
239239
all_detections_count = 0
240240
output_detections_count = 0
@@ -246,7 +246,7 @@ def scan_documents(context: click.Context, documents_to_scan: List[Document], is
246246
scan_result = perform_scan(cycode_client, zipped_documents, scan_type, scan_id, is_git_diff, is_commit_range,
247247
scan_parameters)
248248
all_detections_count, output_detections_count = \
249-
handle_scan_result(context, scan_result, scan_command_type, scan_type, severity_threshold,
249+
handle_scan_result(context, scan_result, command_scan_type, scan_type, severity_threshold,
250250
documents_to_scan)
251251
scan_completed = True
252252
except Exception as e:
@@ -259,7 +259,7 @@ def scan_documents(context: click.Context, documents_to_scan: List[Document], is
259259
{'all_violations_count': all_detections_count, 'relevant_violations_count': output_detections_count,
260260
'scan_id': str(scan_id), 'zip_file_size': zip_file_size})
261261
_report_scan_status(context, scan_type, str(scan_id), scan_completed, output_detections_count,
262-
all_detections_count, len(documents_to_scan), zip_file_size, scan_command_type, error_message)
262+
all_detections_count, len(documents_to_scan), zip_file_size, command_scan_type, error_message)
263263

264264

265265
def scan_commit_range_documents(context: click.Context, from_documents_to_scan: List[Document],
@@ -309,10 +309,10 @@ def should_scan_documents(from_documents_to_scan: List[Document], to_documents_t
309309
return len(from_documents_to_scan) > 0 or len(to_documents_to_scan) > 0
310310

311311

312-
def handle_scan_result(context, scan_result, scan_command_type, scan_type, severity_threshold, to_documents_to_scan):
312+
def handle_scan_result(context, scan_result, command_scan_type, scan_type, severity_threshold, to_documents_to_scan):
313313
document_detections_list = enrich_scan_result(scan_result, to_documents_to_scan)
314314
relevant_document_detections_list = exclude_irrelevant_scan_results(document_detections_list, scan_type,
315-
scan_command_type, severity_threshold)
315+
command_scan_type, severity_threshold)
316316
context.obj['report_url'] = scan_result.report_url
317317
print_results(context, relevant_document_detections_list)
318318
context.obj['issue_detected'] = len(relevant_document_detections_list) > 0
@@ -424,10 +424,10 @@ def enrich_scan_result(scan_result: ZippedFileScanResult, documents_to_scan: Lis
424424

425425

426426
def exclude_irrelevant_scan_results(document_detections_list: List[DocumentDetections], scan_type: str,
427-
scan_command_type: str, severity_threshold: str) -> List[DocumentDetections]:
427+
command_scan_type: str, severity_threshold: str) -> List[DocumentDetections]:
428428
relevant_document_detections_list = []
429429
for document_detections in document_detections_list:
430-
relevant_detections = exclude_irrelevant_detections(scan_type, scan_command_type, severity_threshold,
430+
relevant_detections = exclude_irrelevant_detections(scan_type, command_scan_type, severity_threshold,
431431
document_detections.detections)
432432
if relevant_detections:
433433
relevant_document_detections_list.append(DocumentDetections(document=document_detections.document,
@@ -540,9 +540,9 @@ def exclude_irrelevant_files(context: click.Context, filenames: List[str]) -> Li
540540
return [filename for filename in filenames if _is_relevant_file_to_scan(scan_type, filename)]
541541

542542

543-
def exclude_irrelevant_detections(scan_type: str, scan_command_type: str, severity_threshold: str, detections) -> List:
543+
def exclude_irrelevant_detections(scan_type: str, command_scan_type: str, severity_threshold: str, detections) -> List:
544544
relevant_detections = exclude_detections_by_exclusions_configuration(scan_type, detections)
545-
relevant_detections = exclude_detections_by_scan_command_type(scan_command_type, relevant_detections)
545+
relevant_detections = exclude_detections_by_scan_type(scan_type, command_scan_type, relevant_detections)
546546
relevant_detections = exclude_detections_by_severity(scan_type, severity_threshold, relevant_detections)
547547

548548
return relevant_detections
@@ -557,14 +557,18 @@ def exclude_detections_by_severity(scan_type: str, severity_threshold: str, dete
557557
severity_threshold)]
558558

559559

560-
def exclude_detections_by_scan_command_type(scan_command_type: str, detections) -> List:
561-
if scan_command_type != PRE_COMMIT_SCAN_COMMAND_TYPE:
562-
return detections
560+
def exclude_detections_by_scan_type(scan_type: str, command_scan_type: str, detections) -> List:
561+
if command_scan_type == PRE_COMMIT_COMMAND_SCAN_TYPE:
562+
return exclude_detections_in_deleted_lines(detections)
563563

564-
return exclude_detections_for_pre_commit_scan_command_type(detections)
564+
if command_scan_type in COMMIT_RANGE_BASED_COMMAND_SCAN_TYPES \
565+
and scan_type == SECRET_SCAN_TYPE\
566+
and configuration_manager.get_should_exclude_detections_in_deleted_lines(command_scan_type):
567+
return exclude_detections_in_deleted_lines(detections)
568+
return detections
565569

566570

567-
def exclude_detections_for_pre_commit_scan_command_type(detections) -> List:
571+
def exclude_detections_in_deleted_lines(detections) -> List:
568572
return [detection for detection in detections if detection.detection_details.get('line_type') != 'Removed']
569573

570574

@@ -795,7 +799,7 @@ def _handle_exception(context: click.Context, e: Exception):
795799

796800
def _report_scan_status(context: click.Context, scan_type: str, scan_id: str, scan_completed: bool,
797801
output_detections_count: int, all_detections_count: int, files_to_scan_count: int,
798-
zip_size: int, scan_command_type: str, error_message: Optional[str]):
802+
zip_size: int, command_scan_type: str, error_message: Optional[str]):
799803
try:
800804
cycode_client = context.obj["client"]
801805
end_scan_time = time.time()
@@ -806,7 +810,7 @@ def _report_scan_status(context: click.Context, scan_type: str, scan_id: str, sc
806810
'all_detections_count': all_detections_count,
807811
'scannable_files_count': files_to_scan_count,
808812
'status': 'Completed' if scan_completed else 'Error',
809-
'scan_command_type': scan_command_type,
813+
'scan_command_type': command_scan_type,
810814
'operation_system': platform(),
811815
'error_message': error_message
812816
}

cli/consts.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
PRE_COMMIT_SCAN_COMMAND_TYPE = 'pre_commit'
1+
PRE_COMMIT_COMMAND_SCAN_TYPE = 'pre_commit'
2+
PRE_RECEIVE_COMMAND_SCAN_TYPE = 'pre_receive'
3+
COMMIT_HISTORY_COMMAND_SCAN_TYPE = 'commit_history'
24

35
SECRET_SCAN_TYPE = 'secret'
46
INFRA_CONFIGURATION_SCAN_TYPE = 'iac'
@@ -46,6 +48,8 @@
4648

4749
COMMIT_RANGE_SCAN_SUPPORTED_SCAN_TYPES = [SECRET_SCAN_TYPE, SCA_SCAN_TYPE]
4850

51+
COMMIT_RANGE_BASED_COMMAND_SCAN_TYPES = [PRE_RECEIVE_COMMAND_SCAN_TYPE, COMMIT_HISTORY_COMMAND_SCAN_TYPE]
52+
4953
DEFAULT_CYCODE_API_URL = "https://api.cycode.com"
5054
DEFAULT_CYCODE_APP_URL = "https://app.cycode.com"
5155

@@ -98,6 +102,9 @@
98102
Learn how to: https://cycode.com/dont-let-hardcoded-secrets-compromise-your-security-4-effective-remediation-techniques
99103
"""
100104

105+
EXCLUDE_DETECTIONS_IN_DELETED_LINES_ENV_VAR_NAME = 'EXCLUDE_DETECTIONS_IN_DELETED_LINES'
106+
DEFAULT_EXCLUDE_DETECTIONS_IN_DELETED_LINES = True
107+
101108
# scan statuses
102109
SCAN_STATUS_COMPLETED = 'Completed'
103110
SCAN_STATUS_ERROR = 'Error'

cli/printers/text_printer.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from cli.printers.base_printer import BasePrinter
55
from cli.models import DocumentDetections, Detection, Document
66
from cli.config import config
7-
from cli.consts import SECRET_SCAN_TYPE
7+
from cli.consts import SECRET_SCAN_TYPE, COMMIT_RANGE_BASED_COMMAND_SCAN_TYPES
88
from cli.utils.string_utils import obfuscate_text
99

1010

@@ -57,7 +57,7 @@ def _print_detection_summary(self, detection: Detection, document_path: str):
5757
f'{detection_sha_message}{detection_commit_id_message} ⛔ ')
5858

5959
def _print_detection_code_segment(self, detection: Detection, document: Document, code_segment_size: int):
60-
if document.is_git_diff_format:
60+
if self._is_git_diff_based_scan():
6161
self._print_detection_from_git_diff(detection, document)
6262
return
6363

@@ -169,3 +169,6 @@ def _print_detection_from_git_diff(self, detection: Detection, document: Documen
169169
self._print_detection_line(document, detection_line, detection_line_number_in_original_file,
170170
detection_position_in_line, violation_length)
171171
click.echo()
172+
173+
def _is_git_diff_based_scan(self):
174+
return self.command_scan_type in COMMIT_RANGE_BASED_COMMAND_SCAN_TYPES and self.scan_type == SECRET_SCAN_TYPE

cli/user_settings/config_file_manager.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class ConfigFileManager(BaseFileManager):
1818

1919
MAX_COMMITS_FIELD_NAME: str = 'max_commits'
2020
COMMAND_TIMEOUT_FIELD_NAME: str = 'command_timeout'
21-
21+
EXCLUDE_DETECTIONS_IN_DELETED_LINES: str = 'exclude_detections_in_deleted_lines'
2222

2323
def __init__(self, path):
2424
self.path = path
@@ -43,6 +43,10 @@ def get_max_commits(self, command_scan_type) -> Optional[int]:
4343
def get_command_timeout(self, command_scan_type) -> Optional[int]:
4444
return self._get_value_from_command_scan_type_configuration(command_scan_type, self.COMMAND_TIMEOUT_FIELD_NAME)
4545

46+
def get_exclude_detections_in_deleted_lines(self, command_scan_type) -> Optional[bool]:
47+
return self._get_value_from_command_scan_type_configuration(command_scan_type,
48+
self.EXCLUDE_DETECTIONS_IN_DELETED_LINES)
49+
4650
def update_base_url(self, base_url: str):
4751
update_data = {
4852
self.ENVIRONMENT_SECTION_NAME: {

cli/user_settings/configuration_manager.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,24 @@ def get_pre_receive_command_timeout(self, command_scan_type: str) -> int:
117117

118118
return DEFAULT_PRE_RECEIVE_COMMAND_TIMEOUT_IN_SECONDS
119119

120+
def get_should_exclude_detections_in_deleted_lines(self, command_scan_type: str) -> bool:
121+
exclude_detections_in_deleted_lines = self._get_value_from_environment_variables(
122+
EXCLUDE_DETECTIONS_IN_DELETED_LINES_ENV_VAR_NAME)
123+
if exclude_detections_in_deleted_lines is not None:
124+
return exclude_detections_in_deleted_lines.lower() in ('true', '1')
125+
126+
exclude_detections_in_deleted_lines = self.local_config_file_manager \
127+
.get_exclude_detections_in_deleted_lines(command_scan_type)
128+
if exclude_detections_in_deleted_lines is not None:
129+
return exclude_detections_in_deleted_lines
130+
131+
exclude_detections_in_deleted_lines = self.global_config_file_manager\
132+
.get_exclude_detections_in_deleted_lines(command_scan_type)
133+
if exclude_detections_in_deleted_lines is not None:
134+
return exclude_detections_in_deleted_lines
135+
136+
return DEFAULT_EXCLUDE_DETECTIONS_IN_DELETED_LINES
137+
120138
@staticmethod
121139
def _get_value_from_environment_variables(env_var_name, default=None):
122140
return os.getenv(env_var_name, default)

0 commit comments

Comments
 (0)