diff --git a/README.rst b/README.rst index d6869b52..7eb62be8 100644 --- a/README.rst +++ b/README.rst @@ -63,6 +63,7 @@ Usage:: usage: bandit [-h] [-r] [-a {file,vuln}] [-n CONTEXT_LINES] [-c CONFIG_FILE] [-p PROFILE] [-l] [-i] [-f {txt,json,csv,xml}] [-o OUTPUT_FILE] [-v] [-d] [--ignore-nosec] + [--exclude EXCLUDED_PATHS] targets [targets ...] Bandit - a Python source code analyzer. @@ -99,6 +100,10 @@ Usage:: files -d, --debug turn on debug mode --ignore-nosec do not skip lines with # nosec comments + -x, --exclude EXCLUDED_PATHS + Comma separated list of paths to exclude from scan. + Note that these are in addition to the excluded paths + provided in the config file. Configuration diff --git a/bandit/bandit.py b/bandit/bandit.py index a51cabe1..88e84f9f 100644 --- a/bandit/bandit.py +++ b/bandit/bandit.py @@ -175,6 +175,12 @@ def main(): '--ignore-nosec', dest='ignore_nosec', action='store_true', help='do not skip lines with # nosec comments' ) + parser.add_argument( + '-x', '--exclude', dest='excluded_paths', action='store', + default='', help='Comma separated list of paths to exclude from scan. ' + 'Note that these are in addition to the excluded ' + 'paths provided in the config file.' + ) parser.set_defaults(debug=False) parser.set_defaults(verbose=False) parser.set_defaults(ignore_nosec=False) @@ -231,7 +237,7 @@ def main(): sys.exit(2) # initiate file discovery step within Bandit Manager - b_mgr.discover_files(args.targets, args.recursive) + b_mgr.discover_files(args.targets, args.recursive, args.excluded_paths) # initiate execution of tests within Bandit Manager b_mgr.run_tests() diff --git a/bandit/core/manager.py b/bandit/core/manager.py index 782758ff..5476415d 100644 --- a/bandit/core/manager.py +++ b/bandit/core/manager.py @@ -131,7 +131,7 @@ class BanditManager(): except IOError: print("Unable to write to file: %s" % output_filename) - def discover_files(self, targets, recursive=False): + def discover_files(self, targets, recursive=False, excluded_paths=''): '''Add tests directly and from a directory to the test set :param targets: The command line list of files and directories @@ -146,6 +146,11 @@ class BanditManager(): excluded_path_strings = self.b_conf.get_option('exclude_dirs') or [] included_globs = self.b_conf.get_option('include') or ['*.py'] + # if there are command line provided exclusions add them to the list + if excluded_paths: + for path in excluded_paths.split(','): + excluded_path_strings.append(path) + # build list of files we will analyze for fname in targets: # if this is a directory and recursive is set, find all files diff --git a/tests/unit/core/test_manager.py b/tests/unit/core/test_manager.py index 5cb54914..77ac3888 100644 --- a/tests/unit/core/test_manager.py +++ b/tests/unit/core/test_manager.py @@ -215,6 +215,14 @@ class ManagerTests(testtools.TestCase): self.assertEqual(self.manager.files_list, []) self.assertEqual(self.manager.excluded_files, ['thing']) + @mock.patch('os.path.isdir') + def test_discover_files_exclude_cmdline(self, isdir): + isdir.return_value = False + with mock.patch.object(manager, '_is_file_included') as m: + self.manager.discover_files(['a', 'b', 'c'], True, + excluded_paths='a,b') + m.assert_called_with('c', ['*.py'], ['a', 'b'], enforce_glob=False) + @mock.patch('os.path.isdir') def test_discover_files_include(self, isdir): isdir.return_value = False