| #!/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 "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:]) |