Repository: bridgecrewio/checkov

Issue:
Parsing error scanning terraform plan output
**Describe the bug**
Receiving a parsing error when scanning terraform plan output. parsing error is in the cloudformation scan results. the file being scanned contains no cloudformation code. the terraform_plan scan results are reporting well

**To Reproduce**
Steps to reproduce the behavior:
1. Go to a folder which contains the output of a terraform plan piped into a tf.json file
2. Run cli command  checkov -f .\tf.json
3. See error in attached scanlog.txt

**Expected behavior**
Expect to be able to scan terraform plan output without encountering a parsing error

**Screenshots**
scanlog.txt
[scanlog.txt](https://github.com/bridgecrewio/checkov/files/7464351/scanlog.txt)

ts.json - terraform plan output being scanned
[tf.json.txt](https://github.com/bridgecrewio/checkov/files/7464354/tf.json.txt)


**Desktop (please complete the following information):**
 - OS: Windows 10
 - Checkov Version 2.0.536

**Additional context**
Add any other context about the problem here (e.g. code snippets).



Discussion:
I have had this issue quite a bit as well.

Resolving patch:
diff --git a/checkov/cloudformation/parser/__init__.py b/checkov/cloudformation/parser/__init__.py
--- a/checkov/cloudformation/parser/__init__.py
+++ b/checkov/cloudformation/parser/__init__.py
@@ -1,5 +1,5 @@
 import logging
-from typing import Tuple, List, Union, Dict
+from typing import Tuple, List, Union, Dict, Optional
 
 from checkov.cloudformation.parser import cfn_yaml
 from checkov.common.parsers.json import parse as json_parse
@@ -11,13 +11,19 @@
 LOGGER = logging.getLogger(__name__)
 
 
-def parse(filename: str, out_parsing_errors: Dict[str, str] = {}) -> Union[Tuple[DictNode, List[Tuple[int, str]]], Tuple[None, None]]:
+def parse(
+    filename: str, out_parsing_errors: Optional[Dict[str, str]] = None
+) -> Union[Tuple[DictNode, List[Tuple[int, str]]], Tuple[None, None]]:
     """
-        Decode filename into an object
+    Decode filename into an object
     """
     template = None
     template_lines = None
     error = None
+
+    if out_parsing_errors is None:
+        out_parsing_errors = {}
+
     try:
         (template, template_lines) = cfn_yaml.load(filename)
     except IOError as err:
@@ -34,6 +40,10 @@ def parse(filename: str, out_parsing_errors: Dict[str, str] = {}) -> Union[Tuple
         error = f"Cannot read file contents: {filename} - {err}"
         LOGGER.error(error)
     except cfn_yaml.CfnParseError as err:
+        if "Null value at" in err.message:
+            LOGGER.info(f"Null values do not exist in CFN templates: {filename} - {err}")
+            return None, None
+
         error = f"Parsing error in file: {filename} - {err}"
         LOGGER.info(error)
     except ValueError as err:
@@ -56,8 +66,8 @@ def parse(filename: str, out_parsing_errors: Dict[str, str] = {}) -> Union[Tuple
     if isinstance(template, dict):
         resources = template.get(TemplateSections.RESOURCES.value, None)
         if resources:
-            if '__startline__' in resources:
-                del resources['__startline__']
-            if '__endline__' in resources:
-                del resources['__endline__']
+            if "__startline__" in resources:
+                del resources["__startline__"]
+            if "__endline__" in resources:
+                del resources["__endline__"]
     return template, template_lines
diff --git a/checkov/cloudformation/parser/cfn_yaml.py b/checkov/cloudformation/parser/cfn_yaml.py
--- a/checkov/cloudformation/parser/cfn_yaml.py
+++ b/checkov/cloudformation/parser/cfn_yaml.py
@@ -3,6 +3,9 @@
 SPDX-License-Identifier: MIT-0
 """
 import logging
+from pathlib import Path
+from typing import List, Tuple
+
 from yaml import MappingNode
 from yaml import ScalarNode
 from yaml import SequenceNode
@@ -199,17 +202,13 @@ def loads(yaml_string, fname=None):
     return template
 
 
-def load(filename):
+def load(filename: str) -> Tuple[DictNode, List[Tuple[int, str]]]:
     """
     Load the given YAML file
     """
 
-    content = ''
-
-    with open(filename) as fp:
-        content = fp.read()
-        fp.seek(0)
-        file_lines = [(ind + 1, line) for (ind, line) in
-                      list(enumerate(fp.readlines()))]
+    file_path = Path(filename)
+    content = file_path.read_text()
+    file_lines = [(idx + 1, line) for idx, line in enumerate(content.splitlines(keepends=True))]
 
     return (loads(content, filename), file_lines)


Test patch:
diff --git a/tests/cloudformation/parser/test_cfn_json.py b/tests/cloudformation/parser/test_cfn_json.py
--- a/tests/cloudformation/parser/test_cfn_json.py
+++ b/tests/cloudformation/parser/test_cfn_json.py
@@ -1,6 +1,7 @@
 import os
 import unittest
 from json import JSONDecodeError
+from pathlib import Path
 
 from checkov.common.parsers.json import load
 from checkov.cloudformation.runner import Runner
@@ -23,6 +24,16 @@ def test_fail_parsing(self):
         test_files = current_dir + "/fail.json"
         self.assertRaises(JSONDecodeError, load, test_files)
 
+    def test_skip_tf_plan_file(self):
+        # given
+        test_file = Path(__file__).parent / "tfplan.json"
+
+        # when
+        report = Runner().run(None, files=[str(test_file)], runner_filter=RunnerFilter())
+
+        # then
+        self.assertEqual(0, len(report.parsing_errors))
+
 
 if __name__ == '__main__':
     unittest.main()
diff --git a/tests/cloudformation/parser/tfplan.json b/tests/cloudformation/parser/tfplan.json
new file mode 100644
--- /dev/null
+++ b/tests/cloudformation/parser/tfplan.json
@@ -0,0 +1,115 @@
+{
+  "format_version": "0.1",
+  "terraform_version": "0.12.5",
+  "planned_values": {
+    "root_module": {
+      "resources": [
+        {
+          "address": "aws_s3_bucket.bucket",
+          "mode": "managed",
+          "type": "aws_s3_bucket",
+          "name": "bucket",
+          "provider_name": "aws",
+          "schema_version": 0,
+          "values": {
+            "acl": "private",
+            "bucket": "bucket",
+            "bucket_prefix": null,
+            "cors_rule": [],
+            "force_destroy": false,
+            "grant": [],
+            "lifecycle_rule": [],
+            "logging": [],
+            "object_lock_configuration": [],
+            "policy": null,
+            "replication_configuration": [],
+            "server_side_encryption_configuration": [],
+            "tags": null,
+            "website": []
+          }
+        }
+      ]
+    }
+  },
+  "resource_changes": [
+    {
+      "address": "aws_s3_bucket.bucket",
+      "mode": "managed",
+      "type": "aws_s3_bucket",
+      "name": "bucket",
+      "provider_name": "aws",
+      "change": {
+        "actions": [
+          "create"
+        ],
+        "before": null,
+        "after": {
+          "acl": "private",
+          "bucket": "bucket",
+          "bucket_prefix": null,
+          "cors_rule": [],
+          "force_destroy": false,
+          "grant": [],
+          "lifecycle_rule": [],
+          "logging": [],
+          "object_lock_configuration": [],
+          "policy": null,
+          "replication_configuration": [],
+          "server_side_encryption_configuration": [],
+          "tags": null,
+          "website": []
+        },
+        "after_unknown": {
+          "acceleration_status": true,
+          "arn": true,
+          "bucket_domain_name": true,
+          "bucket_regional_domain_name": true,
+          "cors_rule": [],
+          "grant": [],
+          "hosted_zone_id": true,
+          "id": true,
+          "lifecycle_rule": [],
+          "logging": [],
+          "object_lock_configuration": [],
+          "region": true,
+          "replication_configuration": [],
+          "request_payer": true,
+          "server_side_encryption_configuration": [],
+          "versioning": true,
+          "website": [],
+          "website_domain": true,
+          "website_endpoint": true
+        }
+      }
+    }
+  ],
+  "configuration": {
+    "provider_config": {
+      "aws": {
+        "name": "aws",
+        "expressions": {
+          "region": {
+            "constant_value": "us-west-2"
+          }
+        }
+      }
+    },
+    "root_module": {
+      "resources": [
+        {
+          "address": "aws_s3_bucket.bucket",
+          "mode": "managed",
+          "type": "aws_s3_bucket",
+          "name": "bucket",
+          "provider_config_key": "aws",
+          "expressions": {
+            "bucket": {
+              "constant_value": "bucket"
+            }
+          },
+          "schema_version": 0
+        }
+      ]
+    }
+  }
+}