diff --git a/checkov/common/runners/base_runner.py b/checkov/common/runners/base_runner.py index 3d8aa896c8..d0fafad25c 100644 --- a/checkov/common/runners/base_runner.py +++ b/checkov/common/runners/base_runner.py @@ -44,7 +44,16 @@ def strtobool(val: str) -> int: raise ValueError("invalid boolean value %r for environment variable CKV_IGNORE_HIDDEN_DIRECTORIES" % (val,)) -IGNORED_DIRECTORIES_ENV = os.getenv("CKV_IGNORED_DIRECTORIES", "node_modules,.terraform,.serverless") +def re_dir(path: str) -> str: + """Compile a regex pattern that matches paths containing the given directory at any level.""" + sep = re.escape(os.sep) # windows compatibility + return rf"(^|.*{sep}){re.escape(path)}($|{sep}.*)" + + +IGNORED_DIRECTORIES_ENV = os.getenv( + "CKV_IGNORED_DIRECTORIES", + ",".join(re_dir(p) for p in ["node_modules", ".terraform", ".serverless"]) +) IGNORE_HIDDEN_DIRECTORY_ENV = strtobool(os.getenv("CKV_IGNORE_HIDDEN_DIRECTORIES", "True")) ignored_directories = IGNORED_DIRECTORIES_ENV.split(",") diff --git a/checkov/secrets/utils.py b/checkov/secrets/utils.py index 63496cd3fe..2b0ba29abc 100644 --- a/checkov/secrets/utils.py +++ b/checkov/secrets/utils.py @@ -4,10 +4,16 @@ import re from collections.abc import Iterable -from checkov.common.runners.base_runner import ignored_directories, safe_remove +from checkov.common.runners.base_runner import ignored_directories, safe_remove, re_dir from checkov.common.util.consts import DEFAULT_EXTERNAL_MODULES_DIR -EXCLUDED_PATHS = [*ignored_directories, DEFAULT_EXTERNAL_MODULES_DIR, ".idea", ".git", "venv"] +EXCLUDED_PATHS = [ + *ignored_directories, + re_dir(DEFAULT_EXTERNAL_MODULES_DIR), + re_dir(".idea"), + re_dir(".git"), + re_dir("venv"), +] def filter_excluded_paths( diff --git a/tests/common/runners/test_base_runner.py b/tests/common/runners/test_base_runner.py index 63226a7a96..82f4b11050 100644 --- a/tests/common/runners/test_base_runner.py +++ b/tests/common/runners/test_base_runner.py @@ -1,14 +1,47 @@ import os +import re import unittest from typing import Optional, List from checkov.common.output.report import Report -from checkov.common.runners.base_runner import filter_ignored_paths, BaseRunner +from checkov.common.runners.base_runner import filter_ignored_paths, BaseRunner, re_dir from checkov.runner_filter import RunnerFilter class TestBaseRunner(unittest.TestCase): + def test_re_dir(self): + sep = '\\' if os.name == 'nt' else '/' + # add regex prefix and suffix to the (unmodified) directory name + self.assertEqual(re_dir('dir'), fr'(^|.*{sep})dir($|{sep}.*)') + # escape the directory name (but leave the os separator unaltered) + self.assertEqual(re_dir('.dir1/.dir2'), fr'(^|.*{sep})\.dir1/\.dir2($|{sep}.*)') + + def tests_re_dir_pattern(self): + dir_name_to_ignore = ".hidden" + dir_name_to_ignore_re = re.compile(re_dir(dir_name_to_ignore)) + paths_to_ignore = [ + ".hidden", + "/.hidden", + "/path/.hidden", + "path/.hidden", + ".hidden/path", + "path/.hidden/path", + "path/.hidden/path/", + ] + paths_to_keep = [ + ".hidden1", + "not.hidden", + "nothidden", + "not.hidden/path", + "path/not.hidden", + "also/nothidden", + "hidden/not", + "also/hidden/not", + ] + self.assertTrue(all(dir_name_to_ignore_re.match(p) for p in paths_to_ignore)) + self.assertFalse(any(dir_name_to_ignore_re.match(p) for p in paths_to_keep)) + def test_filter_ignored_directories_regex_legacy(self): d_names = ['bin', 'integration_tests', 'tests', 'docs', '.github', 'checkov', 'venv', '.git', 'kubernetes', '.idea'] expected = ['bin', 'docs', 'checkov', 'venv', 'kubernetes']