Tweaks to #nosec (+ ignore flag, - dead constant)

Adds a flag '--ignore-nosec' to address the situation where a user is
auditing a code base and wants to see all identified issues, not just
those that haven't been nosec'd.

Also removes SKIP_FLAGS from core/constants.py, as that is no longer
used within the Bandit code base.

Change-Id: I1cef004660ff4abedb7128844cc0f26b9fdcda42
Closes-Bug: #1499467
This commit is contained in:
Jamie Finnigan
2015-10-12 16:27:18 -04:00
parent 73af54ffcc
commit 981ef46a46
6 changed files with 33 additions and 18 deletions

View File

@@ -59,10 +59,10 @@ using only the plugins listed in the ``ShellInjection`` profile::
Usage::
bandit -h
$ bandit -h
usage: bandit [-h] [-r] [-a {file,vuln}] [-n CONTEXT_LINES] [-c CONFIG_FILE]
[-p PROFILE] [-l] [-f {txt,json,csv,xml}] [-o OUTPUT_FILE] [-v]
[-d]
[-p PROFILE] [-l] [-i] [-f {txt,json,csv,xml}]
[-o OUTPUT_FILE] [-v] [-d] [--ignore-nosec]
targets [targets ...]
Bandit - a Python source code analyzer.
@@ -98,6 +98,7 @@ Usage::
-v, --verbose show extra information like excluded and included
files
-d, --debug turn on debug mode
--ignore-nosec do not skip lines with # nosec comments
Configuration

View File

@@ -171,8 +171,13 @@ def main():
'-d', '--debug', dest='debug', action='store_true',
help='turn on debug mode'
)
parser.add_argument(
'--ignore-nosec', dest='ignore_nosec', action='store_true',
help='do not skip lines with # nosec comments'
)
parser.set_defaults(debug=False)
parser.set_defaults(verbose=False)
parser.set_defaults(ignore_nosec=False)
plugin_list = '\n\t'.join(sorted(extension_mgr.plugin_names))
parser.epilog = ('The following plugin suites were discovered and'
@@ -201,7 +206,8 @@ def main():
b_mgr = b_manager.BanditManager(b_conf, args.agg_type, args.debug,
profile_name=args.profile,
verbose=args.verbose)
verbose=args.verbose,
ignore_nosec=args.ignore_nosec)
if args.output_format != "json":
logger.info("using config: %s", config_file)

View File

@@ -29,9 +29,6 @@ plugin_name_pattern = '*.py'
# default progress increment
progress_increment = 50
# flag/s used to mark lines where identified issues should not be reported
SKIP_FLAGS = ['nosec', ]
RANKING = ['UNDEFINED', 'LOW', 'MEDIUM', 'HIGH']
RANKING_VALUES = {'UNDEFINED': 1, 'LOW': 3, 'MEDIUM': 5, 'HIGH': 10}
CRITERIA = [('SEVERITY', 'UNDEFINED'), ('CONFIDENCE', 'UNDEFINED')]

View File

@@ -35,7 +35,7 @@ class BanditManager():
scope = []
def __init__(self, config, agg_type, debug=False, verbose=False,
profile_name=None):
profile_name=None, ignore_nosec=False):
'''Get logger, config, AST handler, and result store ready
:param config: config options object
@@ -44,10 +44,12 @@ class BanditManager():
:param debug: Whether to show debug messsages or not
:param verbose: Whether to show verbose output
:param profile_name: Optional name of profile to use (from cmd line)
:param ignore_nosec: Whether to ignore #nosec or not
:return:
'''
self.debug = debug
self.verbose = verbose
self.ignore_nosec = ignore_nosec
self.b_conf = config
self.files_list = []
self.excluded_files = []
@@ -254,7 +256,7 @@ class BanditManager():
score = []
if fdata is not None:
res = b_node_visitor.BanditNodeVisitor(
fname, self.b_conf, b_ma, b_ts, self.debug
fname, self.b_conf, b_ma, b_ts, self.debug, self.ignore_nosec
)
score, metrics = res.process(fdata)
self.results.extend(res.tester.results)

View File

@@ -34,8 +34,9 @@ class BanditNodeVisitor(object):
'function': None, 'lineno': None, 'skip_lines': None}
def __init__(self, fname, config, metaast, testset,
debug):
debug, ignore_nosec):
self.debug = debug
self.ignore_nosec = ignore_nosec
self.seen = 0
self.scores = {
'SEVERITY': [0] * len(constants.RANKING),
@@ -267,11 +268,13 @@ class BanditNodeVisitor(object):
if hasattr(node, 'lineno'):
self.context['lineno'] = node.lineno
if ("# nosec" in self.lines[node.lineno - 1] or
"#nosec" in self.lines[node.lineno - 1]):
logger.debug("skipped, nosec")
self.metrics['nosec'] += 1
return
if not self.ignore_nosec:
if ("# nosec" in self.lines[node.lineno - 1] or
"#nosec" in self.lines[node.lineno - 1]):
logger.debug("skipped, nosec")
self.metrics['nosec'] += 1
return
self.context['node'] = node
self.context['linerange'] = b_utils.linerange_fix(node)

View File

@@ -49,7 +49,7 @@ class FunctionalTests(testtools.TestCase):
self.b_mgr.b_conf._settings['plugins_dir'] = path
self.b_mgr.b_ts = b_test_set.BanditTestSet(config=b_conf)
def run_example(self, example_script):
def run_example(self, example_script, ignore_nosec=False):
'''A helper method to run the specified test
This method runs the test, which populates the self.b_mgr.scores
@@ -58,10 +58,11 @@ class FunctionalTests(testtools.TestCase):
:param example_script: Filename of an example script to test
'''
path = os.path.join(os.getcwd(), 'examples', example_script)
self.b_mgr.ignore_nosec = ignore_nosec
self.b_mgr.discover_files([path], True)
self.b_mgr.run_tests()
def check_example(self, example_script, expect):
def check_example(self, example_script, expect, ignore_nosec=False):
'''A helper method to test the scores for example scripts.
:param example_script: Filename of an example script to test
@@ -69,7 +70,7 @@ class FunctionalTests(testtools.TestCase):
'''
# reset scores for subsequent calls to check_example
self.b_mgr.scores = []
self.run_example(example_script)
self.run_example(example_script, ignore_nosec=ignore_nosec)
expected = 0
result = 0
for test_scores in self.b_mgr.scores:
@@ -272,6 +273,11 @@ class FunctionalTests(testtools.TestCase):
expect = {'SEVERITY': {'LOW': 5}, 'CONFIDENCE': {'HIGH': 5}}
self.check_example('skip.py', expect)
def test_ignore_skip(self):
''' Test --ignore-nosec flag.'''
expect = {'SEVERITY': {'LOW': 7}, 'CONFIDENCE': {'HIGH': 7}}
self.check_example('skip.py', expect, ignore_nosec=True)
def test_sql_statements(self):
'''Test for SQL injection through string building.'''
expect = {