Repository: bridgecrewio/checkov
Pull request: feat(general): Skip check in json file
**By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.**

[//]: # "
    # PR Title
    Be aware that we use the title to create changelog automatically and therefore only allow specific prefixes
    - break:    to indicate a breaking change, this supersedes any of the types
    - feat:     to indicate new features or checks
    - fix:      to indicate a bugfix or handling of edge cases of existing checks
    - docs:     to indicate an update to our documentation
    - chore:    to indicate adjustments to workflow files or dependency updates
    - platform: to indicate a change needed for the platform
    Additionally a scope is needs to be added to the prefix, which indicates the targeted framework, in doubt choose 'general'.
    #    
    Allowed prefixs:
    argo|arm|azure|bicep|bitbucket|circleci|cloudformation|dockerfile|github|gha|gitlab|helm|kubernetes|kustomize|openapi|sca|secrets|serverless|terraform|general|graph|terraform_plan
    #
    ex.
    feat(terraform): add CKV_AWS_123 to ensure that VPC Endpoint Service is configured for Manual Acceptance
"

## Description

Now user can skip secret json files check by using regex pattern. Usage documentation has been added to Readme.

Fixes #3950

## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my own code
- [x] I have commented my code, particularly in hard-to-understand areas
- [x] I have made corresponding changes to the documentation
- [x] I have added tests that prove my feature, policy, or fix is effective and works
- [x] New and existing tests pass locally with my changes
- [x] Any dependent changes have been merged and published in downstream modules


Problem statement:
Skip checks by directory/path/glob
**Describe the issue**
The secrets scanner is detecting possible secrets in JSON files, but false positives can't be ignored because JSON files don't allow for comments. Excluding the check `CKV_SECRET_6` for the entire directory scanned is too broad of an exclusion.

It would be really nice if you could exclude a check based on the directory/path the file with the issue is in.

**Examples**

This is the command I run today:

`checkov --framework "secrets" -d /repo --skip-check CKV_SECRET_6 --quiet --compact`

This is how I'd like to run it with a glob exclusion:

`checkov --framework "secrets" -d /repo --skip-check 'CKV_SECRET_6:**/*.json' --quiet --compact`

This example above means that the CKV_SECRET_6 check will never match any JSON files. The glob pattern is relative to the `-d` parameter.

**Version:**
 - Docker Hub: bridgecrew/checkov:2

Hints from issue discussion:

Commit message: Remove redundant comment

Patch to review:
diff --git a/README.md b/README.md
index ddac4898b0..b6edd54381 100644
--- a/README.md
+++ b/README.md
@@ -203,7 +203,11 @@ The `--workdir /tf` flag is optional to change the working directory to the moun
 ### Running or skipping checks 
 
 By using command line flags, you can specify to run only named checks (allow list) or run all checks except 
-those listed (deny list). If you are using the platform integration via API key, you can also specify a severity threshold to skip and / or include. See the docs for more detailed information about how these flags work together.
+those listed (deny list). If you are using the platform integration via API key, you can also specify a severity threshold to skip and / or include.
+Moreover, as json files can't contain comments, one can pass regex pattern to skip json file secret scan.
+
+See the docs for more detailed information about how these flags work together.
+   
 
 ## Examples
 
@@ -280,6 +284,18 @@ export PYTHONUNBUFFERED=1 LOG_LEVEL=DEBUG CHECKOV_EXPERIMENTAL_IMAGE_REFERENCING
 checkov -d .
 ```
 
+Run secrets scanning on all files in MyDirectory. Skip CKV_SECRET_6 check on json files that their suffix is DontScan
+```sh
+checkov -d /MyDirectory --framework secrets --bc-api-key ... --skip-check CKV_SECRET_6:.*DontScan.json$
+```
+
+Run secrets scanning on all files in MyDirectory. Skip CKV_SECRET_6 check on json files that contains "skip_test" in path
+```sh
+checkov -d /MyDirectory --framework secrets --bc-api-key ... --skip-check CKV_SECRET_6:.*skip_test.*json$
+```
+
+
+
 
 ### Suppressing/Ignoring a check
 
diff --git a/checkov/runner_filter.py b/checkov/runner_filter.py
index 1182ea6752..c4d6cda4ee 100644
--- a/checkov/runner_filter.py
+++ b/checkov/runner_filter.py
@@ -4,6 +4,7 @@
 import fnmatch
 from collections.abc import Iterable
 from typing import Any, Set, Optional, Union, List, TYPE_CHECKING, Dict
+import re
 
 from checkov.common.bridgecrew.code_categories import CodeCategoryMapping, CodeCategoryConfiguration
 from checkov.common.bridgecrew.severities import Severity, Severities
@@ -185,6 +186,38 @@ def should_run_check(
         logging.debug(f'Should run check {check_id}: {result}')
         return result
 
+    def should_run_check_for_file(self, check_id: str, file_full_path: str, root_folder: str | None) -> bool:
+        """
+        Check if skip check_id for a certain file_types, according to given path pattern
+        """
+        # Check that we have skip check with a path pattern
+        if not self.skip_checks:
+            return True
+
+        skip_check_with_rule = next(iter([skip_check for skip_check in self.skip_checks if check_id in skip_check]), None)
+        if not skip_check_with_rule:
+            return True
+
+        # skip_check_with_rule pattern should be as following (All upper case params is configured by user:
+        # "{CHECK_ID}:{DIRECTORY_RELATIVE_TO_ROOT}/{FILE_NAME_PATTERN}.{FILE_TYPE}
+        splitted_check = skip_check_with_rule.split(":")
+        # In case it's not expected pattern
+        if len(splitted_check) != 2:
+            return True
+        # Creating a Regex pattern according to User Input
+        pattern = splitted_check[1]
+        full_regex_pattern = fr"^{root_folder}/{pattern}" if root_folder else pattern
+        try:
+            if re.search(full_regex_pattern, file_full_path):
+                return False
+        except Exception as exc:
+            logging.error(
+                "Invalid regex pattern has been supplied",
+                extra={"regex_pattern": pattern, "exc": str(exc)}
+            )
+
+        return True
+
     @staticmethod
     def check_matches(check_id: str,
                       bc_check_id: Optional[str],
diff --git a/checkov/secrets/runner.py b/checkov/secrets/runner.py
index 7286e6f684..144f6b7933 100644
--- a/checkov/secrets/runner.py
+++ b/checkov/secrets/runner.py
@@ -171,6 +171,7 @@ def run(
                     severity=severity,
                     secret=secret,
                     runner_filter=runner_filter,
+                    root_folder=root_folder
                 ) or result
                 resource = f'{secret.filename}:{secret.secret_hash}'
                 report.add_resource(resource)
@@ -241,13 +242,16 @@ def search_for_suppression(
             bc_check_id: str,
             severity: Severity | None,
             secret: PotentialSecret,
-            runner_filter: RunnerFilter
+            runner_filter: RunnerFilter,
+            root_folder: str | None
     ) -> _CheckResult | None:
-        if not runner_filter.should_run_check(check_id=check_id, bc_check_id=bc_check_id, severity=severity, report_type=CheckType.SECRETS) and check_id in CHECK_ID_TO_SECRET_TYPE.keys():
+        if (not runner_filter.should_run_check(check_id=check_id, bc_check_id=bc_check_id, severity=severity, report_type=CheckType.SECRETS) and check_id in CHECK_ID_TO_SECRET_TYPE.keys()) or \
+                not runner_filter.should_run_check_for_file(check_id=check_id, file_full_path=secret.filename, root_folder=root_folder):
             return {
                 "result": CheckResult.SKIPPED,
                 "suppress_comment": f"Secret scan {check_id} is skipped"
             }
+
         # Check for suppression comment in the line before, the line of, and the line after the secret
         for line_number in [secret.line_number, secret.line_number - 1, secret.line_number + 1]:
             lt = linecache.getline(secret.filename, line_number)
diff --git a/tests/secrets/skip_test1/skip1.json b/tests/secrets/skip_test1/skip1.json
new file mode 100644
index 0000000000..dd94062df7
--- /dev/null
+++ b/tests/secrets/skip_test1/skip1.json
@@ -0,0 +1,30 @@
+{
+  "spec": [
+    {
+      "name": "SOME_NAME1",
+      "value": "some_value1"
+    },
+    {
+      "value": "Zo5Zhexnf9TUggdn+zBKGEkmUUvuKzVN+/fKPaMBA4zVyef4irH5H5YfwoC4IqAX0DNoMD12yIF67nIdIMg13atW4WM33eNMfXlE",
+      "name": "TEST_PASSWORD_1",
+      "name1": "TEST_PASSWORD_2",
+      "value1": "1Vab3xejyUlh89P6tUJNXgO4t07DzmomF4tPBwTbwt+sjXHg3G0MPMRpH/I2ho4gS5H3AKJkvJZj87V7/Qnp/rHdbMVYK1F0BX35"
+    },
+    {
+      "name": "TEST_PASSWORD_3",
+      "value": "PtpfIZR+zZGPUWUYvLojqylVeEg63CBYN0FpGJ4yuH+9YxZZe8Uq7drEoTSfL64kElPEnVJk+H7SZr+wBoxN5qDWsbDmmUS2H76h"
+    },
+    {
+      "name": "TEST_PASSWORD_4",
+      "value": "emDJTiv6H/hP6I8Tmr5+kUdpBIQDrXMwFO7AkmbwROf3rM6uNToJlIJW7H5ApfPmSGU0oWBwflV6Cd9pPu5nEvgxt4YMHZ0SQ85z"
+    },
+    {
+      "name": "TEST_PASSWORD_LONG_1",
+      "value": "m9+1ONt6FdpnByhlaKDwZ/jjA5gaPzrKY9q5G8cr6kjn092ogigwEOGGryjDqq/NkX1DnKGGG7iduJUJ48+Rv0tgpdVAxwLQuiszRnssmi2ck/Zf1iDFlNQtiE8rvXE6OTCsb6mrpyItLOVnEwsRSpggyRa3KLSuiguiZsK5KyXQ6BsiAclpLvz6QFBQoQkZNxownQrqgLwVwkK1gW0/EEm0m1ylz20ZeLgYO6tRSvKDW0lrgAI7g60F7/eJGv1UqQlxK58T+7u1UX/K11Q69e9jJE+LkQ932eY37U70oVbBVchHwSFKUoffernEaG9XP1tyEpIptPqVpcS2BMpktoR1p1yyWuxC5GsPc2RlPQzEbs3n5lPPnC/uEVu7/cJENSw5+9DzigiHYPz1Cq/p5HedIl5ysn2U2VFgHWekGBYin6ytfmF2Sx+hYqeRd6RcxyU434CXspWQqc330sp9q7vwPQHNecBrvG2Iy7mqVSvaJDnkZ8AN"
+    },
+    {
+      "name": "TEST_PASSWORD_no_password",
+      "value": "RandomP@ssw0rd"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/tests/secrets/skip_test1/skip2.json b/tests/secrets/skip_test1/skip2.json
new file mode 100644
index 0000000000..0bb07055be
--- /dev/null
+++ b/tests/secrets/skip_test1/skip2.json
@@ -0,0 +1,30 @@
+{
+  "spec": [
+    {
+      "name": "SOME_NAME",
+      "value": "some_value"
+    },
+    {
+      "value": "Zo5Zhexnf9TUggdn+zBKGEkmUUvuKzVN+/fKPaMBA4zVyef4irH5H5YfwoC4IqAX0DNoMD12yIF67nIdIMg13atW4WM33eNMfXlE",
+      "name": "TEST_PASSWORD_1",
+      "name1": "TEST_PASSWORD_2",
+      "value1": "1Vab3xejyUlh89P6tUJNXgO4t07DzmomF4tPBwTbwt+sjXHg3G0MPMRpH/I2ho4gS5H3AKJkvJZj87V7/Qnp/rHdbMVYK1F0BX35"
+    },
+    {
+      "name": "TEST_PASSWORD_3",
+      "value": "PtpfIZR+zZGPUWUYvLojqylVeEg63CBYN0FpGJ4yuH+9YxZZe8Uq7drEoTSfL64kElPEnVJk+H7SZr+wBoxN5qDWsbDmmUS2H76h"
+    },
+    {
+      "name": "TEST_PASSWORD_4",
+      "value": "emDJTiv6H/hP6I8Tmr5+kUdpBIQDrXMwFO7AkmbwROf3rM6uNToJlIJW7H5ApfPmSGU0oWBwflV6Cd9pPu5nEvgxt4YMHZ0SQ85z"
+    },
+    {
+      "name": "TEST_PASSWORD_LONG_1",
+      "value": "m9+1ONt6FdpnByhlaKDwZ/jjA5gaPzrKY9q5G8cr6kjn092ogigwEOGGryjDqq/NkX1DnKGGG7iduJUJ48+Rv0tgpdVAxwLQuiszRnssmi2ck/Zf1iDFlNQtiE8rvXE6OTCsb6mrpyItLOVnEwsRSpggyRa3KLSuiguiZsK5KyXQ6BsiAclpLvz6QFBQoQkZNxownQrqgLwVwkK1gW0/EEm0m1ylz20ZeLgYO6tRSvKDW0lrgAI7g60F7/eJGv1UqQlxK58T+7u1UX/K11Q69e9jJE+LkQ932eY37U70oVbBVchHwSFKUoffernEaG9XP1tyEpIptPqVpcS2BMpktoR1p1yyWuxC5GsPc2RlPQzEbs3n5lPPnC/uEVu7/cJENSw5+9DzigiHYPz1Cq/p5HedIl5ysn2U2VFgHWekGBYin6ytfmF2Sx+hYqeRd6RcxyU434CXspWQqc330sp9q7vwPQHNecBrvG2Iy7mqVSvaJDnkZ8AN"
+    },
+    {
+      "name": "TEST_PASSWORD_no_password",
+      "value": "RandomP@ssw0rd"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/tests/secrets/skip_test1/skip_test2/skip1.json b/tests/secrets/skip_test1/skip_test2/skip1.json
new file mode 100644
index 0000000000..dd94062df7
--- /dev/null
+++ b/tests/secrets/skip_test1/skip_test2/skip1.json
@@ -0,0 +1,30 @@
+{
+  "spec": [
+    {
+      "name": "SOME_NAME1",
+      "value": "some_value1"
+    },
+    {
+      "value": "Zo5Zhexnf9TUggdn+zBKGEkmUUvuKzVN+/fKPaMBA4zVyef4irH5H5YfwoC4IqAX0DNoMD12yIF67nIdIMg13atW4WM33eNMfXlE",
+      "name": "TEST_PASSWORD_1",
+      "name1": "TEST_PASSWORD_2",
+      "value1": "1Vab3xejyUlh89P6tUJNXgO4t07DzmomF4tPBwTbwt+sjXHg3G0MPMRpH/I2ho4gS5H3AKJkvJZj87V7/Qnp/rHdbMVYK1F0BX35"
+    },
+    {
+      "name": "TEST_PASSWORD_3",
+      "value": "PtpfIZR+zZGPUWUYvLojqylVeEg63CBYN0FpGJ4yuH+9YxZZe8Uq7drEoTSfL64kElPEnVJk+H7SZr+wBoxN5qDWsbDmmUS2H76h"
+    },
+    {
+      "name": "TEST_PASSWORD_4",
+      "value": "emDJTiv6H/hP6I8Tmr5+kUdpBIQDrXMwFO7AkmbwROf3rM6uNToJlIJW7H5ApfPmSGU0oWBwflV6Cd9pPu5nEvgxt4YMHZ0SQ85z"
+    },
+    {
+      "name": "TEST_PASSWORD_LONG_1",
+      "value": "m9+1ONt6FdpnByhlaKDwZ/jjA5gaPzrKY9q5G8cr6kjn092ogigwEOGGryjDqq/NkX1DnKGGG7iduJUJ48+Rv0tgpdVAxwLQuiszRnssmi2ck/Zf1iDFlNQtiE8rvXE6OTCsb6mrpyItLOVnEwsRSpggyRa3KLSuiguiZsK5KyXQ6BsiAclpLvz6QFBQoQkZNxownQrqgLwVwkK1gW0/EEm0m1ylz20ZeLgYO6tRSvKDW0lrgAI7g60F7/eJGv1UqQlxK58T+7u1UX/K11Q69e9jJE+LkQ932eY37U70oVbBVchHwSFKUoffernEaG9XP1tyEpIptPqVpcS2BMpktoR1p1yyWuxC5GsPc2RlPQzEbs3n5lPPnC/uEVu7/cJENSw5+9DzigiHYPz1Cq/p5HedIl5ysn2U2VFgHWekGBYin6ytfmF2Sx+hYqeRd6RcxyU434CXspWQqc330sp9q7vwPQHNecBrvG2Iy7mqVSvaJDnkZ8AN"
+    },
+    {
+      "name": "TEST_PASSWORD_no_password",
+      "value": "RandomP@ssw0rd"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/tests/secrets/skip_test1/skip_test2/skip2.json b/tests/secrets/skip_test1/skip_test2/skip2.json
new file mode 100644
index 0000000000..0bb07055be
--- /dev/null
+++ b/tests/secrets/skip_test1/skip_test2/skip2.json
@@ -0,0 +1,30 @@
+{
+  "spec": [
+    {
+      "name": "SOME_NAME",
+      "value": "some_value"
+    },
+    {
+      "value": "Zo5Zhexnf9TUggdn+zBKGEkmUUvuKzVN+/fKPaMBA4zVyef4irH5H5YfwoC4IqAX0DNoMD12yIF67nIdIMg13atW4WM33eNMfXlE",
+      "name": "TEST_PASSWORD_1",
+      "name1": "TEST_PASSWORD_2",
+      "value1": "1Vab3xejyUlh89P6tUJNXgO4t07DzmomF4tPBwTbwt+sjXHg3G0MPMRpH/I2ho4gS5H3AKJkvJZj87V7/Qnp/rHdbMVYK1F0BX35"
+    },
+    {
+      "name": "TEST_PASSWORD_3",
+      "value": "PtpfIZR+zZGPUWUYvLojqylVeEg63CBYN0FpGJ4yuH+9YxZZe8Uq7drEoTSfL64kElPEnVJk+H7SZr+wBoxN5qDWsbDmmUS2H76h"
+    },
+    {
+      "name": "TEST_PASSWORD_4",
+      "value": "emDJTiv6H/hP6I8Tmr5+kUdpBIQDrXMwFO7AkmbwROf3rM6uNToJlIJW7H5ApfPmSGU0oWBwflV6Cd9pPu5nEvgxt4YMHZ0SQ85z"
+    },
+    {
+      "name": "TEST_PASSWORD_LONG_1",
+      "value": "m9+1ONt6FdpnByhlaKDwZ/jjA5gaPzrKY9q5G8cr6kjn092ogigwEOGGryjDqq/NkX1DnKGGG7iduJUJ48+Rv0tgpdVAxwLQuiszRnssmi2ck/Zf1iDFlNQtiE8rvXE6OTCsb6mrpyItLOVnEwsRSpggyRa3KLSuiguiZsK5KyXQ6BsiAclpLvz6QFBQoQkZNxownQrqgLwVwkK1gW0/EEm0m1ylz20ZeLgYO6tRSvKDW0lrgAI7g60F7/eJGv1UqQlxK58T+7u1UX/K11Q69e9jJE+LkQ932eY37U70oVbBVchHwSFKUoffernEaG9XP1tyEpIptPqVpcS2BMpktoR1p1yyWuxC5GsPc2RlPQzEbs3n5lPPnC/uEVu7/cJENSw5+9DzigiHYPz1Cq/p5HedIl5ysn2U2VFgHWekGBYin6ytfmF2Sx+hYqeRd6RcxyU434CXspWQqc330sp9q7vwPQHNecBrvG2Iy7mqVSvaJDnkZ8AN"
+    },
+    {
+      "name": "TEST_PASSWORD_no_password",
+      "value": "RandomP@ssw0rd"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/tests/secrets/test_skip_check_in_json.py b/tests/secrets/test_skip_check_in_json.py
new file mode 100644
index 0000000000..9bef8126fa
--- /dev/null
+++ b/tests/secrets/test_skip_check_in_json.py
@@ -0,0 +1,133 @@
+import os
+import unittest
+from typing import Any, Dict, List
+
+from checkov.common.bridgecrew.platform_integration import bc_integration
+from checkov.runner_filter import RunnerFilter
+from checkov.secrets.plugins.custom_regex_detector import modify_secrets_policy_to_detectors, CustomRegexDetector
+from checkov.secrets.runner import Runner
+
+
+class TestCustomRegexDetector(unittest.TestCase):
+
+    def test_no_skip(self) -> None:
+        """
+        Pass regex pattern which is not apply on any file from test_files_dir
+        """
+        runner = Runner()
+        current_dir = os.path.dirname(os.path.realpath(__file__))
+
+        test_files_dir = os.path.join(current_dir, "skip_test1/skip_test2")
+
+        report = runner.run(
+            root_folder=test_files_dir,
+            runner_filter=RunnerFilter(skip_checks=["CKV_SECRET_6:.*3.json$"]))
+
+        summary = report.get_summary()
+        self.assertEqual(summary['passed'], 0)
+        self.assertEqual(summary['failed'], 10)
+        self.assertEqual(summary['skipped'], 0)
+        self.assertEqual(summary['parsing_errors'], 0)
+
+    def test_skip_on_one1(self) -> None:
+        """
+        Pass regex pattern which is apply on one file - first check
+        """
+        runner = Runner()
+        current_dir = os.path.dirname(os.path.realpath(__file__))
+        test_files_dir = os.path.join(current_dir, "skip_test1/skip_test2")
+        report = runner.run(
+            root_folder=test_files_dir,
+            runner_filter=RunnerFilter(skip_checks=["CKV_SECRET_6:.*1.json$"]))
+
+        summary = report.get_summary()
+        self.assertEqual(summary['passed'], 0)
+        self.assertEqual(summary['failed'], 5)
+        self.assertEqual(summary['skipped'], 5)
+        self.assertEqual(summary['parsing_errors'], 0)
+
+    def test_skip_on_one2(self) -> None:
+        """
+        Pass regex pattern which is apply on one file - second check
+        """
+        runner = Runner()
+        current_dir = os.path.dirname(os.path.realpath(__file__))
+        test_files_dir = os.path.join(current_dir, "skip_test1/skip_test2")
+        report = runner.run(
+            root_folder=test_files_dir,
+            runner_filter=RunnerFilter(skip_checks=["CKV_SECRET_6:.*2.json$"]))
+
+        summary = report.get_summary()
+        self.assertEqual(summary['passed'], 0)
+        self.assertEqual(summary['failed'], 5)
+        self.assertEqual(summary['skipped'], 5)
+        self.assertEqual(summary['parsing_errors'], 0)
+
+    def test_skip_both(self) -> None:
+        """
+        Pass regex pattern apply all files in root folder
+        """
+        runner = Runner()
+        current_dir = os.path.dirname(os.path.realpath(__file__))
+        test_files_dir = os.path.join(current_dir, "skip_test1/skip_test2")
+        report = runner.run(
+            root_folder=test_files_dir,
+            runner_filter=RunnerFilter(skip_checks=["CKV_SECRET_6:.*json$"]))
+
+        summary = report.get_summary()
+        self.assertEqual(summary['passed'], 0)
+        self.assertEqual(summary['failed'], 0)
+        self.assertEqual(summary['skipped'], 10)
+        self.assertEqual(summary['parsing_errors'], 0)
+
+    def test_skip_directory_pattern(self) -> None:
+        """
+        Pass regex pattern which is only apply on one directory pattern
+        """
+        runner = Runner()
+        current_dir = os.path.dirname(os.path.realpath(__file__))
+        test_files_dir = os.path.join(current_dir, "skip_test1")
+        report = runner.run(
+            root_folder=test_files_dir,
+            runner_filter=RunnerFilter(skip_checks=["CKV_SECRET_6:.*skip_test2.*json$"]))
+
+        summary = report.get_summary()
+        self.assertEqual(summary['passed'], 0)
+        self.assertEqual(summary['failed'], 10)
+        self.assertEqual(summary['skipped'], 10)
+        self.assertEqual(summary['parsing_errors'], 0)
+
+    def test_skip_file_pattern(self) -> None:
+        """
+        Pass regex pattern which is only apply on certain file pattern
+        """
+        runner = Runner()
+        current_dir = os.path.dirname(os.path.realpath(__file__))
+        test_files_dir = os.path.join(current_dir, "skip_test1")
+        report = runner.run(
+            root_folder=test_files_dir,
+            runner_filter=RunnerFilter(skip_checks=["CKV_SECRET_6:.*skip1.json$"]))
+
+        summary = report.get_summary()
+        self.assertEqual(summary['passed'], 0)
+        self.assertEqual(summary['failed'], 10)
+        self.assertEqual(summary['skipped'], 10)
+        self.assertEqual(summary['parsing_errors'], 0)
+
+    def test_invalid_regex(self) -> None:
+        """
+        Pass invalid regex pattern
+        """
+        runner = Runner()
+        current_dir = os.path.dirname(os.path.realpath(__file__))
+        test_files_dir = os.path.join(current_dir, "skip_test1")
+        report = runner.run(
+            root_folder=test_files_dir,
+            runner_filter=RunnerFilter(skip_checks=["CKV_SECRET_6:[a-z]++$"]))
+
+        summary = report.get_summary()
+        self.assertEqual(summary['passed'], 0)
+        self.assertEqual(summary['failed'], 20)
+        self.assertEqual(summary['skipped'], 0)
+        self.assertEqual(summary['parsing_errors'], 0)
+


Code review comments:
diff_hunk: @@ -241,13 +242,16 @@ def search_for_suppression(
             bc_check_id: str,
             severity: Severity | None,
             secret: PotentialSecret,
-            runner_filter: RunnerFilter
+            runner_filter: RunnerFilter,
+            root_folder: str | None
     ) -> _CheckResult | None:
-        if not runner_filter.should_run_check(check_id=check_id, bc_check_id=bc_check_id, severity=severity, report_type=CheckType.SECRETS) and check_id in CHECK_ID_TO_SECRET_TYPE.keys():
+        if (not runner_filter.should_run_check(check_id=check_id, bc_check_id=bc_check_id, severity=severity, report_type=CheckType.SECRETS) and check_id in CHECK_ID_TO_SECRET_TYPE.keys()) or \
+                not runner_filter.should_run_check_for_file(check_id=check_id, file_full_path=secret.filename, root_folder=root_folder):
path: checkov/secrets/runner.py
text: @user1:
This filter should be applied to `should_run_check`, runner should not know the internals of all the possible skips. You can have a default value of `None` to keep backwards compatibility

diff_hunk: @@ -185,6 +186,38 @@ def should_run_check(
         logging.debug(f'Should run check {check_id}: {result}')
         return result
 
+    def should_run_check_for_file(self, check_id: str, file_full_path: str, root_folder: str | None) -> bool:
+        """
+        Check if skip check_id for a certain file_types, according to given path pattern
+        """
+        # Check that we have skip check with a path pattern
+        if not self.skip_checks:
+            return True
+
+        skip_check_with_rule = next(iter([skip_check for skip_check in self.skip_checks if check_id in skip_check]), None)
+        if not skip_check_with_rule:
+            return True
+
+        # skip_check_with_rule pattern should be as following (All upper case params is configured by user:
+        # "{CHECK_ID}:{DIRECTORY_RELATIVE_TO_ROOT}/{FILE_NAME_PATTERN}.{FILE_TYPE}
+        splitted_check = skip_check_with_rule.split(":")
+        # In case it's not expected pattern
+        if len(splitted_check) != 2:
+            return True
+        # Creating a Regex pattern according to User Input
+        pattern = splitted_check[1]
+        full_regex_pattern = fr"^{root_folder}/{pattern}" if root_folder else pattern
path: checkov/runner_filter.py
text: @user1:
@author 
1. This can be supplied multiple times, so let's not take only the 1st via `next`
2. Let's compute this once per run, in the constructor, and have a list (empty or non-empty) of regexes to filter

@author:
Done, pls take a look :)