We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
CKV_AWS_40: failure even when not setting users
**Describe the issue**
The check fails when executing checkov on Terraform plan's JSON output.

**Examples**
```
resource "aws_iam_policy_attachment" "attachment" {
  ...
  roles = [...]
  # no users
}
```
JSON:
```
{
  "address": "aws_iam_policy_attachment.attachment",
  ...
  "values": {
    ...
    "roles": [
      "data-analytics@eng-0"
    ],
    "users": []
  },
...
```
The `users` field is set to `[]` in JSON, and the [check implementation](https://github.com/bridgecrewio/checkov/blob/e2538c48df14363d6ed46e5b838e19cc71ba6cbf/checkov/terraform/checks/resource/base_resource_negative_value_check.py#L39-L53) doesn't handle this scenario correctly:

https://github.com/bridgecrewio/checkov/blob/e2538c48df14363d6ed46e5b838e19cc71ba6cbf/checkov/terraform/checks/resource/base_resource_negative_value_check.py#L39-L53

**Version (please complete the following information):**
```
> checkov --version
2.0.780
```

I saw there are tests for the check implementation, but only targeting Terraform source files. Are there tests targeting JSON output from Terraform plan?

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `checkov/terraform/checks/resource/base_resource_negative_value_check.py`
Content:
```
1 from abc import abstractmethod
2 from collections.abc import Iterable
3 from typing import List, Dict, Any, Optional
4 
5 import dpath
6 
7 from checkov.common.models.consts import ANY_VALUE
8 from checkov.common.models.enums import CheckResult, CheckCategories
9 from checkov.common.util.type_forcers import force_list
10 from checkov.terraform.checks.resource.base_resource_check import BaseResourceCheck
11 from checkov.terraform.graph_builder.utils import get_referenced_vertices_in_value
12 from checkov.terraform.parser_functions import handle_dynamic_values
13 
14 
15 class BaseResourceNegativeValueCheck(BaseResourceCheck):
16     def __init__(
17         self,
18         name: str,
19         id: str,
20         categories: "Iterable[CheckCategories]",
21         supported_resources: "Iterable[str]",
22         missing_attribute_result: CheckResult = CheckResult.PASSED,
23     ) -> None:
24         super().__init__(name=name, id=id, categories=categories, supported_resources=supported_resources)
25         self.missing_attribute_result = missing_attribute_result
26 
27     def scan_resource_conf(self, conf: Dict[str, List[Any]]) -> CheckResult:
28         handle_dynamic_values(conf)
29 
30         excluded_key = self.get_excluded_key()
31         if excluded_key is not None:
32             if dpath.search(conf, excluded_key) != {}:
33                 value = dpath.get(conf, excluded_key)
34                 if isinstance(value, list) and len(value) == 1:
35                     value = value[0]
36                 if self.check_excluded_condition(value):
37                     return CheckResult.PASSED
38 
39         inspected_key = self.get_inspected_key()
40         bad_values = self.get_forbidden_values()
41         if dpath.search(conf, inspected_key) != {}:
42             value = dpath.get(conf, inspected_key)
43             if isinstance(value, list) and len(value) == 1:
44                 value = value[0]
45             if get_referenced_vertices_in_value(value=value, aliases={}, resources_types=[]):
46                 # we don't provide resources_types as we want to stay provider agnostic
47                 return CheckResult.UNKNOWN
48             if value is None:
49                 return self.missing_attribute_result
50             if value in bad_values or ANY_VALUE in bad_values:
51                 return CheckResult.FAILED
52             else:
53                 return CheckResult.PASSED
54 
55         return self.missing_attribute_result
56 
57     @abstractmethod
58     def get_inspected_key(self) -> str:
59         """
60         :return: JSONPath syntax path of the checked attribute
61         """
62         raise NotImplementedError()
63 
64     @abstractmethod
65     def get_forbidden_values(self) -> List[Any]:
66         """
67         Returns a list of vulnerable values for the inspected key, governed by provider best practices
68         """
69         raise NotImplementedError()
70 
71     def get_excluded_key(self) -> Optional[str]:
72         """
73         :return: JSONPath syntax path of the an attribute that provides exclusion condition for the inspected key
74         """
75         return None
76 
77     def check_excluded_condition(self, value: str) -> bool:
78         """
79         :param:  value: value for  excluded_key
80         :return: True if the value should exclude the check from failing if the inspected key has a bad value
81         """
82         return False
83 
84     def get_evaluated_keys(self) -> List[str]:
85         return force_list(self.get_inspected_key())
86
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/checkov/terraform/checks/resource/base_resource_negative_value_check.py b/checkov/terraform/checks/resource/base_resource_negative_value_check.py
--- a/checkov/terraform/checks/resource/base_resource_negative_value_check.py
+++ b/checkov/terraform/checks/resource/base_resource_negative_value_check.py
@@ -42,11 +42,11 @@
             value = dpath.get(conf, inspected_key)
             if isinstance(value, list) and len(value) == 1:
                 value = value[0]
+            if value is None or (isinstance(value, list) and not value):
+                return self.missing_attribute_result
             if get_referenced_vertices_in_value(value=value, aliases={}, resources_types=[]):
                 # we don't provide resources_types as we want to stay provider agnostic
                 return CheckResult.UNKNOWN
-            if value is None:
-                return self.missing_attribute_result
             if value in bad_values or ANY_VALUE in bad_values:
                 return CheckResult.FAILED
             else:

{"golden_diff": "diff --git a/checkov/terraform/checks/resource/base_resource_negative_value_check.py b/checkov/terraform/checks/resource/base_resource_negative_value_check.py\n--- a/checkov/terraform/checks/resource/base_resource_negative_value_check.py\n+++ b/checkov/terraform/checks/resource/base_resource_negative_value_check.py\n@@ -42,11 +42,11 @@\n             value = dpath.get(conf, inspected_key)\n             if isinstance(value, list) and len(value) == 1:\n                 value = value[0]\n+            if value is None or (isinstance(value, list) and not value):\n+                return self.missing_attribute_result\n             if get_referenced_vertices_in_value(value=value, aliases={}, resources_types=[]):\n                 # we don't provide resources_types as we want to stay provider agnostic\n                 return CheckResult.UNKNOWN\n-            if value is None:\n-                return self.missing_attribute_result\n             if value in bad_values or ANY_VALUE in bad_values:\n                 return CheckResult.FAILED\n             else:\n", "issue": "CKV_AWS_40: failure even when not setting users\n**Describe the issue**\r\nThe check fails when executing checkov on Terraform plan's JSON output.\r\n\r\n**Examples**\r\n```\r\nresource \"aws_iam_policy_attachment\" \"attachment\" {\r\n  ...\r\n  roles = [...]\r\n  # no users\r\n}\r\n```\r\nJSON:\r\n```\r\n{\r\n  \"address\": \"aws_iam_policy_attachment.attachment\",\r\n  ...\r\n  \"values\": {\r\n    ...\r\n    \"roles\": [\r\n      \"data-analytics@eng-0\"\r\n    ],\r\n    \"users\": []\r\n  },\r\n...\r\n```\r\nThe `users` field is set to `[]` in JSON, and the [check implementation](https://github.com/bridgecrewio/checkov/blob/e2538c48df14363d6ed46e5b838e19cc71ba6cbf/checkov/terraform/checks/resource/base_resource_negative_value_check.py#L39-L53) doesn't handle this scenario correctly:\r\n\r\nhttps://github.com/bridgecrewio/checkov/blob/e2538c48df14363d6ed46e5b838e19cc71ba6cbf/checkov/terraform/checks/resource/base_resource_negative_value_check.py#L39-L53\r\n\r\n**Version (please complete the following information):**\r\n```\r\n> checkov --version\r\n2.0.780\r\n```\r\n\r\nI saw there are tests for the check implementation, but only targeting Terraform source files. Are there tests targeting JSON output from Terraform plan?\n", "before_files": [{"content": "from abc import abstractmethod\nfrom collections.abc import Iterable\nfrom typing import List, Dict, Any, Optional\n\nimport dpath\n\nfrom checkov.common.models.consts import ANY_VALUE\nfrom checkov.common.models.enums import CheckResult, CheckCategories\nfrom checkov.common.util.type_forcers import force_list\nfrom checkov.terraform.checks.resource.base_resource_check import BaseResourceCheck\nfrom checkov.terraform.graph_builder.utils import get_referenced_vertices_in_value\nfrom checkov.terraform.parser_functions import handle_dynamic_values\n\n\nclass BaseResourceNegativeValueCheck(BaseResourceCheck):\n    def __init__(\n        self,\n        name: str,\n        id: str,\n        categories: \"Iterable[CheckCategories]\",\n        supported_resources: \"Iterable[str]\",\n        missing_attribute_result: CheckResult = CheckResult.PASSED,\n    ) -> None:\n        super().__init__(name=name, id=id, categories=categories, supported_resources=supported_resources)\n        self.missing_attribute_result = missing_attribute_result\n\n    def scan_resource_conf(self, conf: Dict[str, List[Any]]) -> CheckResult:\n        handle_dynamic_values(conf)\n\n        excluded_key = self.get_excluded_key()\n        if excluded_key is not None:\n            if dpath.search(conf, excluded_key) != {}:\n                value = dpath.get(conf, excluded_key)\n                if isinstance(value, list) and len(value) == 1:\n                    value = value[0]\n                if self.check_excluded_condition(value):\n                    return CheckResult.PASSED\n\n        inspected_key = self.get_inspected_key()\n        bad_values = self.get_forbidden_values()\n        if dpath.search(conf, inspected_key) != {}:\n            value = dpath.get(conf, inspected_key)\n            if isinstance(value, list) and len(value) == 1:\n                value = value[0]\n            if get_referenced_vertices_in_value(value=value, aliases={}, resources_types=[]):\n                # we don't provide resources_types as we want to stay provider agnostic\n                return CheckResult.UNKNOWN\n            if value is None:\n                return self.missing_attribute_result\n            if value in bad_values or ANY_VALUE in bad_values:\n                return CheckResult.FAILED\n            else:\n                return CheckResult.PASSED\n\n        return self.missing_attribute_result\n\n    @abstractmethod\n    def get_inspected_key(self) -> str:\n        \"\"\"\n        :return: JSONPath syntax path of the checked attribute\n        \"\"\"\n        raise NotImplementedError()\n\n    @abstractmethod\n    def get_forbidden_values(self) -> List[Any]:\n        \"\"\"\n        Returns a list of vulnerable values for the inspected key, governed by provider best practices\n        \"\"\"\n        raise NotImplementedError()\n\n    def get_excluded_key(self) -> Optional[str]:\n        \"\"\"\n        :return: JSONPath syntax path of the an attribute that provides exclusion condition for the inspected key\n        \"\"\"\n        return None\n\n    def check_excluded_condition(self, value: str) -> bool:\n        \"\"\"\n        :param:  value: value for  excluded_key\n        :return: True if the value should exclude the check from failing if the inspected key has a bad value\n        \"\"\"\n        return False\n\n    def get_evaluated_keys(self) -> List[str]:\n        return force_list(self.get_inspected_key())\n", "path": "checkov/terraform/checks/resource/base_resource_negative_value_check.py"}], "after_files": [{"content": "from abc import abstractmethod\nfrom collections.abc import Iterable\nfrom typing import List, Dict, Any, Optional\n\nimport dpath\n\nfrom checkov.common.models.consts import ANY_VALUE\nfrom checkov.common.models.enums import CheckResult, CheckCategories\nfrom checkov.common.util.type_forcers import force_list\nfrom checkov.terraform.checks.resource.base_resource_check import BaseResourceCheck\nfrom checkov.terraform.graph_builder.utils import get_referenced_vertices_in_value\nfrom checkov.terraform.parser_functions import handle_dynamic_values\n\n\nclass BaseResourceNegativeValueCheck(BaseResourceCheck):\n    def __init__(\n        self,\n        name: str,\n        id: str,\n        categories: \"Iterable[CheckCategories]\",\n        supported_resources: \"Iterable[str]\",\n        missing_attribute_result: CheckResult = CheckResult.PASSED,\n    ) -> None:\n        super().__init__(name=name, id=id, categories=categories, supported_resources=supported_resources)\n        self.missing_attribute_result = missing_attribute_result\n\n    def scan_resource_conf(self, conf: Dict[str, List[Any]]) -> CheckResult:\n        handle_dynamic_values(conf)\n\n        excluded_key = self.get_excluded_key()\n        if excluded_key is not None:\n            if dpath.search(conf, excluded_key) != {}:\n                value = dpath.get(conf, excluded_key)\n                if isinstance(value, list) and len(value) == 1:\n                    value = value[0]\n                if self.check_excluded_condition(value):\n                    return CheckResult.PASSED\n\n        inspected_key = self.get_inspected_key()\n        bad_values = self.get_forbidden_values()\n        if dpath.search(conf, inspected_key) != {}:\n            value = dpath.get(conf, inspected_key)\n            if isinstance(value, list) and len(value) == 1:\n                value = value[0]\n            if value is None or (isinstance(value, list) and not value):\n                return self.missing_attribute_result\n            if get_referenced_vertices_in_value(value=value, aliases={}, resources_types=[]):\n                # we don't provide resources_types as we want to stay provider agnostic\n                return CheckResult.UNKNOWN\n            if value in bad_values or ANY_VALUE in bad_values:\n                return CheckResult.FAILED\n            else:\n                return CheckResult.PASSED\n\n        return self.missing_attribute_result\n\n    @abstractmethod\n    def get_inspected_key(self) -> str:\n        \"\"\"\n        :return: JSONPath syntax path of the checked attribute\n        \"\"\"\n        raise NotImplementedError()\n\n    @abstractmethod\n    def get_forbidden_values(self) -> List[Any]:\n        \"\"\"\n        Returns a list of vulnerable values for the inspected key, governed by provider best practices\n        \"\"\"\n        raise NotImplementedError()\n\n    def get_excluded_key(self) -> Optional[str]:\n        \"\"\"\n        :return: JSONPath syntax path of the an attribute that provides exclusion condition for the inspected key\n        \"\"\"\n        return None\n\n    def check_excluded_condition(self, value: str) -> bool:\n        \"\"\"\n        :param:  value: value for  excluded_key\n        :return: True if the value should exclude the check from failing if the inspected key has a bad value\n        \"\"\"\n        return False\n\n    def get_evaluated_keys(self) -> List[str]:\n        return force_list(self.get_inspected_key())\n", "path": "checkov/terraform/checks/resource/base_resource_negative_value_check.py"}]}