예제 #1
0
 def test_update_flags(self):
     self.assertNotEqual(
         main(["cve-bin-tool", "-x", "-u", "never", self.tempdir]), 0)
     self.assertNotEqual(
         main(["cve-bin-tool", "-x", "--update", "daily", self.tempdir]), 0)
     self.assertNotEqual(
         main(["cve-bin-tool", "-x", "-u", "now", self.tempdir]), 0)
     with self.assertRaises(SystemExit) as exit:
         main(["cve-bin-tool", "-u", "whatever", self.tempdir])
     self.assertEqual(exit.exception.code, -2)
예제 #2
0
    def test_runs(self):
        logger = logging.getLogger()
        test_path = os.path.join(os.path.abspath(os.path.dirname(__file__)), "csv")
        runs = ["expat", "libgcrypt", "openssl", "sqlite"]
        skip_checkers = ["systemd", "xerces", "xml2", "kerberos"]
        with self.assertLogs(logger, logging.INFO) as cm:
            main(["cve-bin-tool", test_path, "-r", ",".join(runs)])
        self.check_checkers_log(cm, skip_checkers, runs)

        runs, skip_checkers = skip_checkers, runs
        with self.assertLogs(logger, logging.INFO) as cm:
            main(["cve-bin-tool", test_path, "-r", ",".join(runs)])
        self.check_checkers_log(cm, skip_checkers, runs)
예제 #3
0
    def test_update(self):
        logger = logging.getLogger()
        test_path = os.path.join(os.path.abspath(os.path.dirname(__file__)),
                                 "csv")

        with self.assertLogs(logger, logging.INFO) as cm:
            main(["cve-bin-tool", "-u", "never", test_path])
        self.assertTrue(
            "INFO:cve_bin_tool.CVEDB:Updating CVE data. This will take a few minutes."
            not in cm.output)

        with self.assertLogs(logger, logging.INFO) as cm:
            main(["cve-bin-tool", "-u", "daily", test_path])
        self.assertTrue((
            "INFO:cve_bin_tool.CVEDB:Using cached CVE data (<24h old). Use -u now to update immediately."
            in cm.output
        ) or (
            "INFO:cve_bin_tool.CVEDB:Updating CVE data. This will take a few minutes."
            in cm.output))

        with self.assertLogs(logger, logging.INFO) as cm:
            main(["cve-bin-tool", "-u", "now", test_path])
        db_path = os.path.join(os.path.expanduser("~"), ".cache", "cvedb")
        self.assertTrue(
            ("WARNING:cve_bin_tool.CVEDB:Deleting cachedir " + db_path
             in cm.output) and
            ("INFO:cve_bin_tool.CVEDB:Updating CVE data. This will take a few minutes."
             in cm.output))

        with self.assertLogs(logger, logging.INFO) as cm:
            main(["cve-bin-tool", "-u", "latest", test_path])
        self.assertTrue(
            "INFO:cve_bin_tool.CVEDB:Updating CVE data. This will take a few minutes."
            in cm.output)
예제 #4
0
    def test_runs(self, caplog):
        test_path = os.path.join(os.path.abspath(os.path.dirname(__file__)),
                                 "csv")

        runs = ["expat", "libgcrypt", "openssl", "sqlite"]
        skip_checkers = ["systemd", "xerces", "xml2", "kerberos"]
        with caplog.at_level(logging.INFO):
            main(["cve-bin-tool", test_path, "-r", ",".join(runs)])
        self.check_checkers_log(caplog, skip_checkers, runs)

        runs, skip_checkers = skip_checkers, runs
        with caplog.at_level(logging.INFO):
            main(["cve-bin-tool", test_path, "-r", ",".join(runs)])
        self.check_checkers_log(caplog, skip_checkers, runs)
예제 #5
0
    def test_extract_bad_zip_messages(self, caplog):
        """Test that bad zip files are logged as extraction failed, but
        bad exe files produce no such message"""
        bad_exe_file = os.path.join(self.tempdir, "empty-file.exe")
        # creates an empty, invalid .exe test file
        open(bad_exe_file, "w").close()
        with caplog.at_level(logging.WARNING):
            main(["cve-bin-tool", bad_exe_file])
        assert "Failure extracting" not in caplog.text

        bad_zip_file = os.path.join(self.tempdir, "empty-file.zip")
        open(bad_zip_file, "w").close()
        with caplog.at_level(logging.WARNING):
            main(["cve-bin-tool", bad_zip_file])
        assert "Failure extracting" in caplog.text
예제 #6
0
    def test_quiet_mode(self):
        """ Test that an quite mode isn't generating any output """
        logger = logging.getLogger()

        # build the test file in test/binaries
        binaries_path = os.path.join(
            os.path.abspath(os.path.dirname(__file__)), "binaries")
        filename = "test-python-3.7.1.out"
        subprocess.call(["make", filename], cwd=binaries_path)

        with self.assertLogs(logger, logging.INFO) as cm:
            main(["cve-bin-tool", "-q", os.path.join(binaries_path, filename)])
            logger.info("test")

        self.assertEqual(["INFO:root:test"], cm.output)
예제 #7
0
 def test_update_flags(self):
     assert (main([
         "cve-bin-tool", "-x", "-u", "never", "-n", "json", self.tempdir
     ]) != 0)
     assert (main([
         "cve-bin-tool", "-x", "--update", "daily", "-n", "json",
         self.tempdir
     ]) != 0)
     assert (main([
         "cve-bin-tool", "-x", "-u", "now", "-n", "json", self.tempdir
     ]) != 0)
     with pytest.raises(SystemExit) as e:
         main(
             ["cve-bin-tool", "-u", "whatever", "-n", "json", self.tempdir])
     assert e.value.args[0] == ERROR_CODES[SystemExit]
예제 #8
0
    def test_update(self, caplog):
        test_path = os.path.join(os.path.abspath(os.path.dirname(__file__)),
                                 "csv")

        with caplog.at_level(logging.INFO):
            main(["cve-bin-tool", "-u", "never", "-n", "json", test_path])
        assert (
            "cve_bin_tool",
            logging.WARNING,
            "Not verifying CVE DB cache",
        ) in caplog.record_tuples
        caplog.clear()

        with caplog.at_level(logging.DEBUG):
            main([
                "cve-bin-tool", "-l", "debug", "-u", "daily", "-n", "json",
                test_path
            ])
        assert (
            "cve_bin_tool.CVEDB",
            logging.INFO,
            "Using cached CVE data (<24h old). Use -u now to update immediately.",
        ) in caplog.record_tuples or (
            "cve_bin_tool.CVEDB",
            logging.DEBUG,
            "Updating CVE data. This will take a few minutes.",
        ) in caplog.record_tuples
        caplog.clear()

        with caplog.at_level(logging.DEBUG):
            main([
                "cve-bin-tool", "-l", "debug", "-u", "now", "-n", "json",
                test_path
            ])
        db_path = DISK_LOCATION_DEFAULT
        assert (
            "cve_bin_tool.CVEDB",
            logging.WARNING,
            f"Updating cachedir {db_path}",
        ) in caplog.record_tuples and (
            "cve_bin_tool.CVEDB",
            logging.DEBUG,
            "Updating CVE data. This will take a few minutes.",
        ) in caplog.record_tuples
        caplog.clear()

        with caplog.at_level(logging.DEBUG):
            main([
                "cve-bin-tool", "-l", "debug", "-u", "latest", "-n", "json",
                test_path
            ])
        assert (
            "cve_bin_tool.CVEDB",
            logging.DEBUG,
            "Updating CVE data. This will take a few minutes.",
        ) in caplog.record_tuples
        caplog.clear()
예제 #9
0
 def test_binary_curl_7_20_0(self):
     """ Extracting from rpm and scanning curl-7.20.0 """
     with Extractor()() as ectx:
         extracted_path = ectx.extract(os.path.join(self.tempdir,
                                                    CURL_7_20_0_RPM))
         self.assertNotEqual(main(['cve-bin-tool', '-l', 'debug',
                                   os.path.join(extracted_path, 'usr', 'bin',
                                                'curl')]), 0)
예제 #10
0
    def test_skips(self):
        """Tests the skips option"""

        logger = logging.getLogger()
        test_path = os.path.join(os.path.abspath(os.path.dirname(__file__)),
                                 "csv")

        skip_checkers = ["systemd", "xerces", "xml2", "kerberos"]
        include_checkers = ["expat", "libgcrypt", "openssl", "sqlite"]

        with self.assertLogs(logger, logging.INFO) as cm:
            main(["cve-bin-tool", test_path, "-s", ",".join(skip_checkers)])

        # The final log has all the checkers detected
        final_log = [i for i in cm.output if "Checkers:" in i]
        self.assertTrue(
            len(final_log) > 0, "Could not find checkers line in log")
        final_log = final_log[0]
        for checker in skip_checkers:
            self.assertTrue(checker not in final_log,
                            "found skipped checker {}".format(checker))

        for checker in include_checkers:
            self.assertTrue(
                checker in final_log,
                "could not find expected checker {}".format(checker),
            )

        # swap skip_checkers and include_checkers
        include_checkers, skip_checkers = skip_checkers, include_checkers
        with self.assertLogs(logger, logging.INFO) as cm:
            main(["cve-bin-tool", test_path, "-s", ",".join(skip_checkers)])

        final_log = [i for i in cm.output if "Checkers:" in i]
        self.assertTrue(
            len(final_log) > 0, "Could not find checkers line in log")
        final_log = final_log[0]
        for checker in skip_checkers:
            self.assertTrue(checker not in final_log,
                            "found skipped checker {}".format(checker))

        for checker in include_checkers:
            self.assertTrue(
                checker in final_log,
                "could not find expected checker {}".format(checker),
            )
예제 #11
0
    def test_skips(self, caplog):
        """Tests the skips option"""

        test_path = os.path.join(os.path.abspath(os.path.dirname(__file__)),
                                 "csv")

        skip_checkers = ["systemd", "xerces", "xml2", "kerberos"]
        include_checkers = ["expat", "libgcrypt", "openssl", "sqlite"]
        with caplog.at_level(logging.INFO):
            main(["cve-bin-tool", test_path, "-s", ",".join(skip_checkers)])
        self.check_checkers_log(caplog, skip_checkers, include_checkers)

        # swap skip_checkers and include_checkers
        include_checkers, skip_checkers = skip_checkers, include_checkers
        with caplog.at_level(logging.INFO):
            main(["cve-bin-tool", test_path, "-s", ",".join(skip_checkers)])
        self.check_checkers_log(caplog, skip_checkers, include_checkers)
예제 #12
0
    def test_SBOM(self, caplog):
        # check sbom file option
        SBOM_PATH = os.path.join(os.path.abspath(os.path.dirname(__file__)),
                                 "sbom")

        with caplog.at_level(logging.INFO):
            main([
                "cve-bin-tool",
                "--sbom",
                "spdx",
                "--sbom-file",
                os.path.join(SBOM_PATH, "spdx_test.spdx"),
            ])
        # Verify that one product detected
        assert (
            "cve_bin_tool",
            logging.INFO,
            "There are 1 products with known CVEs detected",
        ) in caplog.record_tuples
예제 #13
0
    def test_unknown_warning(self):
        """ Test that an "UNKNOWN" file generates a warning """
        logger = logging.getLogger()

        # build the unknown test file in test/binaries
        binaries_path = os.path.join(
            os.path.abspath(os.path.dirname(__file__)), "binaries")
        unknown_filename = "test-png-unknown.out"
        subprocess.call(["make", unknown_filename], cwd=binaries_path)

        # Run against the "unknown" file
        with self.assertLogs(logger, logging.INFO) as cm:
            main([
                "cve-bin-tool",
                os.path.join(binaries_path, unknown_filename)
            ])

        warnings = [i for i in cm.output if "WARNING" in i]
        self.assertTrue(len(warnings) > 0)
        self.assertTrue("was detected with version UNKNOWN" in warnings[0])
예제 #14
0
 def test_binary_curl_7_20_0(self):
     """ Extracting from rpm and scanning curl-7.20.0 """
     with Extractor() as ectx:
         extracted_path = ectx.extract(
             os.path.join(self.tempdir, CURL_7_20_0_RPM))
         assert (main([
             "cve-bin-tool",
             "-l",
             "debug",
             os.path.join(extracted_path, "usr", "bin", "curl"),
         ]) != 0)
예제 #15
0
    def test_skips(self):
        """Tests the skips option"""

        logger = logging.getLogger()
        test_path = os.path.join(os.path.abspath(os.path.dirname(__file__)), "csv")

        skip_checkers = ["systemd", "xerces", "xml2", "kerberos"]
        include_checkers = ["expat", "libgcrypt", "openssl", "sqlite"]

        with self.assertLogs(logger, logging.INFO) as cm:
            main(["cve-bin-tool", test_path, "-s", ",".join(skip_checkers)])

        self.check_checkers_log(cm, skip_checkers, include_checkers)

        # swap skip_checkers and include_checkers
        include_checkers, skip_checkers = skip_checkers, include_checkers
        with self.assertLogs(logger, logging.INFO) as cm:
            main(["cve-bin-tool", test_path, "-s", ",".join(skip_checkers)])

        self.check_checkers_log(cm, skip_checkers, include_checkers)
예제 #16
0
    def test_quiet_mode(self):
        """ Test that an quite mode isn't generating any output """
        logger = logging.getLogger()

        with tempfile.NamedTemporaryFile("w+b",
                                         suffix="strong-swan-4.6.3.out",
                                         delete=False) as f:
            signatures = [
                b"\x7f\x45\x4c\x46\x02\x01\x01\x03\n", b"strongSwan 4.6.3"
            ]
            f.writelines(signatures)
            filename = f.name

        with self.assertLogs(logger, logging.INFO) as cm:
            main(["cve-bin-tool", "-q", filename])
            logger.info("test")

        self.assertEqual(["INFO:root:test"], cm.output)

        # clean up temporary file.
        os.remove(filename)
예제 #17
0
    def test_severity(self, capsys, caplog):
        # scan with severity setting to ensure only CVEs above severity threshold are reported

        # Check command line parameters - wrong case
        with pytest.raises(SystemExit) as e:
            main(["cve-bin-tool", "-S", "HIGH", self.tempdir])
        assert e.value.args[0] == -2
        # Check command line parameters - wrong option
        with pytest.raises(SystemExit) as e:
            main(["cve-bin-tool", "-S", "ALL", self.tempdir])
        assert e.value.args[0] == -2

        my_test_filename = "sevtest.csv"

        if os.path.exists(my_test_filename):
            os.remove(my_test_filename)
        with caplog.at_level(logging.DEBUG):
            main([
                "cve-bin-tool",
                "-x",
                "-f",
                "csv",
                "-o",
                my_test_filename,
                "-S",
                "high",
                os.path.join(self.tempdir, CURL_7_20_0_RPM),
            ])
        # Verify that no CVEs with a severity of Medium are reported
        assert not self.check_string_in_file(my_test_filename, "MEDIUM")
        # Verify that CVEs with a higher severity are reported
        assert self.check_string_in_file(my_test_filename, "HIGH")
        caplog.clear()
        if os.path.exists(my_test_filename):
            os.remove(my_test_filename)
예제 #18
0
    def test_quiet_mode(self, capsys, caplog):
        """ Test that an quite mode isn't generating any output """

        with tempfile.NamedTemporaryFile("w+b",
                                         suffix="strong-swan-4.6.3.out",
                                         delete=False) as f:
            signatures = [
                b"\x7f\x45\x4c\x46\x02\x01\x01\x03\n", b"strongSwan 4.6.3"
            ]
            f.writelines(signatures)
            filename = f.name

        main(["cve-bin-tool", "-q", filename, "-u", "now"])
        # clean up temporary file.
        os.remove(filename)

        # Make sure log is empty
        assert not caplog.records

        # Make sure nothing is getting printed on stdout or stderr
        captured = capsys.readouterr()
        assert not (captured.out or captured.err)
예제 #19
0
def main(argv=None):
    logger = LOGGER.getChild("CSV2CVE")
    argv = argv or sys.argv
    if len(argv) < 2:
        with ErrorHandler(logger=logger):
            raise InsufficientArgs("csv file required")

    flag = False
    for idx, arg in enumerate(argv):
        if arg.endswith(".csv"):
            argv[idx] = f"-i={arg}"
            flag = True
    if flag:
        return cli.main(argv)
    else:
        with ErrorHandler(logger=logger):
            raise InsufficientArgs("csv file required")
예제 #20
0
    def test_invalid_parameter(self):
        """ Test that invalid parmeters exit with expected error code.
       ArgParse calls sys.exit(2) for all errors, we've overwritten to -2 """

        # no directory specified
        with self.assertRaises(SystemExit) as exit:
            main(["cve-bin-tool", "--bad-param"])
        self.assertEqual(exit.exception.code, -2)

        # bad parameter (but good directory)
        with self.assertRaises(SystemExit) as exit:
            main(["cve-bin-tool", "--bad-param", self.tempdir])
        self.assertEqual(exit.exception.code, -2)

        # worse parameter
        with self.assertRaises(SystemExit) as exit:
            main(["cve-bin-tool", "--bad-param && cat hi", self.tempdir])
        self.assertEqual(exit.exception.code, -2)

        # bad parameter after directory
        with self.assertRaises(SystemExit) as exit:
            main(["cve-bin-tool", self.tempdir, "--bad-param;cat hi"])
        self.assertEqual(exit.exception.code, -2)
예제 #21
0
    def test_invalid_parameter(self):
        """Test that invalid parmeters exit with expected error code.
        ArgParse calls sys.exit(2) for all errors, we've overwritten to -2"""

        # no directory specified
        with pytest.raises(SystemExit) as e:
            main(["cve-bin-tool", "--bad-param"])
        assert e.value.args[0] == -2

        # bad parameter (but good directory)
        with pytest.raises(SystemExit) as e:
            main(["cve-bin-tool", "--bad-param", self.tempdir])
        assert e.value.args[0] == -2

        # worse parameter
        with pytest.raises(SystemExit) as e:
            main(["cve-bin-tool", "--bad-param && cat hi", self.tempdir])
        assert e.value.args[0] == -2

        # bad parameter after directory
        with pytest.raises(SystemExit) as e:
            main(["cve-bin-tool", self.tempdir, "--bad-param;cat hi"])
        assert e.value.args[0] == -2
예제 #22
0
    def test_config_file(self, caplog, filename):
        # scan with config file and overwrite output format
        assert main(["cve-bin-tool", "-C", filename, "-l", "info"]) != 0

        # assert only checkers for binutils and curl get to run
        assert (
            "cve_bin_tool.VersionScanner",
            logging.INFO,
            "Checkers: binutils, curl",
        ) in caplog.record_tuples

        # assert only CVEs of curl get reflected. Because other are skipped
        assert (
            "cve_bin_tool",
            logging.INFO,
            "There are 1 products with known CVEs detected",
        ) in caplog.record_tuples

        for record in caplog.record_tuples:
            if record[1] < 20:
                pytest.fail(
                    msg=
                    "cli option should override logging level specified in config file"
                )
예제 #23
0
 def test_invalid_file_or_directory(self):
     """ Test behaviour with an invalid file/directory """
     self.assertEqual(main(["cve-bin-tool", "non-existant"]), -1)
예제 #24
0
 def test_usage(self):
     """ Test that the usage returns 0 """
     self.assertEqual(main(["cve-bin-tool"]), 0)
예제 #25
0
 def test_no_extraction(self):
     """ Test scanner against curl-7.20.0 rpm with extraction turned off """
     self.assertEqual(
         main(["cve-bin-tool",
               os.path.join(self.tempdir, CURL_7_20_0_RPM)]), 0)
예제 #26
0
 def test_extract_curl_7_20_0(self):
     """Scanning curl-7.20.0"""
     self.assertNotEqual(
         main(["cve-bin-tool", "-l", "debug", "-x", self.tempdir]), 0)
예제 #27
0
 def test_invalid_file_or_directory(self):
     """ Test behaviour with an invalid file/directory """
     with pytest.raises(SystemExit) as e:
         main(["cve-bin-tool", "non-existant"])
     assert e.value.args[0] == -3
예제 #28
0
 def test_usage(self):
     """ Test that the usage returns 0 """
     with pytest.raises(SystemExit) as e:
         main(["cve-bin-tool"])
     assert e.value.args[0] == -6
예제 #29
0
 def test_multithread(self):
     """ Test Multithread mode """
     self.assertNotEqual(
         main(["cve-bin-tool", "-l", "debug", "-m", "-x", self.tempdir]), 0)
예제 #30
0
    def test_CVSS_score(self, capsys, caplog):
        # scan with severity score to ensure only CVEs above score threshold are reported

        my_test_filename = "sevtest.csv"

        # Check command line parameters. Less than 0 result in default behaviour.
        if os.path.exists(my_test_filename):
            os.remove(my_test_filename)
        with caplog.at_level(logging.DEBUG):
            main([
                "cve-bin-tool",
                "-x",
                "-c",
                "-1",
                "-f",
                "csv",
                "-o",
                my_test_filename,
                os.path.join(self.tempdir, CURL_7_20_0_RPM),
            ])
        # Verify that some CVEs with a severity of Medium are reported
        assert self.check_string_in_file(my_test_filename, "MEDIUM")
        caplog.clear()

        # Check command line parameters. >10 results in no CVEs being reported (Maximum CVSS score is 10)
        if os.path.exists(my_test_filename):
            os.remove(my_test_filename)
        with caplog.at_level(logging.DEBUG):
            main([
                "cve-bin-tool",
                "-x",
                "-c",
                "11",
                "-f",
                "csv",
                "-o",
                my_test_filename,
                os.path.join(self.tempdir, CURL_7_20_0_RPM),
            ])
        # Verify that no CVEs are reported (no file is created)
        assert not os.path.exists(my_test_filename)
        caplog.clear()

        with caplog.at_level(logging.DEBUG):
            main([
                "cve-bin-tool",
                "-x",
                "-f",
                "csv",
                "-o",
                my_test_filename,
                os.path.join(self.tempdir, CURL_7_20_0_RPM),
            ])
        # Verify that CVEs with a severity of Medium are reported
        assert self.check_string_in_file(my_test_filename, "MEDIUM")
        caplog.clear()
        if os.path.exists(my_test_filename):
            os.remove(my_test_filename)

        # Now check subset
        with caplog.at_level(logging.DEBUG):
            main([
                "cve-bin-tool",
                "-x",
                "-c",
                "7",
                "-f",
                "csv",
                "-o",
                my_test_filename,
                os.path.join(self.tempdir, CURL_7_20_0_RPM),
            ])
        # Verify that no CVEs with a severity of Medium are reported
        assert not self.check_string_in_file(my_test_filename, "MEDIUM")
        if os.path.exists(my_test_filename):
            os.remove(my_test_filename)
        caplog.clear()