| #!/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:") | |
| except getopt.GetoptError: | |
| show_syntax_and_exit(1) | |
| for opt, arg in opts: | |
| if opt in ("-h"): | |
| show_syntax_and_exit(0) | |
| elif opt in ("-i"): | |
| infile = arg | |
| elif opt in ("-o"): | |
| outfile = 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 "scorev4" in issue: | |
| lines += "CVSS v4 BASE SCORE: %s\n" % issue["scorev4"] | |
| 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:]) |