|
@@ -0,0 +1,145 @@
|
|
|
+#!/bin/env python3
|
|
|
+# SPDX-FileCopyrightText: OpenEmbedded Contributors
|
|
|
+#
|
|
|
+# SPDX-License-Identifier: MIT
|
|
|
+
|
|
|
+# CVE results conversion script: JSON format to text
|
|
|
+# Derived from cve-report.py from Oniro (MIT, by Huawei Inc)
|
|
|
+
|
|
|
+import sys
|
|
|
+import getopt
|
|
|
+
|
|
|
+infile = "in.json"
|
|
|
+outfile = "out.txt"
|
|
|
+
|
|
|
+
|
|
|
+def show_syntax_and_exit(code):
|
|
|
+ """
|
|
|
+ Show the program syntax and exit with an errror
|
|
|
+ Arguments:
|
|
|
+ code: the error code to return
|
|
|
+ """
|
|
|
+ print("Syntax: %s [-h] [-i inputJSONfile][-o outputfile]" % sys.argv[0])
|
|
|
+ sys.exit(code)
|
|
|
+
|
|
|
+
|
|
|
+def exit_error(code, message):
|
|
|
+ """
|
|
|
+ Show the error message and exit with an errror
|
|
|
+ Arguments:
|
|
|
+ code: the error code to return
|
|
|
+ message: the message to show
|
|
|
+ """
|
|
|
+ print("Error: %s" % message)
|
|
|
+ sys.exit(code)
|
|
|
+
|
|
|
+
|
|
|
+def parse_args(argv):
|
|
|
+ """
|
|
|
+ Parse the program arguments, put options in global variables
|
|
|
+ Arguments:
|
|
|
+ argv: program arguments
|
|
|
+ """
|
|
|
+ global infile, outfile
|
|
|
+ try:
|
|
|
+ opts, args = getopt.getopt(
|
|
|
+ argv, "hi:o:", ["help", "input", "output"]
|
|
|
+ )
|
|
|
+ except getopt.GetoptError:
|
|
|
+ show_syntax_and_exit(1)
|
|
|
+ for opt, arg in opts:
|
|
|
+ if opt in ("-h", "--help"):
|
|
|
+ show_syntax_and_exit(0)
|
|
|
+ elif opt in ("-a", "--all"):
|
|
|
+ show_all = True
|
|
|
+ show_unknown = True
|
|
|
+ elif opt in ("-i", "--input"):
|
|
|
+ infile = arg
|
|
|
+
|
|
|
+def load_json(filename):
|
|
|
+ """
|
|
|
+ Load the JSON file, return the resulting dictionary
|
|
|
+ Arguments:
|
|
|
+ filename: the file to open
|
|
|
+ Returns:
|
|
|
+ Parsed file as a dictionary
|
|
|
+ """
|
|
|
+ import json
|
|
|
+
|
|
|
+ out = {}
|
|
|
+ try:
|
|
|
+ with open(filename, "r") as f:
|
|
|
+ out = json.load(f)
|
|
|
+ except FileNotFoundError:
|
|
|
+ exit_error(1, "Input file (%s) not found" % (filename))
|
|
|
+ except json.decoder.JSONDecodeError as error:
|
|
|
+ exit_error(1, "Malformed JSON file: %s" % str(error))
|
|
|
+ return out
|
|
|
+
|
|
|
+
|
|
|
+def process_data(filename, data):
|
|
|
+ """
|
|
|
+ Write the resulting CSV with one line for each package
|
|
|
+ Arguments:
|
|
|
+ filename: the file to write to
|
|
|
+ data: dictionary from parsing the JSON file
|
|
|
+ Returns:
|
|
|
+ None
|
|
|
+ """
|
|
|
+ if not "version" in data or data["version"] != "1":
|
|
|
+ exit_error(1, "Unrecognized format version number")
|
|
|
+ if not "package" in data:
|
|
|
+ exit_error(1, "Mandatory 'package' key not found")
|
|
|
+
|
|
|
+ lines = ""
|
|
|
+ total_issue_count = 0
|
|
|
+ for package in data["package"]:
|
|
|
+ package_info = ""
|
|
|
+ keys_in_package = {"name", "layer", "version", "issue"}
|
|
|
+ if keys_in_package - package.keys():
|
|
|
+ exit_error(
|
|
|
+ 1,
|
|
|
+ "Missing a mandatory key in package: %s"
|
|
|
+ % (keys_in_package - package.keys()),
|
|
|
+ )
|
|
|
+
|
|
|
+ package_info += "LAYER: %s\n" % package["layer"]
|
|
|
+ package_info += "PACKAGE NAME: %s\n" % package["name"]
|
|
|
+ package_info += "PACKAGE VERSION: %s\n" % package["version"]
|
|
|
+
|
|
|
+ for issue in package["issue"]:
|
|
|
+ keys_in_issue = {"id", "status", "detail"}
|
|
|
+ if keys_in_issue - issue.keys():
|
|
|
+ print("Warning: Missing keys %s in 'issue' for the package '%s'"
|
|
|
+ % (keys_in_issue - issue.keys(), package["name"]))
|
|
|
+
|
|
|
+ lines += package_info
|
|
|
+ lines += "CVE: %s\n" % issue["id"]
|
|
|
+ lines += "CVE STATUS: %s\n" % issue["status"]
|
|
|
+ lines += "CVE DETAIL: %s\n" % issue["detail"]
|
|
|
+ if "description" in issue:
|
|
|
+ lines += "CVE DESCRIPTION: %s\n" % issue["description"]
|
|
|
+ if "summary" in issue:
|
|
|
+ lines += "CVE SUMMARY: %s\n" % issue["summary"]
|
|
|
+ if "scorev2" in issue:
|
|
|
+ lines += "CVSS v2 BASE SCORE: %s\n" % issue["scorev2"]
|
|
|
+ if "scorev3" in issue:
|
|
|
+ lines += "CVSS v3 BASE SCORE: %s\n" % issue["scorev3"]
|
|
|
+ if "vector" in issue:
|
|
|
+ lines += "VECTOR: %s\n" % issue["vector"]
|
|
|
+ if "vectorString" in issue:
|
|
|
+ lines += "VECTORSTRING: %s\n" % issue["vectorString"]
|
|
|
+ lines += "MORE INFORMATION: https://nvd.nist.gov/vuln/detail/%s\n" % issue["id"]
|
|
|
+ lines += "\n"
|
|
|
+
|
|
|
+ with open(filename, "w") as f:
|
|
|
+ f.write(lines)
|
|
|
+
|
|
|
+def main(argv):
|
|
|
+ parse_args(argv)
|
|
|
+ data = load_json(infile)
|
|
|
+ process_data(outfile, data)
|
|
|
+
|
|
|
+
|
|
|
+if __name__ == "__main__":
|
|
|
+ main(sys.argv[1:])
|