prompt: 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()
  
  ```
  
golden_diff: 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,
       }
  
verification_info: {"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"}]}