Repository: bridgecrewio/checkov

Issue:
Suppression comment in Dockerfile skips more checks than it should
**Describe the issue**
I tried to skip CKV_DOCKER_9 by adding a suppression comment into my Dockerfile, but it turned out that CKV_DOCKER_5 was also skipped.

**Examples**
Here's my Dockerfile with comment to skip CKV_DOCKER_9:
```dockerfile
#checkov:skip=CKV_DOCKER_9
FROM alpine:3.16
RUN ls
```
As you can see, CKV_DOCKER_5 is also marked as SKIPPED in the results:
```
$ docker run -it --rm -v "$(pwd):$(pwd)" -w "$(pwd)" bridgecrew/checkov:2.2.104 --framework dockerfile --skip-download --file Dockerfile

       _               _              
   ___| |__   ___  ___| | _______   __
  / __| '_ \ / _ \/ __| |/ / _ \ \ / /
 | (__| | | |  __/ (__|   < (_) \ V / 
  \___|_| |_|\___|\___|_|\_\___/ \_/  
                                      
By bridgecrew.io | version: 2.2.104 

dockerfile scan results:

Passed checks: 2, Failed checks: 2, Skipped checks: 2

Check: CKV_DOCKER_11: "Ensure From Alias are unique for multistage builds."
	PASSED for resource: Dockerfile.
	File: Dockerfile:1-4
Check: CKV_DOCKER_7: "Ensure the base image uses a non latest version tag"
	PASSED for resource: Dockerfile.
	File: Dockerfile:1-4
Check: CKV_DOCKER_2: "Ensure that HEALTHCHECK instructions have been added to container images"
	FAILED for resource: Dockerfile.
	File: Dockerfile:1-4

		1 | #checkov:skip=CKV_DOCKER_9
		2 | FROM alpine:3.16
		3 | RUN ls
		4 | 

Check: CKV_DOCKER_3: "Ensure that a user for the container has been created"
	FAILED for resource: Dockerfile.
	File: Dockerfile:1-4

		1 | #checkov:skip=CKV_DOCKER_9
		2 | FROM alpine:3.16
		3 | RUN ls
		4 | 

Check: CKV_DOCKER_9: "Ensure that APT isn't used"
	SKIPPED for resource: Dockerfile.
	Suppress comment: No comment provided
	File: Dockerfile:1-4
Check: CKV_DOCKER_5: "Ensure update instructions are not use alone in the Dockerfile"
	SKIPPED for resource: Dockerfile.
	Suppress comment: No comment provided
	File: Dockerfile:1-4
```

**Version (please complete the following information):**
 - Checkov Version: 2.2.104



Discussion:
hey @ggolawski thanks for reaching out. I tested it with the latest version `2.2.114` and can't reproduce it
```shell
By bridgecrew.io | version: 2.2.114 

dockerfile scan results:

Passed checks: 3, Failed checks: 2, Skipped checks: 1

Check: CKV_DOCKER_5: "Ensure update instructions are not use alone in the Dockerfile"
	PASSED for resource: Dockerfile.
	File: Dockerfile:1-3
Check: CKV_DOCKER_11: "Ensure From Alias are unique for multistage builds."
	PASSED for resource: Dockerfile.
	File: Dockerfile:1-3
Check: CKV_DOCKER_7: "Ensure the base image uses a non latest version tag"
	PASSED for resource: Dockerfile.
	File: Dockerfile:1-3
Check: CKV_DOCKER_2: "Ensure that HEALTHCHECK instructions have been added to container images"
	FAILED for resource: Dockerfile.
	File: Dockerfile:1-3

		1 | #checkov:skip=CKV_DOCKER_9
		2 | FROM alpine:3.16
		3 | RUN ls

Check: CKV_DOCKER_3: "Ensure that a user for the container has been created"
	FAILED for resource: Dockerfile.
	File: Dockerfile:1-3

		1 | #checkov:skip=CKV_DOCKER_9
		2 | FROM alpine:3.16
		3 | RUN ls

Check: CKV_DOCKER_9: "Ensure that APT isn't used"
	SKIPPED for resource: Dockerfile.
	Suppress comment: No comment provided
	File: Dockerfile:1-3
```
Hi @gruebel can you skip CKV_DOCKER_5 and check if CKV_DOCKER_9 is skipped too? Sometimes it can be reproduced this way.
thanks, that worked, in a sense of I was able to reproduce it 😄 will create a PR to fix it.

Resolving patch:
diff --git a/checkov/dockerfile/base_registry.py b/checkov/dockerfile/base_registry.py
--- a/checkov/dockerfile/base_registry.py
+++ b/checkov/dockerfile/base_registry.py
@@ -33,13 +33,16 @@ def scan(
         results: "dict[BaseCheck, _CheckResult]" = {}
         if not entity:
             return results
+
+        skipped_check_ids = {skipped_check["id"]: skipped_check for skipped_check in skipped_checks}
+
         for instruction, checks in self.checks.items():
-            skip_info: _SkippedCheck = {}
             if instruction in entity:
-
                 for check in checks:
-                    if check.id in [x['id'] for x in skipped_checks]:
-                        skip_info = [x for x in skipped_checks if x['id'] == check.id][0]
+                    skip_info: "_SkippedCheck" = {}
+                    if skipped_check_ids:
+                        if check.id in skipped_check_ids:
+                            skip_info = skipped_check_ids[check.id]
 
                     if runner_filter.should_run_check(check, report_type=CheckType.DOCKERFILE):
                         self.update_result(
@@ -54,9 +57,9 @@ def scan(
 
         for check in self.wildcard_checks["*"]:
             skip_info = {}
-            if skipped_checks:
-                if check.id in [x['id'] for x in skipped_checks]:
-                    skip_info = [x for x in skipped_checks if x['id'] == check.id][0]
+            if skipped_check_ids:
+                if check.id in skipped_check_ids:
+                    skip_info = skipped_check_ids[check.id]
 
             if runner_filter.should_run_check(check, report_type=CheckType.DOCKERFILE):
                 self.update_result(


Test patch:
diff --git a/tests/dockerfile/resources/expose_port/skip/Dockerfile b/tests/dockerfile/resources/expose_port/skip/Dockerfile
--- a/tests/dockerfile/resources/expose_port/skip/Dockerfile
+++ b/tests/dockerfile/resources/expose_port/skip/Dockerfile
@@ -1,3 +1,4 @@
+#checkov:skip=CKV_DOCKER_5: no need to skip
 FROM gliderlabs/alpine:3.3
 RUN apk --no-cache add nginx
 EXPOSE 3000 80 443 22
diff --git a/tests/dockerfile/test_runner.py b/tests/dockerfile/test_runner.py
--- a/tests/dockerfile/test_runner.py
+++ b/tests/dockerfile/test_runner.py
@@ -35,8 +35,7 @@ def test_runner_empty_dockerfile(self):
         self.assertEqual(report.parsing_errors, [])
         self.assertEqual(report.passed_checks, [])
         self.assertEqual(report.skipped_checks, [])
-        report.print_console()
-    
+
     def test_runner_name_variations(self):
         current_dir = os.path.dirname(os.path.realpath(__file__))
         valid_dir_path = current_dir + "/resources/name_variations"
@@ -46,7 +45,6 @@ def test_runner_name_variations(self):
         self.assertEqual(len(report.resources), 2)
         self.assertEqual(len([file for file in report.resources if 'Dockerfile.prod' in file]), 1)
         self.assertEqual(len([file for file in report.resources if 'prod.dockerfile' in file]), 1)
-        report.print_console()
 
     def test_runner_failing_check(self):
         current_dir = os.path.dirname(os.path.realpath(__file__))
@@ -58,7 +56,6 @@ def test_runner_failing_check(self):
         self.assertEqual(report.parsing_errors, [])
         self.assertEqual(report.passed_checks, [])
         self.assertEqual(report.skipped_checks, [])
-        report.print_console()
 
     def test_runner_honors_enforcement_rules(self):
         current_dir = os.path.dirname(os.path.realpath(__file__))
@@ -74,7 +71,6 @@ def test_runner_honors_enforcement_rules(self):
         self.assertEqual(len(report.parsing_errors), 0)
         self.assertEqual(len(report.passed_checks), 0)
         self.assertEqual(len(report.skipped_checks), 0)
-        report.print_console()
 
     def test_runner_failing_check_with_file_path(self):
         current_dir = os.path.dirname(os.path.realpath(__file__))
@@ -89,7 +85,6 @@ def test_runner_failing_check_with_file_path(self):
         self.assertEqual(report.parsing_errors, [])
         self.assertEqual(report.passed_checks, [])
         self.assertEqual(report.skipped_checks, [])
-        report.print_console()
 
     def test_runner_passing_check(self):
         current_dir = os.path.dirname(os.path.realpath(__file__))
@@ -101,19 +96,31 @@ def test_runner_passing_check(self):
         self.assertEqual(report.parsing_errors, [])
         self.assertEqual(report.failed_checks, [])
         self.assertEqual(report.skipped_checks, [])
-        report.print_console()
 
     def test_runner_skip_check(self):
-        current_dir = os.path.dirname(os.path.realpath(__file__))
-        valid_dir_path = current_dir + "/resources/expose_port/skip"
-        runner = Runner()
-        report = runner.run(root_folder=valid_dir_path, external_checks_dir=None,
-                            runner_filter=RunnerFilter(framework='all',checks=['CKV_DOCKER_1']))
-        self.assertEqual(len(report.skipped_checks), 1)
-        self.assertEqual(report.parsing_errors, [])
-        self.assertEqual(report.failed_checks, [])
-        self.assertEqual(report.passed_checks, [])
-        report.print_console()
+        #  given
+        valid_dir_path = Path(__file__).parent / "resources/expose_port/skip"
+
+        # when
+        report = Runner().run(
+            root_folder=str(valid_dir_path),
+            external_checks_dir=None,
+            runner_filter=RunnerFilter(
+                framework=["dockerfile"],
+                checks=["CKV_DOCKER_1", "CKV_DOCKER_5", "CKV_DOCKER_9"],
+            ),
+        )
+
+        # then
+        summary = report.get_summary()
+
+        self.assertEqual(summary["passed"], 1)
+        self.assertEqual(summary["failed"], 0)
+        self.assertEqual(summary["skipped"], 2)
+        self.assertEqual(summary["parsing_errors"], 0)
+
+        expected_skipped_cehcks = [record.check_id for record in report.skipped_checks]
+        self.assertCountEqual(["CKV_DOCKER_1", "CKV_DOCKER_5"], expected_skipped_cehcks)
 
     def test_record_has_severity(self):
         custom_check_id = "MY_CUSTOM_CHECK"