From 3dc6f4765289e4d92134c440f53e9d83591a4b85 Mon Sep 17 00:00:00 2001 From: Max Amelchenko Date: Wed, 23 Aug 2023 14:50:31 +0300 Subject: [PATCH] feat(secrets): handle non iac secrets FP (#5478) * handle non iac secrets FP * fix mypy issue * fix according to comments --------- Co-authored-by: Max Amelchenko --- checkov/secrets/plugins/detector_utils.py | 13 ++++++++++--- .../secrets/plugins/entropy_keyword_combinator.py | 5 ++++- tests/secrets/sanity/{non_iac_fp => iac_fp}/main.tf | 0 tests/secrets/sanity/{iac_fp => non_iac_fp}/a.py | 3 +++ 4 files changed, 17 insertions(+), 4 deletions(-) rename tests/secrets/sanity/{non_iac_fp => iac_fp}/main.tf (100%) rename tests/secrets/sanity/{iac_fp => non_iac_fp}/a.py (90%) diff --git a/checkov/secrets/plugins/detector_utils.py b/checkov/secrets/plugins/detector_utils.py index 0991948207b..3ca1feb714f 100644 --- a/checkov/secrets/plugins/detector_utils.py +++ b/checkov/secrets/plugins/detector_utils.py @@ -174,16 +174,23 @@ } -def remove_fp_secrets_in_keys(detected_secrets: set[PotentialSecret], line: str) -> None: +def remove_fp_secrets_in_keys(detected_secrets: set[PotentialSecret], line: str, is_code_file: bool = False) -> None: formatted_line = line.replace('"', '').replace("'", '') secrets_to_remove = set() for detected_secret in detected_secrets: + if not detected_secret.secret_value: + continue # Found keyword prefix as potential secret - if detected_secret.secret_value and formatted_line.startswith(detected_secret.secret_value): + if formatted_line.startswith(detected_secret.secret_value): secrets_to_remove.add(detected_secret) # found a function name at the end of the line - if detected_secret.secret_value and formatted_line and FUNCTION_CALL_AFTER_KEYWORD_REGEX.search(formatted_line): + if formatted_line and FUNCTION_CALL_AFTER_KEYWORD_REGEX.search(formatted_line): secrets_to_remove.add(detected_secret) + # secret value is substring of keywork + if is_code_file and FOLLOWED_BY_EQUAL_VALUE_KEYWORD_REGEX.search(formatted_line): + key, value = line.split("=", 1) + if detected_secret.secret_value in key and detected_secret.secret_value in value: + secrets_to_remove.add(detected_secret) detected_secrets -= secrets_to_remove diff --git a/checkov/secrets/plugins/entropy_keyword_combinator.py b/checkov/secrets/plugins/entropy_keyword_combinator.py index 569778e9a41..b542897b52d 100644 --- a/checkov/secrets/plugins/entropy_keyword_combinator.py +++ b/checkov/secrets/plugins/entropy_keyword_combinator.py @@ -209,7 +209,7 @@ def analyze_line( # return a possible secret, otherwise check with next parser return potential_secrets else: - return detect_secret( + detected_secrets = detect_secret( # If we found a keyword (i.e. db_pass = ), lower the threshold to the iac threshold scanners=self.high_entropy_scanners if not keyword_on_key else self.entropy_scanners_non_iac_with_keyword, filename=filename, @@ -217,6 +217,9 @@ def analyze_line( line_number=line_number, kwargs=kwargs ) + if detected_secrets: + remove_fp_secrets_in_keys(detected_secrets, line, True) + return detected_secrets return set() diff --git a/tests/secrets/sanity/non_iac_fp/main.tf b/tests/secrets/sanity/iac_fp/main.tf similarity index 100% rename from tests/secrets/sanity/non_iac_fp/main.tf rename to tests/secrets/sanity/iac_fp/main.tf diff --git a/tests/secrets/sanity/iac_fp/a.py b/tests/secrets/sanity/non_iac_fp/a.py similarity index 90% rename from tests/secrets/sanity/iac_fp/a.py rename to tests/secrets/sanity/non_iac_fp/a.py index b27dad91547..52675cca7a0 100644 --- a/tests/secrets/sanity/iac_fp/a.py +++ b/tests/secrets/sanity/non_iac_fp/a.py @@ -3,6 +3,9 @@ def a(): mock_url = mock_bc_integration.bc_api_url + "/api/v1/vulnerabilities/scan-results/2e97f5afea42664309f492a1e2083b43479c2936" + PASSWORD = "PASSWORD" + STATUS_ERROR_PASSWORD_FETCH = "ERROR_PASSWORD_FETCH" + return "Properties/LogPublishingOptions/AUDIT_LOGS/Enabled" metadata_options['HttpTokens'] == "required"