Trivial fixes based on pylint scan

* Constants should be in caps
* Redundant ( ) in if statements
* Use isinstance instead of type ==
* Indentation

Change-Id: I79fda14112a9dd02fe867f6d850762216e0ca9a1
This commit is contained in:
Eric Brown 2016-11-18 22:19:50 -08:00
parent 4bfa1b69be
commit 3be3ca4de0
40 changed files with 282 additions and 213 deletions

View File

@ -38,7 +38,7 @@ bandit_args = sys.argv[1:]
baseline_tmp_file = '_bandit_baseline_run.json_'
current_commit = None
default_output_format = 'terminal'
logger = logging.getLogger(__name__)
LOG = logging.getLogger(__name__)
repo = None
report_basename = 'bandit_baseline_result'
valid_baseline_formats = ['txt', 'html', 'json']
@ -65,17 +65,17 @@ def main():
try:
commit = repo.commit()
current_commit = commit.hexsha
logger.info('Got current commit: [%s]', commit.name_rev)
LOG.info('Got current commit: [%s]', commit.name_rev)
commit = commit.parents[0]
parent_commit = commit.hexsha
logger.info('Got parent commit: [%s]', commit.name_rev)
LOG.info('Got parent commit: [%s]', commit.name_rev)
except git.GitCommandError:
logger.error("Unable to get current or parent commit")
LOG.error("Unable to get current or parent commit")
sys.exit(2)
except IndexError:
logger.error("Parent commit not available")
LOG.error("Parent commit not available")
sys.exit(2)
# #################### Run Bandit against both commits ####################
@ -99,7 +99,7 @@ def main():
for step in steps:
repo.head.reset(commit=step['commit'], working_tree=True)
logger.info(step['message'])
LOG.info(step['message'])
bandit_command = ['bandit'] + step['args']
@ -113,15 +113,15 @@ def main():
output = output.decode('utf-8') # subprocess returns bytes
if return_code not in [0, 1]:
logger.error("Error running command: %s\nOutput: %s\n",
bandit_args, output)
LOG.error("Error running command: %s\nOutput: %s\n",
bandit_args, output)
# #################### Output and exit ####################################
# print output or display message about written report
if output_format == default_output_format:
print(output)
else:
logger.info("Successfully wrote %s", report_fname)
LOG.info("Successfully wrote %s", report_fname)
# exit with the code the last Bandit run returned
sys.exit(return_code)
@ -140,14 +140,14 @@ def baseline_setup():
# #################### Setup logging ##########################################
def init_logger():
logger.handlers = []
LOG.handlers = []
log_level = logging.INFO
log_format_string = "[%(levelname)7s ] %(message)s"
logging.captureWarnings(True)
logger.setLevel(log_level)
LOG.setLevel(log_level)
handler = logging.StreamHandler(sys.stdout)
handler.setFormatter(logging.Formatter(log_format_string))
logger.addHandler(handler)
LOG.addHandler(handler)
# #################### Perform initialization and validate assumptions ########
@ -178,8 +178,7 @@ def initialize():
else default_output_format)
if output_format == default_output_format:
logger.info("No output format specified, using %s",
default_output_format)
LOG.info("No output format specified, using %s", default_output_format)
# set the report name based on the output format
report_fname = "{}.{}".format(report_basename, output_format)
@ -189,33 +188,33 @@ def initialize():
repo = git.Repo(os.getcwd())
except git.exc.InvalidGitRepositoryError:
logger.error("Bandit baseline must be called from a git project root")
LOG.error("Bandit baseline must be called from a git project root")
valid = False
except git.exc.GitCommandNotFound:
logger.error("Git command not found")
LOG.error("Git command not found")
valid = False
else:
if repo.is_dirty():
logger.error("Current working directory is dirty and must be "
"resolved")
LOG.error("Current working directory is dirty and must be "
"resolved")
valid = False
# if output format is specified, we need to be able to write the report
if output_format != default_output_format and os.path.exists(report_fname):
logger.error("File %s already exists, aborting", report_fname)
LOG.error("File %s already exists, aborting", report_fname)
valid = False
# Bandit needs to be able to create this temp file
if os.path.exists(baseline_tmp_file):
logger.error("Temporary file %s needs to be removed prior to running",
baseline_tmp_file)
LOG.error("Temporary file %s needs to be removed prior to running",
baseline_tmp_file)
valid = False
# we must validate -o is not provided, as it will mess up Bandit baseline
if '-o' in bandit_args:
logger.error("Bandit baseline must not be called with the -o option")
LOG.error("Bandit baseline must not be called with the -o option")
valid = False
return (output_format, repo, report_fname) if valid else (None, None, None)

View File

@ -25,7 +25,7 @@ import yaml
from bandit.core import extension_loader
PROG_NAME = 'bandit_conf_generator'
logger = logging.getLogger(__name__)
LOG = logging.getLogger(__name__)
template = """
@ -60,14 +60,14 @@ template = """
def init_logger():
logger.handlers = []
LOG.handlers = []
log_level = logging.INFO
log_format_string = "[%(levelname)5s]: %(message)s"
logging.captureWarnings(True)
logger.setLevel(log_level)
LOG.setLevel(log_level)
handler = logging.StreamHandler(sys.stdout)
handler.setFormatter(logging.Formatter(log_format_string))
logger.addHandler(handler)
LOG.addHandler(handler)
def parse_args():
@ -138,7 +138,7 @@ def main():
if args.output_file:
if os.path.exists(os.path.abspath(args.output_file)):
logger.error("File %s already exists, exiting", args.output_file)
LOG.error("File %s already exists, exiting", args.output_file)
sys.exit(2)
try:
@ -158,9 +158,9 @@ def main():
test_list = [tpl.format(t.plugin._test_id, t.name)
for t in extension_loader.MANAGER.plugins]
test_list.extend([tpl.format(k, v['name'])
for k, v in six.iteritems(
extension_loader.MANAGER.blacklist_by_id)])
others = [tpl.format(k, v['name']) for k, v in six.iteritems(
extension_loader.MANAGER.blacklist_by_id)]
test_list.extend(others)
test_list.sort()
contents = template.format(
@ -172,13 +172,13 @@ def main():
f.write(contents)
except IOError:
logger.error("Unable to open %s for writing", args.output_file)
LOG.error("Unable to open %s for writing", args.output_file)
except Exception as e:
logger.error("Error: %s", e)
LOG.error("Error: %s", e)
else:
logger.info("Successfully wrote profile: %s", args.output_file)
LOG.info("Successfully wrote profile: %s", args.output_file)
return 0

View File

@ -29,7 +29,7 @@ from bandit.core import utils
BASE_CONFIG = 'bandit.yaml'
logger = logging.getLogger()
LOG = logging.getLogger()
def _init_logger(debug=False, log_format=None):
@ -38,7 +38,7 @@ def _init_logger(debug=False, log_format=None):
:param debug: Whether to enable debug mode
:return: An instantiated logging instance
'''
logger.handlers = []
LOG.handlers = []
log_level = logging.INFO
if debug:
log_level = logging.DEBUG
@ -51,11 +51,11 @@ def _init_logger(debug=False, log_format=None):
logging.captureWarnings(True)
logger.setLevel(log_level)
LOG.setLevel(log_level)
handler = logging.StreamHandler(sys.stderr)
handler.setFormatter(logging.Formatter(log_format_string))
logger.addHandler(handler)
logger.debug("logging initialized")
LOG.addHandler(handler)
LOG.debug("logging initialized")
def _get_options_from_ini(ini_path, target):
@ -73,15 +73,13 @@ def _get_options_from_ini(ini_path, target):
bandit_files.append(os.path.join(root, filename))
if len(bandit_files) > 1:
logger.error('Multiple .bandit files found - scan separately or '
'choose one with --ini\n\t%s',
', '.join(bandit_files))
LOG.error('Multiple .bandit files found - scan separately or '
'choose one with --ini\n\t%s', ', '.join(bandit_files))
sys.exit(2)
elif len(bandit_files) == 1:
ini_file = bandit_files[0]
logger.info('Found project level .bandit file: %s',
bandit_files[0])
LOG.info('Found project level .bandit file: %s', bandit_files[0])
if ini_file:
return utils.parse_ini_file(ini_file)
@ -97,10 +95,10 @@ def _init_extensions():
def _log_option_source(arg_val, ini_val, option_name):
"""It's useful to show the source of each option."""
if arg_val:
logger.info("Using command line arg for %s", option_name)
LOG.info("Using command line arg for %s", option_name)
return arg_val
elif ini_val:
logger.info("Using .bandit arg for %s", option_name)
LOG.info("Using .bandit arg for %s", option_name)
return ini_val
else:
return None
@ -120,7 +118,7 @@ def _get_profile(config, profile_name, config_path):
profile = profiles.get(profile_name)
if profile is None:
raise utils.ProfileNotFound(config_path, profile_name)
logger.debug("read in legacy profile '%s': %s", profile_name, profile)
LOG.debug("read in legacy profile '%s': %s", profile_name, profile)
else:
profile['include'] = set(config.get_option('tests') or [])
profile['exclude'] = set(config.get_option('skips') or [])
@ -130,10 +128,10 @@ def _get_profile(config, profile_name, config_path):
def _log_info(args, profile):
inc = ",".join([t for t in profile['include']]) or "None"
exc = ",".join([t for t in profile['exclude']]) or "None"
logger.info("profile include tests: %s", inc)
logger.info("profile exclude tests: %s", exc)
logger.info("cli include tests: %s", args.tests)
logger.info("cli exclude tests: %s", args.skips)
LOG.info("profile include tests: %s", inc)
LOG.info("profile exclude tests: %s", exc)
LOG.info("cli include tests: %s", args.tests)
LOG.info("cli exclude tests: %s", args.skips)
def main():
@ -265,7 +263,7 @@ def main():
try:
b_conf = b_config.BanditConfig(config_file=args.config_file)
except utils.ConfigError as e:
logger.error(e)
LOG.error(e)
sys.exit(2)
# Handle .bandit files in projects to pass cmdline args from file
@ -297,7 +295,7 @@ def main():
extension_mgr.validate_profile(profile)
except (utils.ProfileNotFound, ValueError) as e:
logger.error(e)
LOG.error(e)
sys.exit(2)
b_mgr = b_manager.BanditManager(b_conf, args.agg_type, args.debug,
@ -310,32 +308,32 @@ def main():
data = bl.read()
b_mgr.populate_baseline(data)
except IOError:
logger.warning("Could not open baseline report: %s", args.baseline)
LOG.warning("Could not open baseline report: %s", args.baseline)
sys.exit(2)
if args.output_format not in baseline_formatters:
logger.warning('Baseline must be used with one of the following '
'formats: ' + str(baseline_formatters))
LOG.warning('Baseline must be used with one of the following '
'formats: ' + str(baseline_formatters))
sys.exit(2)
if args.output_format != "json":
if args.config_file:
logger.info("using config: %s", args.config_file)
LOG.info("using config: %s", args.config_file)
logger.info("running on Python %d.%d.%d", sys.version_info.major,
sys.version_info.minor, sys.version_info.micro)
LOG.info("running on Python %d.%d.%d", sys.version_info.major,
sys.version_info.minor, sys.version_info.micro)
# initiate file discovery step within Bandit Manager
b_mgr.discover_files(args.targets, args.recursive, args.excluded_paths)
if not b_mgr.b_ts.tests:
logger.error('No tests would be run, please check the profile.')
LOG.error('No tests would be run, please check the profile.')
sys.exit(2)
# initiate execution of tests within Bandit Manager
b_mgr.run_tests()
logger.debug(b_mgr.b_ma)
logger.debug(b_mgr.metrics)
LOG.debug(b_mgr.b_ma)
LOG.debug(b_mgr.metrics)
# trigger output of results by Bandit Manager
sev_level = constants.RANKING[args.severity - 1]

View File

@ -24,7 +24,7 @@ from bandit.core import extension_loader
from bandit.core import utils
logger = logging.getLogger(__name__)
LOG = logging.getLogger(__name__)
class BanditConfig():
@ -167,8 +167,8 @@ class BanditConfig():
bad_imports_list.append(val)
if bad_imports_list or bad_calls_list:
logger.warning('Legacy blacklist data found in config, '
'overriding data plugins')
LOG.warning('Legacy blacklist data found in config, overriding '
'data plugins')
return bad_calls_list, bad_imports_list
def convert_legacy_blacklist_tests(self, profiles, bad_imports, bad_calls):
@ -235,9 +235,8 @@ class BanditConfig():
# show deprecation message
if legacy:
logger.warn("Config file '%s' contains deprecated legacy "
"config data. Please consider upgrading to "
"the new config format. The tool "
"'bandit-config-generator' can help you with "
"this. Support for legacy configs will be removed "
"in a future bandit version.", path)
LOG.warn("Config file '%s' contains deprecated legacy config "
"data. Please consider upgrading to the new config "
"format. The tool 'bandit-config-generator' can help you "
"with this. Support for legacy configs will be removed "
"in a future bandit version.", path)

View File

@ -103,10 +103,8 @@ class Context():
:return: A dictionary of keyword parameters for a call as strings
'''
if (
'call' in self._context and
hasattr(self._context['call'], 'keywords')
):
if ('call' in self._context and
hasattr(self._context['call'], 'keywords')):
return_dict = {}
for li in self._context['call'].keywords:
if hasattr(li.value, 'attr'):
@ -152,7 +150,7 @@ class Context():
'''Get escaped value of the object.
Turn the value of a string or bytes object into byte sequence with
unknown, control, and \ characters escaped.
unknown, control, and \\ characters escaped.
This function should be used when looking for a known sequence in a
potentially badly encoded string in the code.
@ -298,11 +296,9 @@ class Context():
:param position_num: The index of the argument to return the value for
:return: Value of the argument at the specified position if it exists
'''
if (
'call' in self._context and
hasattr(self._context['call'], 'args') and
position_num < len(self._context['call'].args)
):
if ('call' in self._context and
hasattr(self._context['call'], 'args') and
position_num < len(self._context['call'].args)):
return self._get_literal_value(
self._context['call'].args[position_num]
)
@ -315,10 +311,7 @@ class Context():
:param module: The module name to look for
:return: True if the module is found, False otherwise
'''
if 'module' in self._context and self._context['module'] == module:
return True
else:
return False
return 'module' in self._context and self._context['module'] == module
def is_module_imported_exact(self, module):
'''Check if a specified module has been imported; only exact matches.
@ -326,10 +319,8 @@ class Context():
:param module: The module name to look for
:return: True if the module is found, False otherwise
'''
if 'imports' in self._context and module in self._context['imports']:
return True
else:
return False
return ('imports' in self._context and
module in self._context['imports'])
def is_module_imported_like(self, module):
'''Check if a specified module has been imported

View File

@ -15,7 +15,7 @@
# under the License.
# where our docs are hosted
base_url = 'http://docs.openstack.org/developer/bandit/'
BASE_URL = 'http://docs.openstack.org/developer/bandit/'
def get_url(bid):
@ -26,7 +26,7 @@ def get_url(bid):
info = extension_loader.MANAGER.plugins_by_id.get(bid, None)
if info is not None:
return base_url + ('plugins/%s.html' % info.plugin.__name__)
return BASE_URL + ('plugins/%s.html' % info.plugin.__name__)
info = extension_loader.MANAGER.blacklist_by_id.get(bid, None)
if info is not None:
@ -38,6 +38,6 @@ def get_url(bid):
ext = template.format(
kind='imports', id=info['id'], name=info['name'])
return base_url + ext.lower()
return BASE_URL + ext.lower()
return base_url # no idea, give the docs main page
return BASE_URL # no idea, give the docs main page

View File

@ -17,11 +17,11 @@
from __future__ import division
from __future__ import unicode_literals
from bandit.core import constants
import linecache
from six import moves
import linecache
from bandit.core import constants
class Issue(object):

View File

@ -31,7 +31,7 @@ from bandit.core import node_visitor as b_node_visitor
from bandit.core import test_set as b_test_set
logger = logging.getLogger(__name__)
LOG = logging.getLogger(__name__)
class BanditManager():
@ -39,7 +39,7 @@ class BanditManager():
scope = []
def __init__(self, config, agg_type, debug=False, verbose=False,
profile={}, ignore_nosec=False):
profile=None, ignore_nosec=False):
'''Get logger, config, AST handler, and result store ready
:param config: config options object
@ -53,6 +53,8 @@ class BanditManager():
'''
self.debug = debug
self.verbose = verbose
if not profile:
profile = {}
self.ignore_nosec = ignore_nosec
self.b_conf = config
self.files_list = []
@ -86,7 +88,7 @@ class BanditManager():
jdata = json.loads(data)
items = [issue.issue_from_dict(j) for j in jdata["results"]]
except Exception as e:
logger.warning("Failed to load baseline data: %s", e)
LOG.warning("Failed to load baseline data: %s", e)
self.baseline = items
def filter_results(self, sev_filter, conf_filter):
@ -181,8 +183,8 @@ class BanditManager():
files_list.update(new_files)
excluded_files.update(newly_excluded)
else:
logger.warning("Skipping directory (%s), use -r flag to "
"scan contents", fname)
LOG.warning("Skipping directory (%s), use -r flag to "
"scan contents", fname)
else:
# if the user explicitly mentions a file on command line,
@ -212,7 +214,7 @@ class BanditManager():
new_files_list = list(self.files_list)
for count, fname in enumerate(self.files_list):
logger.debug("working on file : %s", fname)
LOG.debug("working on file : %s", fname)
if len(self.files_list) > self.progress:
# is it time to update the progress indicator?
@ -247,17 +249,17 @@ class BanditManager():
))
new_files_list.remove(fname)
except Exception as e:
logger.error(
LOG.error(
"Exception occurred when executing tests against "
"{0}. Run \"bandit --debug {0}\" to see the full "
"traceback.".format(fname)
"%s. Run \"bandit --debug %s\" to see the full "
"traceback.", fname, fname
)
self.skipped.append(
(fname, 'exception while scanning file')
)
new_files_list.remove(fname)
logger.debug(" Exception string: %s", e)
logger.debug(
LOG.debug(" Exception string: %s", e)
LOG.debug(
" Exception traceback: %s",
traceback.format_exc()
)
@ -294,8 +296,10 @@ class BanditManager():
return score
def _get_files_from_dir(files_dir, included_globs=['*.py'],
def _get_files_from_dir(files_dir, included_globs=None,
excluded_path_strings=None):
if not included_globs:
included_globs = ['*.py']
if not excluded_path_strings:
excluded_path_strings = []

View File

@ -19,13 +19,16 @@ import collections
import logging
logger = logging.getLogger(__name__)
LOG = logging.getLogger(__name__)
class BanditMetaAst():
nodes = collections.OrderedDict()
def __init__(self):
pass
def add_node(self, node, parent_id, depth):
'''Add a node to the AST node collection
@ -35,7 +38,7 @@ class BanditMetaAst():
:return: -
'''
node_id = hex(id(node))
logger.debug('adding node : %s [%s]', node_id, depth)
LOG.debug('adding node : %s [%s]', node_id, depth)
self.nodes[node_id] = {
'raw': node, 'parent_id': parent_id, 'depth': depth
}

View File

@ -23,7 +23,7 @@ from bandit.core import tester as b_tester
from bandit.core import utils as b_utils
logger = logging.getLogger(__name__)
LOG = logging.getLogger(__name__)
class BanditNodeVisitor(object):
@ -49,10 +49,10 @@ class BanditNodeVisitor(object):
try:
self.namespace = b_utils.get_module_qualname_from_path(fname)
except b_utils.InvalidModulePath:
logger.info('Unable to find qualified name for module: %s',
self.fname)
LOG.info('Unable to find qualified name for module: %s',
self.fname)
self.namespace = ""
logger.debug('Module qualified name: %s', self.namespace)
LOG.debug('Module qualified name: %s', self.namespace)
self.metrics = metrics
def visit_ClassDef(self, node):
@ -184,14 +184,14 @@ class BanditNodeVisitor(object):
self.context['import_aliases'] = self.import_aliases
if self.debug:
logger.debug(ast.dump(node))
LOG.debug(ast.dump(node))
self.metaast.add_node(node, '', self.depth)
if hasattr(node, 'lineno'):
self.context['lineno'] = node.lineno
if node.lineno in self.nosec_lines:
logger.debug("skipped, nosec")
LOG.debug("skipped, nosec")
self.metrics.note_nosec()
return False
@ -200,10 +200,10 @@ class BanditNodeVisitor(object):
self.context['filename'] = self.fname
self.seen += 1
logger.debug("entering: %s %s [%s]", hex(id(node)), type(node),
self.depth)
LOG.debug("entering: %s %s [%s]", hex(id(node)), type(node),
self.depth)
self.depth += 1
logger.debug(self.context)
LOG.debug(self.context)
return True
def visit(self, node):
@ -212,14 +212,14 @@ class BanditNodeVisitor(object):
visitor = getattr(self, method, None)
if visitor is not None:
if self.debug:
logger.debug("%s called (%s)", method, ast.dump(node))
LOG.debug("%s called (%s)", method, ast.dump(node))
visitor(node)
else:
self.update_scores(self.tester.run_tests(self.context, name))
def post_visit(self, node):
self.depth -= 1
logger.debug("%s\texiting : %s", self.depth, hex(id(node)))
LOG.debug("%s\texiting : %s", self.depth, hex(id(node)))
# HACK(tkelsey): this is needed to clean up post-recursion stuff that
# gets setup in the visit methods for these node types.

View File

@ -18,7 +18,7 @@ import logging
from bandit.core import utils
logger = logging.getLogger(__name__)
LOG = logging.getLogger(__name__)
def checks(*args):
@ -28,8 +28,8 @@ def checks(*args):
func._checks = []
func._checks.extend(utils.check_ast_node(a) for a in args)
logger.debug('checks() decorator executed')
logger.debug(' func._checks: %s', func._checks)
LOG.debug('checks() decorator executed')
LOG.debug(' func._checks: %s', func._checks)
return func
return wrapper
@ -79,8 +79,7 @@ def accepts_baseline(*args):
if not hasattr(func, '_accepts_baseline'):
func._accepts_baseline = True
logger.debug('accepts_baseline() decorator executed on %s',
func.__name__)
LOG.debug('accepts_baseline() decorator executed on %s', func.__name__)
return func
return wrapper(args[0])

View File

@ -24,11 +24,13 @@ from bandit.core import blacklisting
from bandit.core import extension_loader
logger = logging.getLogger(__name__)
LOG = logging.getLogger(__name__)
class BanditTestSet():
def __init__(self, config, profile={}):
def __init__(self, config, profile=None):
if not profile:
profile = {}
extman = extension_loader.MANAGER
filtering = self._get_filter(config, profile)
self.plugins = [p for p in extman.plugins
@ -109,8 +111,8 @@ class BanditTestSet():
plugin.plugin._config = cfg
for check in plugin.plugin._checks:
self.tests.setdefault(check, []).append(plugin.plugin)
logger.debug('added function %s (%s) targetting %s',
plugin.name, plugin.plugin._test_id, check)
LOG.debug('added function %s (%s) targetting %s',
plugin.name, plugin.plugin._test_id, check)
def get_tests(self, checktype):
'''Returns all tests that are of type checktype

View File

@ -23,7 +23,7 @@ from bandit.core import context as b_context
from bandit.core import utils
warnings.formatwarning = utils.warnings_formatter
logger = logging.getLogger(__name__)
LOG = logging.getLogger(__name__)
class BanditTester():
@ -77,9 +77,7 @@ class BanditTester():
self.results.append(result)
logger.debug(
"Issue identified by %s: %s", name, result
)
LOG.debug("Issue identified by %s: %s", name, result)
sev = constants.RANKING.index(result.severity)
val = constants.RANKING_VALUES[result.severity]
scores['SEVERITY'][sev] += val
@ -91,7 +89,7 @@ class BanditTester():
self.report_error(name, context, e)
if self.debug:
raise
logger.debug("Returning scores: %s", scores)
LOG.debug("Returning scores: %s", scores)
return scores
def report_error(self, test, context, error):
@ -104,4 +102,4 @@ class BanditTester():
what += str(error)
import traceback
what += traceback.format_exc()
logger.error(what)
LOG.error(what)

View File

@ -25,7 +25,7 @@ try:
except ImportError:
import ConfigParser as configparser
logger = logging.getLogger(__name__)
LOG = logging.getLogger(__name__)
"""Various helper functions."""
@ -46,11 +46,11 @@ def _get_attr_qual_name(node, aliases):
:param aliases: Import aliases dictionary
:returns: Qualified name referred to by the attribute or name.
'''
if type(node) == _ast.Name:
if isinstance(node, _ast.Name):
if node.id in aliases:
return aliases[node.id]
return node.id
elif type(node) == _ast.Attribute:
elif isinstance(node, _ast.Attribute):
name = '%s.%s' % (_get_attr_qual_name(node.value, aliases), node.attr)
if name in aliases:
return aliases[name]
@ -60,11 +60,11 @@ def _get_attr_qual_name(node, aliases):
def get_call_name(node, aliases):
if type(node.func) == _ast.Name:
if isinstance(node.func, _ast.Name):
if deepgetattr(node, 'func.id') in aliases:
return aliases[deepgetattr(node, 'func.id')]
return(deepgetattr(node, 'func.id'))
elif type(node.func) == _ast.Attribute:
return deepgetattr(node, 'func.id')
elif isinstance(node.func, _ast.Attribute):
return _get_attr_qual_name(node.func, aliases)
else:
return ""
@ -76,7 +76,7 @@ def get_func_name(node):
def get_qual_attr(node, aliases):
prefix = ""
if type(node) == _ast.Attribute:
if isinstance(node, _ast.Attribute):
try:
val = deepgetattr(node, 'value.id')
if val in aliases:
@ -88,7 +88,7 @@ def get_qual_attr(node, aliases):
# qualified name for an attr, just return its base name.
pass
return("%s.%s" % (prefix, node.attr))
return "%s.%s" % (prefix, node.attr)
else:
return "" # TODO(tkelsey): process other node types
@ -122,10 +122,7 @@ class ProfileNotFound(Exception):
super(ProfileNotFound, self).__init__(message)
def warnings_formatter(message,
category=UserWarning,
filename='',
lineno=-1,
def warnings_formatter(message, category=UserWarning, filename='', lineno=-1,
line=''):
'''Monkey patch for warnings.warn to suppress cruft output.'''
return "{0}\n".format(message)
@ -286,7 +283,7 @@ def get_called_name(node):
'''
func = node.func
try:
return (func.attr if isinstance(func, ast.Attribute) else func.id)
return func.attr if isinstance(func, ast.Attribute) else func.id
except AttributeError:
return ""
@ -303,14 +300,14 @@ def get_path_for_function(f):
elif hasattr(f, "im_func"):
module_name = f.im_func.__module__
else:
logger.warning("Cannot resolve file where %s is defined", f)
LOG.warning("Cannot resolve file where %s is defined", f)
return None
module = sys.modules[module_name]
if hasattr(module, "__file__"):
return module.__file__
else:
logger.warning("Cannot resolve file path for module %s", module_name)
LOG.warning("Cannot resolve file path for module %s", module_name)
return None
@ -321,8 +318,8 @@ def parse_ini_file(f_loc):
return {k: v for k, v in config.items('bandit')}
except (configparser.Error, KeyError, TypeError):
logger.warning("Unable to parse config file %s or missing [bandit] "
"section", f_loc)
LOG.warning("Unable to parse config file %s or missing [bandit] "
"section", f_loc)
return None

View File

@ -40,7 +40,7 @@ import csv
import logging
import sys
logger = logging.getLogger(__name__)
LOG = logging.getLogger(__name__)
def report(manager, fileobj, sev_level, conf_level, lines=-1):
@ -73,4 +73,4 @@ def report(manager, fileobj, sev_level, conf_level, lines=-1):
writer.writerow(result.as_dict(with_code=False))
if fileobj.name != sys.stdout.name:
logger.info("CSV output written to file: %s" % fileobj.name)
LOG.info("CSV output written to file: %s", fileobj.name)

View File

@ -153,7 +153,7 @@ import sys
from bandit.core import docs_utils
from bandit.core import test_properties
logger = logging.getLogger(__name__)
LOG = logging.getLogger(__name__)
@test_properties.accepts_baseline
@ -376,4 +376,4 @@ pre {
fileobj.write(str(report_contents.encode('utf-8')))
if fileobj.name != sys.stdout.name:
logger.info("HTML output written to file: %s" % fileobj.name)
LOG.info("HTML output written to file: %s", fileobj.name)

View File

@ -104,7 +104,7 @@ import six
from bandit.core import constants
from bandit.core import test_properties
logger = logging.getLogger(__name__)
LOG = logging.getLogger(__name__)
@test_properties.accepts_baseline
@ -182,4 +182,4 @@ def report(manager, fileobj, sev_level, conf_level, lines=-1):
fileobj.write(result)
if fileobj.name != sys.stdout.name:
logger.info("JSON output written to file: %s" % fileobj.name)
LOG.info("JSON output written to file: %s", fileobj.name)

View File

@ -46,9 +46,9 @@ import sys
from bandit.core import constants
from bandit.core import test_properties
logger = logging.getLogger(__name__)
LOG = logging.getLogger(__name__)
color = {
COLOR = {
'DEFAULT': '\033[0m',
'HEADER': '\033[95m',
'LOW': '\033[94m',
@ -58,7 +58,7 @@ color = {
def header(text, *args):
return u'%s%s%s' % (color['HEADER'], (text % args), color['DEFAULT'])
return u'%s%s%s' % (COLOR['HEADER'], (text % args), COLOR['DEFAULT'])
def get_verbose_details(manager):
@ -90,7 +90,7 @@ def _output_issue_str(issue, indent, show_lineno=True, show_code=True,
# returns a list of lines that should be added to the existing lines list
bits = []
bits.append("%s%s>> Issue: [%s:%s] %s" % (
indent, color[issue.severity], issue.test_id, issue.test, issue.text))
indent, COLOR[issue.severity], issue.test_id, issue.test, issue.text))
bits.append("%s Severity: %s Confidence: %s" % (
indent, issue.severity.capitalize(), issue.confidence.capitalize()))
@ -98,7 +98,7 @@ def _output_issue_str(issue, indent, show_lineno=True, show_code=True,
bits.append("%s Location: %s:%s%s" % (
indent, issue.fname,
issue.lineno if show_lineno else "",
color['DEFAULT']))
COLOR['DEFAULT']))
if show_code:
bits.extend([indent + l for l in
@ -177,5 +177,5 @@ def report(manager, fileobj, sev_level, conf_level, lines=-1):
do_print(bits)
if fileobj.name != sys.stdout.name:
logger.info(("Screen formatter output was not written to file: %s"
", consider '-f txt'") % fileobj.name)
LOG.info("Screen formatter output was not written to file: %s, "
"consider '-f txt'", fileobj.name)

View File

@ -46,7 +46,7 @@ import sys
from bandit.core import constants
from bandit.core import test_properties
logger = logging.getLogger(__name__)
LOG = logging.getLogger(__name__)
def get_verbose_details(manager):
@ -158,4 +158,4 @@ def report(manager, fileobj, sev_level, conf_level, lines=-1):
fileobj.write(str(result.encode('utf-8')))
if fileobj.name != sys.stdout.name:
logger.info("Text output written to file: %s", fileobj.name)
LOG.info("Text output written to file: %s", fileobj.name)

View File

@ -46,7 +46,7 @@ from xml.etree import cElementTree as ET
import six
logger = logging.getLogger(__name__)
LOG = logging.getLogger(__name__)
def report(manager, fileobj, sev_level, conf_level, lines=-1):
@ -88,4 +88,4 @@ def report(manager, fileobj, sev_level, conf_level, lines=-1):
tree.write(fileobj, encoding='utf-8', xml_declaration=True)
if fileobj.name != sys.stdout.name:
logger.info("XML output written to file: %s" % fileobj.name)
LOG.info("XML output written to file: %s", fileobj.name)

View File

@ -57,9 +57,9 @@ from bandit.core import test_properties as test
@test.test_id('B101')
@test.checks('Assert')
def assert_used(context):
return bandit.Issue(
severity=bandit.LOW,
confidence=bandit.HIGH,
text=("Use of assert detected. The enclosed code "
"will be removed when compiling to optimised byte code.")
)
return bandit.Issue(
severity=bandit.LOW,
confidence=bandit.HIGH,
text=("Use of assert detected. The enclosed code "
"will be removed when compiling to optimised byte code.")
)

View File

@ -70,10 +70,8 @@ def set_bad_file_permissions(context):
if context.call_args_count == 2:
mode = context.get_call_arg_at_position(1)
if (
mode is not None and type(mode) == int and
(mode & stat.S_IWOTH or mode & stat.S_IXGRP)
):
if (mode is not None and isinstance(mode, int) and
(mode & stat.S_IWOTH or mode & stat.S_IXGRP)):
# world writable is an HIGH, group executable is a MEDIUM
if mode & stat.S_IWOTH:
sev_level = bandit.HIGH
@ -87,5 +85,5 @@ def set_bad_file_permissions(context):
severity=sev_level,
confidence=bandit.HIGH,
text="Chmod setting a permissive mask %s on file (%s)." %
(oct(mode), filename)
(oct(mode), filename)
)

View File

@ -21,7 +21,7 @@ import bandit
from bandit.core import test_properties as test
candidates = set(["password", "pass", "passwd", "pwd", "secret", "token",
CANDIDATES = set(["password", "pass", "passwd", "pwd", "secret", "token",
"secrete"])
@ -84,10 +84,10 @@ def hardcoded_password_string(context):
if isinstance(node.parent, ast.Assign):
# looks for "candidate='some_string'"
for targ in node.parent.targets:
if isinstance(targ, ast.Name) and targ.id in candidates:
if isinstance(targ, ast.Name) and targ.id in CANDIDATES:
return _report(node.s)
elif isinstance(node.parent, ast.Index) and node.s in candidates:
elif isinstance(node.parent, ast.Index) and node.s in CANDIDATES:
# looks for "dict[candidate]='some_string'"
# assign -> subscript -> index -> string
assign = node.parent.parent.parent
@ -98,7 +98,7 @@ def hardcoded_password_string(context):
elif isinstance(node.parent, ast.Compare):
# looks for "candidate == 'some_string'"
comp = node.parent
if isinstance(comp.left, ast.Name) and comp.left.id in candidates:
if isinstance(comp.left, ast.Name) and comp.left.id in CANDIDATES:
if isinstance(comp.comparators[0], ast.Str):
return _report(comp.comparators[0].s)
@ -150,7 +150,7 @@ def hardcoded_password_funcarg(context):
"""
# looks for "function(candidate='some_string')"
for kw in context.node.keywords:
if isinstance(kw.value, ast.Str) and kw.arg in candidates:
if isinstance(kw.value, ast.Str) and kw.arg in CANDIDATES:
return _report(kw.value.s)
@ -211,5 +211,5 @@ def hardcoded_password_default(context):
for key, val in zip(context.node.args.args, defs):
if isinstance(key, ast.Name):
check = key.arg if sys.version_info.major > 2 else key.id # Py3
if isinstance(val, ast.Str) and check in candidates:
if isinstance(val, ast.Str) and check in CANDIDATES:
return _report(val.s)

View File

@ -73,7 +73,7 @@ def gen_config(name):
@test.checks('Str')
@test.test_id('B108')
def hardcoded_tmp_directory(context, config):
if (config is not None and 'tmp_dirs' in config):
if config is not None and 'tmp_dirs' in config:
tmp_dirs = config['tmp_dirs']
else:
tmp_dirs = ['/tmp', '/var/tmp', '/dev/shm']

View File

@ -656,7 +656,7 @@ def start_process_with_partial_path(context, config):
node = node.elts[0]
# make sure the param is a string literal and not a var name
if(isinstance(node, ast.Str) and node.s[0] not in delims):
if isinstance(node, ast.Str) and node.s[0] not in delims:
return bandit.Issue(
severity=bandit.LOW,
confidence=bandit.HIGH,

View File

@ -144,6 +144,6 @@ def linux_commands_wildcard_injection(context, config):
severity=bandit.HIGH,
confidence=bandit.MEDIUM,
text="Possible wildcard injection in call: %s" %
context.call_function_name_qual,
context.call_function_name_qual,
lineno=context.get_lineno_for_call_arg('shell'),
)

View File

@ -31,8 +31,7 @@ def gen_config(name):
'PROTOCOL_SSLv3', # strict option
'PROTOCOL_TLSv1', # strict option
'SSLv3_METHOD', # strict option
'TLSv1_METHOD'] # strict option
}
'TLSv1_METHOD']} # strict option
@test.takes_config
@ -117,7 +116,7 @@ def ssl_with_bad_version(context, config):
.. versionadded:: 0.9.0
"""
bad_ssl_versions = get_bad_proto_versions(config)
if (context.call_function_name_qual == 'ssl.wrap_socket'):
if context.call_function_name_qual == 'ssl.wrap_socket':
if context.check_call_arg_value('ssl_version', bad_ssl_versions):
return bandit.Issue(
severity=bandit.HIGH,
@ -126,7 +125,7 @@ def ssl_with_bad_version(context, config):
"version identified, security issue.",
lineno=context.get_lineno_for_call_arg('ssl_version'),
)
elif (context.call_function_name_qual == 'pyOpenSSL.SSL.Context'):
elif context.call_function_name_qual == 'pyOpenSSL.SSL.Context':
if context.check_call_arg_value('method', bad_ssl_versions):
return bandit.Issue(
severity=bandit.HIGH,
@ -139,7 +138,7 @@ def ssl_with_bad_version(context, config):
elif (context.call_function_name_qual != 'ssl.wrap_socket' and
context.call_function_name_qual != 'pyOpenSSL.SSL.Context'):
if (context.check_call_arg_value('method', bad_ssl_versions) or
context.check_call_arg_value('ssl_version', bad_ssl_versions)):
context.check_call_arg_value('ssl_version', bad_ssl_versions)):
lineno = (context.get_lineno_for_call_arg('method') or
context.get_lineno_for_call_arg('ssl_version'))
return bandit.Issue(
@ -259,7 +258,7 @@ def ssl_with_no_version(context):
.. versionadded:: 0.9.0
"""
if (context.call_function_name_qual == 'ssl.wrap_socket'):
if context.call_function_name_qual == 'ssl.wrap_socket':
if context.check_call_arg_value('ssl_version') is None:
# check_call_arg_value() returns False if the argument is found
# but does not match the supplied value (or the default None).

View File

@ -78,7 +78,7 @@ from bandit.core import test_properties as test
@test.test_id('B701')
def jinja2_autoescape_false(context):
# check type just to be safe
if type(context.call_function_name_qual) == str:
if isinstance(context.call_function_name_qual, str):
qualname_list = context.call_function_name_qual.split('.')
func = qualname_list[-1]
if 'jinja2' in qualname_list and func == 'Environment':
@ -87,7 +87,7 @@ def jinja2_autoescape_false(context):
# definite autoescape = False
if (getattr(node, 'arg', None) == 'autoescape' and
(getattr(node.value, 'id', None) == 'False' or
getattr(node.value, 'value', None) is False)):
getattr(node.value, 'value', None) is False)):
return bandit.Issue(
severity=bandit.HIGH,
confidence=bandit.HIGH,

View File

@ -59,7 +59,7 @@ from bandit.core import test_properties as test
@test.test_id('B702')
def use_of_mako_templates(context):
# check type just to be safe
if type(context.call_function_name_qual) == str:
if isinstance(context.call_function_name_qual, str):
qualname_list = context.call_function_name_qual.split('.')
func = qualname_list[-1]
if 'mako' in qualname_list and func == 'Template':

View File

@ -99,9 +99,9 @@ def try_except_continue(context, config):
node = context.node
if len(node.body) == 1:
if (not config['check_typed_exception'] and
node.type is not None and
getattr(node.type, 'id', None) != 'Exception'):
return
node.type is not None and
getattr(node.type, 'id', None) != 'Exception'):
return
if isinstance(node.body[0], ast.Continue):
return bandit.Issue(

View File

@ -98,9 +98,9 @@ def try_except_pass(context, config):
node = context.node
if len(node.body) == 1:
if (not config['check_typed_exception'] and
node.type is not None and
getattr(node.type, 'id', None) != 'Exception'):
return
node.type is not None and
getattr(node.type, 'id', None) != 'Exception'):
return
if isinstance(node.body[0], ast.Pass):
return bandit.Issue(

View File

@ -67,7 +67,7 @@ def _classify_key_size(key_type, key_size):
severity=level,
confidence=bandit.HIGH,
text='%s key sizes below %d bits are considered breakable. ' %
(key_type, size))
(key_type, size))
def _weak_crypto_key_size_cryptography_io(context):

View File

@ -55,7 +55,7 @@ from bandit.core import test_properties as test
@test.test_id('B506')
@test.checks('Call')
def yaml_load(context):
if type(context.call_function_name_qual) == str:
if isinstance(context.call_function_name_qual, str):
qualname_list = context.call_function_name_qual.split('.')
func = qualname_list[-1]
if 'yaml' in qualname_list and func == 'load':

76
pylintrc Normal file
View File

@ -0,0 +1,76 @@
# The format of this file isn't really documented; just use --generate-rcfile
[Messages Control]
# C0111: Don't require docstrings on every method
# C0301: Handled by pep8
# C0325: Parens are required on print in py3x
# F0401: Imports are check by other linters
# W0511: TODOs in code comments are fine.
# W0142: *args and **kwargs are fine.
# W0622: Redefining id is fine.
# TODO(browne): fix these in the future
# C0103: invalid-name
# C1001: old-style-class
# E1101: no-member
# R0201: no-self-use
# R0204: redefined-variable-typ
# R0902: too-many-instance-attributes
# R0911: too-many-return-statements
# R0912: too-many-branches
# R0913: too-many-arguments
# R0914: too-many-locals
# R0915: too-many-statements
# W0110: deprecated-lambda
# W0141: bad-builtin
# W0201: attribute-defined-outside-init
# W0212: protected-access
# W0401: wildcard-import
# W0603: global-statement
# W0612: unused-variable
# W0613: unused-argument
# W0621: redefined-outer-name
# W0703: broad-except
disable=C0111,C0301,C0325,C1001,F0401,W0511,W0142,W0622,C0103,E1101,R0201,R0204,R0902,R0911,R0912,R0913,R0914,R0915,W0110,W0141,W0201,W0401,W0603,W0212,W0612,W0613,W0621,W0703
[Basic]
# Variable names can be 1 to 31 characters long, with lowercase and underscores
variable-rgx=[a-z_][a-z0-9_]{0,30}$
# Argument names can be 2 to 31 characters long, with lowercase and underscores
argument-rgx=[a-z_][a-z0-9_]{1,30}$
# Method names should be at least 3 characters long
# and be lowecased with underscores
method-rgx=([a-z_][a-z0-9_]{2,50}|setUp|tearDown)$
# Module names matching manila-* are ok (files in bin/)
module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+)|(manila-[a-z0-9_-]+))$
# Don't require docstrings on tests.
no-docstring-rgx=((__.*__)|([tT]est.*)|setUp|tearDown)$
[Design]
max-public-methods=100
min-public-methods=0
max-args=6
[Variables]
# List of additional names supposed to be defined in builtins. Remember that
# you should avoid to define new builtins when possible.
# _ is used by our localization
additional-builtins=_
[Similarities]
# Minimum lines number of a similarity.
min-similarity-lines=10
# Ignore comments when computing similarities.
ignore-comments=yes
# Ignore docstrings when computing similarities.
ignore-docstrings=yes
# Ignore imports when computing similarities.
ignore-imports=yes

View File

@ -15,3 +15,5 @@ sphinx!=1.3b1,<1.4,>=1.2.1 # BSD
oslosphinx>=4.7.0 # Apache-2.0
beautifulsoup4 # MIT
reno>=1.8.0 # Apache-2.0
pylint==1.4.5 # GPLv2

View File

@ -189,7 +189,7 @@ class BanditBaselineToolTests(testtools.TestCase):
def test_init_logger(self):
# Test whether the logger was initialized when calling init_logger
baseline.init_logger()
logger = baseline.logger
logger = baseline.LOG
# verify that logger was initialized
self.assertIsNotNone(logger)

View File

@ -187,7 +187,7 @@ class BanditCLIMainTests(testtools.TestCase):
"skips": "skip_test",
"tests": "some_test"}
with mock.patch('bandit.cli.main.logger.error') as err_mock:
with mock.patch('bandit.cli.main.LOG.error') as err_mock:
# SystemExit with code 2 when test not found in profile
self.assertRaisesRegex(SystemExit, '2', bandit.main)
self.assertEqual(str(err_mock.call_args[0][0]),
@ -224,7 +224,7 @@ class BanditCLIMainTests(testtools.TestCase):
with open('bandit.yaml', 'wt') as fd:
fd.write(bandit_config_content)
# assert a SystemExit with code 2
with mock.patch('bandit.cli.main.logger.error') as err_mock:
with mock.patch('bandit.cli.main.LOG.error') as err_mock:
self.assertRaisesRegex(SystemExit, '2', bandit.main)
self.assertEqual(
str(err_mock.call_args[0][0]),

View File

@ -233,7 +233,7 @@ class TestConfigCompat(testtools.TestCase):
"'bandit-config-generator' can help you with this. Support for "
"legacy configs will be removed in a future bandit version.")
with mock.patch('bandit.core.config.logger.warn') as m:
with mock.patch('bandit.core.config.LOG.warn') as m:
self.config._config = {"profiles": {}}
self.config.validate('')
self.assertEqual((msg, ''), m.call_args_list[0][0])

View File

@ -46,27 +46,27 @@ class ScreenFormatterTests(testtools.TestCase):
_issue.confidence.capitalize()),
"{} Location: {}:{}{}".
format(_indent_val, _issue.fname, _issue.lineno,
screen.color['DEFAULT'])]
screen.COLOR['DEFAULT'])]
if _code:
return_val.append("{}{}".format(_indent_val, _code))
return '\n'.join(return_val)
issue_text = screen._output_issue_str(issue, indent_val)
expected_return = _template(issue, indent_val, 'DDDDDDD',
screen.color['MEDIUM'])
screen.COLOR['MEDIUM'])
self.assertEqual(expected_return, issue_text)
issue_text = screen._output_issue_str(issue, indent_val,
show_code=False)
expected_return = _template(issue, indent_val, '',
screen.color['MEDIUM'])
screen.COLOR['MEDIUM'])
self.assertEqual(expected_return, issue_text)
issue.lineno = ''
issue_text = screen._output_issue_str(issue, indent_val,
show_lineno=False)
expected_return = _template(issue, indent_val, 'DDDDDDD',
screen.color['MEDIUM'])
screen.COLOR['MEDIUM'])
self.assertEqual(expected_return, issue_text)
@mock.patch('bandit.core.manager.BanditManager.get_issue_list')

View File

@ -32,6 +32,7 @@ deps = {[testenv]deps}
.
commands = flake8 {posargs} bandit
flake8 {posargs} tests
{[testenv:pylint]commands}
bandit-baseline -r bandit -ll -ii
[testenv:venv]
@ -68,3 +69,6 @@ exclude=.venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build,rele
[testenv:releasenotes]
commands = sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html
[testenv:pylint]
commands = pylint --rcfile=pylintrc bandit