codeql_fail_on_error.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. #!/usr/bin/env python3
  2. #
  3. # Copyright (C) 2019 Intel Corporation. All rights reserved.
  4. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  5. #
  6. import json
  7. import sys
  8. import os
  9. import requests
  10. def fetch_dismissed_alerts(repo_name, github_token):
  11. headers = {
  12. "Authorization": f"token {github_token}",
  13. "Accept": "application/vnd.github.v3+json",
  14. }
  15. url = (
  16. f"https://api.github.com/repos/{repo_name}/code-scanning/alerts?state=dismissed"
  17. )
  18. response = requests.get(url, headers=headers)
  19. return response.json() # This assumes a successful API call
  20. def parse_location(location):
  21. path = location.get("physicalLocation", {}).get("artifactLocation", {}).get("uri")
  22. start_line = location.get("physicalLocation", {}).get("region", {}).get("startLine")
  23. column_range = (
  24. location.get("physicalLocation", {}).get("region", {}).get("startColumn"),
  25. location.get("physicalLocation", {}).get("region", {}).get("endColumn"),
  26. )
  27. return (path, start_line, column_range)
  28. def is_dismissed(rule_id, path, start_line, column_range, dismissed_alerts):
  29. for alert in dismissed_alerts:
  30. alert_rule_id = alert.get("rule", {}).get("id")
  31. alert_path = alert.get("location", {}).get("path")
  32. alert_start_line = alert.get("location", {}).get("start_line")
  33. alert_column_range = (
  34. alert.get("location", {}).get("start_column"),
  35. alert.get("location", {}).get("end_column"),
  36. )
  37. if (
  38. rule_id == alert_rule_id
  39. and path == alert_path
  40. and start_line == alert_start_line
  41. and column_range == alert_column_range
  42. ):
  43. return True
  44. return False
  45. # Return whether SARIF file contains error-level results
  46. def codeql_sarif_contain_error(filename, dismissed_alerts):
  47. has_error = False
  48. with open(filename, "r") as f:
  49. s = json.load(f)
  50. for run in s.get("runs", []):
  51. rules_metadata = run["tool"]["driver"]["rules"]
  52. if not rules_metadata:
  53. rules_metadata = run["tool"]["extensions"][0]["rules"]
  54. for res in run.get("results", []):
  55. if "ruleIndex" in res:
  56. rule_index = res["ruleIndex"]
  57. elif "rule" in res and "index" in res["rule"]:
  58. rule_index = res["rule"]["index"]
  59. else:
  60. continue
  61. # check whether it's dismissed before
  62. rule_id = res["ruleId"]
  63. path, start_line, column_range = parse_location(res["locations"][0])
  64. # the source code is from dependencies
  65. if "_deps" in path:
  66. continue
  67. if is_dismissed(rule_id, path, start_line, column_range, dismissed_alerts):
  68. print(
  69. f"====== Finding a dismissed entry: {rule_id} at {path}:{start_line} is dismissed.======"
  70. )
  71. print(res)
  72. continue
  73. try:
  74. rule_level = rules_metadata[rule_index]["defaultConfiguration"]["level"]
  75. except IndexError as e:
  76. print(e, rule_index, len(rules_metadata))
  77. else:
  78. if rule_level == "error":
  79. # very likely to be an actual error
  80. if rules_metadata[rule_index]["properties"].get("precision") in [
  81. "high",
  82. "very-high",
  83. ]:
  84. # the security severity is above medium(Common Vulnerability Scoring System (CVSS) >= 4.0)
  85. if "security-severity" in rules_metadata[rule_index][
  86. "properties"
  87. ] and (
  88. float(
  89. rules_metadata[rule_index]["properties"][
  90. "security-severity"
  91. ]
  92. )
  93. > 4.0
  94. ):
  95. print("====== Finding a likely error. ======")
  96. print(res)
  97. has_error = True
  98. return has_error
  99. if __name__ == "__main__":
  100. GITHUB_TOKEN = os.getenv("GITHUB_TOKEN")
  101. GITHUB_REPOSITORY = os.getenv("GITHUB_REPOSITORY")
  102. dismissed_alerts = fetch_dismissed_alerts(GITHUB_REPOSITORY, GITHUB_TOKEN)
  103. if codeql_sarif_contain_error(sys.argv[1], dismissed_alerts):
  104. sys.exit(1)