diff --git a/checkov/secrets/plugins/custom_regex_detector.py b/checkov/secrets/plugins/custom_regex_detector.py index 10a8f3e78a5..b92e3e56a98 100644 --- a/checkov/secrets/plugins/custom_regex_detector.py +++ b/checkov/secrets/plugins/custom_regex_detector.py @@ -170,12 +170,12 @@ def _find_potential_secret( continue multiline_matches = multiline_regex.findall(file_content) for mm in multiline_matches: - mm = f"'{mm}'" + quoted_mm = f"'{mm}'" ps = PotentialSecret( type=regex_data["Name"], filename=filename, - secret=mm, - line_number=line_number, + secret=quoted_mm, + line_number=find_line_number(file_content, mm, line_number), is_verified=is_verified, is_added=is_added, is_removed=is_removed, @@ -216,3 +216,12 @@ def analyze_string(self, string: str, **kwargs: Optional[Dict[str, Any]]) -> Gen yield submatch, regex else: yield match, regex + + +def find_line_number(file_string: str, substring: str, default_line_number: int) -> int: + lines = file_string.splitlines() + + for line_number, line in enumerate(lines, start=1): + if substring in line: + return line_number + return default_line_number diff --git a/tests/secrets/multiline_finding/Dockerfile.mine b/tests/secrets/multiline_finding/Dockerfile.mine new file mode 100644 index 00000000000..6e5d8ea5550 --- /dev/null +++ b/tests/secrets/multiline_finding/Dockerfile.mine @@ -0,0 +1,2 @@ +Algolia +const ADMIN_KEY = 'b782df1739614041699a45f8079a3623'; \ No newline at end of file diff --git a/tests/secrets/test_multiline_finding_line_number.py b/tests/secrets/test_multiline_finding_line_number.py new file mode 100644 index 00000000000..73f0d00819b --- /dev/null +++ b/tests/secrets/test_multiline_finding_line_number.py @@ -0,0 +1,53 @@ +import os +import unittest + + +from checkov.common.bridgecrew.platform_integration import bc_integration +from checkov.runner_filter import RunnerFilter +from checkov.secrets.runner import Runner +from tests.secrets.utils_for_test import _filter_reports_for_incident_ids + + +class TestMultilineFinding(unittest.TestCase): + + def test_multiline_finding(self): + current_dir = os.path.dirname(os.path.realpath(__file__)) + valid_dir_path = current_dir + "/multiline_finding" + bc_integration.customer_run_config_response = {"secretsPolicies": [ + { + "incidentId": "test1", + "category": "Secrets", + "severity": "MEDIUM", + "incidentType": "Violation", + "title": "test1", + "guideline": "test", + "laceworkViolationId": None, + "prowlerCheckId": None, + "checkovCheckId": None, + "resourceTypes": + [ + "aws_instance" + ], + "provider": "AWS", + "remediationIds": + [], + "customerName": "test1", + "isCustom": True, + "code": "definition:\n cond_type: secrets\n multiline: true\n prerun:\n - (?i)(?:algolia)\n value:\n - (?i)(?:algolia)(?:.|[\\n\\r]){0,80}([A-Za-z0-9]{32})\n", + "descriptiveTitle": None, + "constructiveTitle": None, + "pcPolicyId": None, + "additionalPcPolicyIds": None, + "pcSeverity": None, + "sourceIncidentId": None + } + ]} + runner = Runner() + report = runner.run(root_folder=valid_dir_path, + runner_filter=RunnerFilter(framework=['secrets'], + enable_secret_scan_all_files=True)) + interesting_failed_checks = _filter_reports_for_incident_ids(report.failed_checks, ["test1"]) + self.assertEqual(len(interesting_failed_checks), 1) + self.assertEqual(len(interesting_failed_checks[0].code_block), 1) + self.assertEqual(len(interesting_failed_checks[0].code_block[0]), 2) + self.assertEqual(interesting_failed_checks[0].code_block[0][0], 2)