diff --git a/prowler/changelog.d/kingfisher-lf-line-indexing.fixed.md b/prowler/changelog.d/kingfisher-lf-line-indexing.fixed.md new file mode 100644 index 0000000000..aea6249d7f --- /dev/null +++ b/prowler/changelog.d/kingfisher-lf-line-indexing.fixed.md @@ -0,0 +1 @@ +Secret ignore patterns now use Kingfisher-compatible LF line indexing for scanned content containing ASCII control characters diff --git a/prowler/lib/utils/utils.py b/prowler/lib/utils/utils.py index 62e01d66ef..fdec495c25 100644 --- a/prowler/lib/utils/utils.py +++ b/prowler/lib/utils/utils.py @@ -232,7 +232,10 @@ def _scan_batch_chunk( encoding=encoding_format_utf_8, errors="replace", ) as f: - source_lines_cache[file_name] = f.read().splitlines() + # Kingfisher reports LF-delimited line numbers. Unlike + # splitlines(), this does not treat ASCII control characters + # such as FS, GS, and RS as additional line boundaries. + source_lines_cache[file_name] = f.read().split("\n") return source_lines_cache[file_name] for entry in kingfisher_output.get("findings", []): diff --git a/tests/lib/utils/utils_test.py b/tests/lib/utils/utils_test.py index c3340704de..342f5d4bd5 100644 --- a/tests/lib/utils/utils_test.py +++ b/tests/lib/utils/utils_test.py @@ -227,6 +227,23 @@ class Test_detect_secrets_scan_batch: ) assert results == {} + @pytest.mark.parametrize("separator", ["\x1c", "\x1d", "\x1e"]) + def test_batch_excluded_secrets_uses_lf_line_numbers(self, separator): + payload = ( + f'const characterTable = "prefix{separator}suffix";\n' + 'DB_ALLOW_EMPTY_PASSWORD = "Tr0ub4dor3xKq9vLmZ"' + ) + with patch( + "prowler.lib.utils.utils.subprocess.run", + side_effect=_fake_kingfisher_run_with_findings([(0, 2)]), + ): + results = detect_secrets_scan_batch( + {"a": payload}, + excluded_secrets=[".*ALLOW_EMPTY_PASSWORD.*"], + ) + + assert results == {} + def test_batch_chunking_maps_all_keys(self): payloads = {f"k{i}": f'password = "S3cr3tV4lu3xy{i}z"' for i in range(5)} results = detect_secrets_scan_batch(payloads, chunk_size=2)