Repository: bridgecrewio/checkov

Issue:
Parsing does not work with terraform files being encoded with UTF-8/BOM
**Example**
Create an empty file with Unix line endings and save it in UTF-8 encoding with a BOM. Running checkov will fail.
Removing BOM will resolve the issue

**Stacktrace**
```
Traceback (most recent call last):
  File "/usr/local/lib/python3.8/dist-packages/lark/lexer.py", line 536, in lex
    token = self.root_lexer.next_token(lexer_state, parser_state)
  File "/usr/local/lib/python3.8/dist-packages/lark/lexer.py", line 466, in next_token
    raise UnexpectedCharacters(lex_state.text, line_ctr.char_pos, line_ctr.line, line_ctr.column,
lark.exceptions.UnexpectedCharacters: <unprintable UnexpectedCharacters object>

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.8/dist-packages/checkov/terraform/parser.py", line 742, in _load_or_die_quietly
    raw_data = hcl2.load(f)
```


Discussion:
@andreireinus thanks for reaching out. I think this should be no problem to fix on our side.

Resolving patch:
diff --git a/checkov/terraform/parser.py b/checkov/terraform/parser.py
--- a/checkov/terraform/parser.py
+++ b/checkov/terraform/parser.py
@@ -735,7 +735,7 @@ def _load_or_die_quietly(
     try:
         logging.debug(f"Parsing {file_path}")
 
-        with open(file_path, "r") as f:
+        with open(file_path, "r", encoding="utf-8-sig") as f:
             if file_name.endswith(".json"):
                 return json.load(f)
             else:


Test patch:
diff --git a/tests/terraform/parser/resources/file_bom/with_bom.tf b/tests/terraform/parser/resources/file_bom/with_bom.tf
new file mode 100644
--- /dev/null
+++ b/tests/terraform/parser/resources/file_bom/with_bom.tf
@@ -0,0 +1,3 @@
+﻿resource "aws_s3_bucket" "example" {
+  bucket = "example"
+}
diff --git a/tests/terraform/parser/resources/file_bom/without_bom.tf b/tests/terraform/parser/resources/file_bom/without_bom.tf
new file mode 100644
--- /dev/null
+++ b/tests/terraform/parser/resources/file_bom/without_bom.tf
@@ -0,0 +1,3 @@
+resource "aws_s3_bucket" "example" {
+  bucket = "example"
+}
diff --git a/tests/terraform/parser/test_parser_internals.py b/tests/terraform/parser/test_parser_internals.py
--- a/tests/terraform/parser/test_parser_internals.py
+++ b/tests/terraform/parser/test_parser_internals.py
@@ -1,9 +1,56 @@
-import unittest
+from pathlib import Path
 
-from checkov.terraform import parser
+from checkov.common.util.parser_utils import eval_string
+from checkov.terraform.parser import _load_or_die_quietly
 
 
-class TestParserInternals(unittest.TestCase):
-    def test_eval_string_to_list(self):
-        expected = ["a", "b", "c"]
-        assert parser.eval_string('["a", "b", "c"]') == expected
+def test_eval_string_to_list():
+    # given
+    expected = ["a", "b", "c"]
+
+    # when
+    actual = eval_string('["a", "b", "c"]')
+
+    assert actual == expected
+
+
+def test__load_or_die_quietly_with_bom():
+    # given
+    test_file = Path(__file__).parent / "resources/file_bom/with_bom.tf"
+    parsing_errors = {}
+
+    # when
+    definition = _load_or_die_quietly(file=test_file, parsing_errors=parsing_errors)
+
+    # then
+    assert not parsing_errors
+    assert definition == {
+        "resource": [
+            {
+                "aws_s3_bucket": {
+                    "example": {"bucket": ["example"], "__start_line__": 1, "__end_line__": 3},
+                },
+            }
+        ]
+    }
+
+
+def test__load_or_die_quietly_without_bom():
+    # given
+    test_file = Path(__file__).parent / "resources/file_bom/without_bom.tf"
+    parsing_errors = {}
+
+    # when
+    definition = _load_or_die_quietly(file=test_file, parsing_errors=parsing_errors)
+
+    # then
+    assert not parsing_errors
+    assert definition == {
+        "resource": [
+            {
+                "aws_s3_bucket": {
+                    "example": {"bucket": ["example"], "__start_line__": 1, "__end_line__": 3},
+                },
+            }
+        ]
+    }