We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Update sigma2attack to the latest navigator version
the data generated for navigator is not up to date.

![Clipboard - 5 novembre 2020 15_38](https://user-images.githubusercontent.com/1626464/98255016-3675e080-1f7d-11eb-8490-321a7a053c04.png)

specs on [att&ck navigator github](https://github.com/mitre-attack/attack-navigator/blob/master/layers/LAYERFORMATv4.md)


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `tools/sigma/sigma2attack.py`
Content:
```
1 #!/usr/bin/env python3
2 
3 import argparse
4 import glob
5 import json
6 import os
7 import sys
8 
9 import yaml
10 
11 def main():
12     parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
13     parser.add_argument("--rules-directory", "-d", dest="rules_dir", default="rules", help="Directory to read rules from")
14     parser.add_argument("--out-file", "-o", dest="out_file", default="heatmap.json", help="File to write the JSON layer to")
15     parser.add_argument("--no-comment", dest="no_comment", action="store_true", help="Don't store rule names in comments")
16     args = parser.parse_args()
17 
18     rule_files = glob.glob(os.path.join(args.rules_dir, "**/*.yml"), recursive=True)
19     techniques_to_rules = {}
20     curr_max_technique_count = 0
21     num_rules_used = 0
22     for rule_file in rule_files:
23         try:
24             rule = yaml.safe_load(open(rule_file).read())
25         except yaml.YAMLError:
26             sys.stderr.write("Ignoring rule " + rule_file + " (parsing failed)\n")
27             continue
28         if "tags" not in rule:
29             sys.stderr.write("Ignoring rule " + rule_file + " (no tags)\n")
30             continue
31         tags = rule["tags"]
32         for tag in tags:
33             if tag.lower().startswith("attack.t"):
34                 technique_id = tag[len("attack."):].upper()
35                 num_rules_used += 1
36                 if technique_id not in techniques_to_rules:
37                     techniques_to_rules[technique_id] = []
38                 techniques_to_rules[technique_id].append(os.path.basename(rule_file))
39                 curr_max_technique_count = max(curr_max_technique_count, len(techniques_to_rules[technique_id]))
40 
41 
42     scores = []
43     for technique in techniques_to_rules:
44         entry = {
45             "techniqueID": technique, 
46             "score": len(techniques_to_rules[technique]), 
47         }
48         if not args.no_comment:
49             entry["comment"] = "\n".join(techniques_to_rules[technique])
50 
51         scores.append(entry)
52 
53     output = {
54         "domain": "mitre-enterprise",
55         "name": "Sigma rules heatmap",
56         "gradient": {
57             "colors": [
58                 "#ffffff",
59                 "#ff6666"
60             ],
61             "maxValue": curr_max_technique_count,
62             "minValue": 0
63         },
64         "version": "2.2", 
65         "techniques": scores,
66     }
67 
68     with open(args.out_file, "w") as f:
69         f.write(json.dumps(output))
70         print("[*] Layer file written in " + args.out_file + " (" + str(num_rules_used) + " rules)")
71 
72 if __name__ == "__main__":
73     main()
74
```
--- 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/tools/sigma/sigma2attack.py b/tools/sigma/sigma2attack.py
--- a/tools/sigma/sigma2attack.py
+++ b/tools/sigma/sigma2attack.py
@@ -21,7 +21,7 @@
     num_rules_used = 0
     for rule_file in rule_files:
         try:
-            rule = yaml.safe_load(open(rule_file).read())
+            rule = yaml.safe_load(open(rule_file, encoding="utf-8").read())
         except yaml.YAMLError:
             sys.stderr.write("Ignoring rule " + rule_file + " (parsing failed)\n")
             continue
@@ -61,7 +61,10 @@
             "maxValue": curr_max_technique_count,
             "minValue": 0
         },
-        "version": "2.2", 
+        "versions": {
+            "navigator": "4.0",
+            "layer": "4.0"
+        },
         "techniques": scores,
     }

{"golden_diff": "diff --git a/tools/sigma/sigma2attack.py b/tools/sigma/sigma2attack.py\n--- a/tools/sigma/sigma2attack.py\n+++ b/tools/sigma/sigma2attack.py\n@@ -21,7 +21,7 @@\n     num_rules_used = 0\n     for rule_file in rule_files:\n         try:\n-            rule = yaml.safe_load(open(rule_file).read())\n+            rule = yaml.safe_load(open(rule_file, encoding=\"utf-8\").read())\n         except yaml.YAMLError:\n             sys.stderr.write(\"Ignoring rule \" + rule_file + \" (parsing failed)\\n\")\n             continue\n@@ -61,7 +61,10 @@\n             \"maxValue\": curr_max_technique_count,\n             \"minValue\": 0\n         },\n-        \"version\": \"2.2\", \n+        \"versions\": {\n+            \"navigator\": \"4.0\",\n+            \"layer\": \"4.0\"\n+        },\n         \"techniques\": scores,\n     }\n", "issue": "Update sigma2attack to the latest navigator version\nthe data generated for navigator is not up to date.\r\n\r\n![Clipboard - 5 novembre 2020 15_38](https://user-images.githubusercontent.com/1626464/98255016-3675e080-1f7d-11eb-8490-321a7a053c04.png)\r\n\r\nspecs on [att&ck navigator github](https://github.com/mitre-attack/attack-navigator/blob/master/layers/LAYERFORMATv4.md)\r\n\n", "before_files": [{"content": "#!/usr/bin/env python3\n\nimport argparse\nimport glob\nimport json\nimport os\nimport sys\n\nimport yaml\n\ndef main():\n    parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)\n    parser.add_argument(\"--rules-directory\", \"-d\", dest=\"rules_dir\", default=\"rules\", help=\"Directory to read rules from\")\n    parser.add_argument(\"--out-file\", \"-o\", dest=\"out_file\", default=\"heatmap.json\", help=\"File to write the JSON layer to\")\n    parser.add_argument(\"--no-comment\", dest=\"no_comment\", action=\"store_true\", help=\"Don't store rule names in comments\")\n    args = parser.parse_args()\n\n    rule_files = glob.glob(os.path.join(args.rules_dir, \"**/*.yml\"), recursive=True)\n    techniques_to_rules = {}\n    curr_max_technique_count = 0\n    num_rules_used = 0\n    for rule_file in rule_files:\n        try:\n            rule = yaml.safe_load(open(rule_file).read())\n        except yaml.YAMLError:\n            sys.stderr.write(\"Ignoring rule \" + rule_file + \" (parsing failed)\\n\")\n            continue\n        if \"tags\" not in rule:\n            sys.stderr.write(\"Ignoring rule \" + rule_file + \" (no tags)\\n\")\n            continue\n        tags = rule[\"tags\"]\n        for tag in tags:\n            if tag.lower().startswith(\"attack.t\"):\n                technique_id = tag[len(\"attack.\"):].upper()\n                num_rules_used += 1\n                if technique_id not in techniques_to_rules:\n                    techniques_to_rules[technique_id] = []\n                techniques_to_rules[technique_id].append(os.path.basename(rule_file))\n                curr_max_technique_count = max(curr_max_technique_count, len(techniques_to_rules[technique_id]))\n\n\n    scores = []\n    for technique in techniques_to_rules:\n        entry = {\n            \"techniqueID\": technique, \n            \"score\": len(techniques_to_rules[technique]), \n        }\n        if not args.no_comment:\n            entry[\"comment\"] = \"\\n\".join(techniques_to_rules[technique])\n\n        scores.append(entry)\n\n    output = {\n        \"domain\": \"mitre-enterprise\",\n        \"name\": \"Sigma rules heatmap\",\n        \"gradient\": {\n            \"colors\": [\n                \"#ffffff\",\n                \"#ff6666\"\n            ],\n            \"maxValue\": curr_max_technique_count,\n            \"minValue\": 0\n        },\n        \"version\": \"2.2\", \n        \"techniques\": scores,\n    }\n\n    with open(args.out_file, \"w\") as f:\n        f.write(json.dumps(output))\n        print(\"[*] Layer file written in \" + args.out_file + \" (\" + str(num_rules_used) + \" rules)\")\n\nif __name__ == \"__main__\":\n    main()\n", "path": "tools/sigma/sigma2attack.py"}], "after_files": [{"content": "#!/usr/bin/env python3\n\nimport argparse\nimport glob\nimport json\nimport os\nimport sys\n\nimport yaml\n\ndef main():\n    parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)\n    parser.add_argument(\"--rules-directory\", \"-d\", dest=\"rules_dir\", default=\"rules\", help=\"Directory to read rules from\")\n    parser.add_argument(\"--out-file\", \"-o\", dest=\"out_file\", default=\"heatmap.json\", help=\"File to write the JSON layer to\")\n    parser.add_argument(\"--no-comment\", dest=\"no_comment\", action=\"store_true\", help=\"Don't store rule names in comments\")\n    args = parser.parse_args()\n\n    rule_files = glob.glob(os.path.join(args.rules_dir, \"**/*.yml\"), recursive=True)\n    techniques_to_rules = {}\n    curr_max_technique_count = 0\n    num_rules_used = 0\n    for rule_file in rule_files:\n        try:\n            rule = yaml.safe_load(open(rule_file, encoding=\"utf-8\").read())\n        except yaml.YAMLError:\n            sys.stderr.write(\"Ignoring rule \" + rule_file + \" (parsing failed)\\n\")\n            continue\n        if \"tags\" not in rule:\n            sys.stderr.write(\"Ignoring rule \" + rule_file + \" (no tags)\\n\")\n            continue\n        tags = rule[\"tags\"]\n        for tag in tags:\n            if tag.lower().startswith(\"attack.t\"):\n                technique_id = tag[len(\"attack.\"):].upper()\n                num_rules_used += 1\n                if technique_id not in techniques_to_rules:\n                    techniques_to_rules[technique_id] = []\n                techniques_to_rules[technique_id].append(os.path.basename(rule_file))\n                curr_max_technique_count = max(curr_max_technique_count, len(techniques_to_rules[technique_id]))\n\n\n    scores = []\n    for technique in techniques_to_rules:\n        entry = {\n            \"techniqueID\": technique, \n            \"score\": len(techniques_to_rules[technique]), \n        }\n        if not args.no_comment:\n            entry[\"comment\"] = \"\\n\".join(techniques_to_rules[technique])\n\n        scores.append(entry)\n\n    output = {\n        \"domain\": \"mitre-enterprise\",\n        \"name\": \"Sigma rules heatmap\",\n        \"gradient\": {\n            \"colors\": [\n                \"#ffffff\",\n                \"#ff6666\"\n            ],\n            \"maxValue\": curr_max_technique_count,\n            \"minValue\": 0\n        },\n        \"versions\": {\n            \"navigator\": \"4.0\",\n            \"layer\": \"4.0\"\n        },\n        \"techniques\": scores,\n    }\n\n    with open(args.out_file, \"w\") as f:\n        f.write(json.dumps(output))\n        print(\"[*] Layer file written in \" + args.out_file + \" (\" + str(num_rules_used) + \" rules)\")\n\nif __name__ == \"__main__\":\n    main()\n", "path": "tools/sigma/sigma2attack.py"}]}