Repository: bridgecrewio/checkov

Issue:
Malformed resource causes crash
**Describe the bug**
A malformed resource like this causes an exception that kills off all subsequent checks:
```terraform
resource "aws_instance" {
  ami = "amiid"
  instance_type = "t3.micro"
}
```

Example error:
```
Traceback (most recent call last):
  File "/Users/robeden/git/third-party/checkov/checkov/common/checks/base_check.py", line 62, in run
    raise e
  File "/Users/robeden/git/third-party/checkov/checkov/common/checks/base_check.py", line 42, in run
    check_result['result'] = self.scan_entity_conf(entity_configuration, entity_type)
  File "/Users/robeden/git/third-party/checkov/checkov/terraform/checks/resource/base_resource_check.py", line 16, in scan_entity_conf
    self.handle_dynamic_values(conf)
  File "/Users/robeden/git/third-party/checkov/checkov/terraform/checks/resource/base_resource_check.py", line 38, in handle_dynamic_values
    for dynamic_element in conf.get("dynamic", []):
AttributeError: 'list' object has no attribute 'get'
```

**Expected behavior**
The bad data should be skipped before being passed to checks.

Long term: it would be good to catch exceptions thrown by checks and report that something didn't work properly with the check.


Discussion:

Resolving patch:
diff --git a/checkov/common/checks/base_check_registry.py b/checkov/common/checks/base_check_registry.py
--- a/checkov/common/checks/base_check_registry.py
+++ b/checkov/common/checks/base_check_registry.py
@@ -94,6 +94,10 @@ def scan(self, scanned_file, entity, skipped_checks, runner_filter):
         (entity_type, entity_name, entity_configuration) = self.extract_entity_details(entity)
 
         results = {}
+
+        if not isinstance(entity_configuration, dict):
+            return results
+
         checks = self.get_checks(entity_type)
         for check in checks:
             skip_info = {}
diff --git a/checkov/terraform/tag_providers/__init__.py b/checkov/terraform/tag_providers/__init__.py
--- a/checkov/terraform/tag_providers/__init__.py
+++ b/checkov/terraform/tag_providers/__init__.py
@@ -10,6 +10,9 @@
 
 
 def get_resource_tags(resource_type, entity_config):
+    if not isinstance(entity_config, dict):
+        return None
+
     if '_' not in resource_type:
         return None  # probably not a resource block
     provider = resource_type[:resource_type.index('_')]


Test patch:
diff --git a/tests/terraform/runner/resources/malformed_857/main.tf b/tests/terraform/runner/resources/malformed_857/main.tf
new file mode 100644
--- /dev/null
+++ b/tests/terraform/runner/resources/malformed_857/main.tf
@@ -0,0 +1,4 @@
+resource "aws_instance" {
+  ami = "amiid"
+  instance_type = "t3.micro"
+}
diff --git a/tests/terraform/runner/test_runner.py b/tests/terraform/runner/test_runner.py
--- a/tests/terraform/runner/test_runner.py
+++ b/tests/terraform/runner/test_runner.py
@@ -495,6 +495,15 @@ def test_record_relative_path_with_abs_file(self):
             # no need to join with a '/' because the TF runner adds it to the start of the file path
             self.assertEqual(record.repo_file_path, f'/{file_rel_path}')
 
+    def test_runner_malformed_857(self):
+        current_dir = os.path.dirname(os.path.realpath(__file__))
+
+        passing_tf_file_path = current_dir + "/resources/malformed_857/main.tf"
+
+        runner = Runner()
+        runner.run(root_folder=None, external_checks_dir=None, files=[passing_tf_file_path])
+        # If we get here all is well. :-)  Failure would throw an exception.
+
     def tearDown(self):
         parser_registry.definitions_context = {}