import difflib import glob import json import re import sys import unittest def versioncompare(safe_version, find_version): safe_version_tup = [int(x) for x in safe_version.split(".")] find_version_tup = [int(x) for x in find_version.split(".")] return find_version_tup < safe_version_tup class TestJsonLint(unittest.TestCase): @unittest.skipIf( sys.version_info < (3, 6, 0), "json.dumps force-sorts on python 3.5" ) def test_json_lint(self): valid = True for f in glob.glob("freewvsdb/*.json"): fp = open(f, encoding="ascii") orig = fp.read() fp.close() tmp = json.loads(orig) new = json.dumps(tmp, indent=2) + "\n" if orig != new: print(f"json {f} not valid") sys.stdout.writelines(difflib.unified_diff(orig, new)) valid = False self.assertTrue(valid) def test_json_values(self): jconfig = [] for cfile in glob.glob("freewvsdb/*.json"): with open(cfile, encoding="ascii") as json_file: jconfig += json.load(json_file) mkeys = {"name", "url", "safe", "vuln", "detection"} for item in jconfig: # check for all mandatory keys self.assertEqual( mkeys.intersection(item.keys()), mkeys, msg=f"Missing key in {item['name']}", ) # check we have at least one detection self.assertTrue( len(item["detection"]) >= 1, msg=f"No detection in {item['name']}" ) # vuln needs to be CVE or HTTPS URL self.assertTrue( re.match("^CVE-[0-9]*-[0-9]*$", item["vuln"]) or item["vuln"].startswith("https://"), msg=f"{item['name']}: Invalid vuln {item['vuln']}", ) # make sure safe is a version if item["safe"] != "": # we have a theoretical reDoS here, but # this is no external data, therefore ok self.assertTrue( re.match(r"^([0-9]+\.)*[0-9]+$", item["safe"]), # noqa: DUO138 msg=f"{item['name']}: Invalid safe version {item['safe']}", ) # make sure old_safe is properly sorted if "old_safe" in item: old_safe = item["old_safe"].split(",") for i in range(1, len(old_safe)): self.assertTrue( versioncompare(old_safe[i - 1], old_safe[i]), msg=f"{item['name']}: Invalid old_safe" " ordering {item['old_safe']}", ) # make sure latest is not outdated if "latest" in item and item["safe"] != "": self.assertTrue( not versioncompare(item["safe"], item["latest"]), msg=f"{item['name']}: Safe version " "{item['safe']} newer than latest" " {item['latest']}", ) # subdir needs to be integer for det in item["detection"]: self.assertTrue( isinstance(det["subdir"], int), msg=f"{item['name']}: subdir not int", ) if __name__ == "__main__": unittest.main()