From 464a0610bad82fe6d437fd3075232a185072bc76 Mon Sep 17 00:00:00 2001 From: Anthony Shaw Date: Tue, 2 Jun 2020 11:13:30 +1000 Subject: [PATCH 01/17] Rename blacklist to banlist across the namespace --- bandit/{blacklists => banlists}/__init__.py | 0 bandit/{blacklists => banlists}/calls.py | 22 ++++---- bandit/{blacklists => banlists}/imports.py | 24 ++++---- bandit/{blacklists => banlists}/utils.py | 2 +- bandit/cli/config_generator.py | 2 +- bandit/cli/main.py | 8 +-- .../core/{blacklisting.py => banlisting.py} | 20 +++---- bandit/core/config.py | 48 ++++++++-------- bandit/core/docs_utils.py | 4 +- bandit/core/extension_loader.py | 32 +++++------ bandit/core/test_set.py | 46 +++++++-------- bandit/formatters/csv.py | 2 +- bandit/formatters/custom.py | 7 ++- bandit/formatters/json.py | 2 +- bandit/formatters/text.py | 2 +- bandit/formatters/xml.py | 2 +- .../plugins/hashlib_new_insecure_functions.py | 2 +- doc/source/banlists/banlist_calls.rst | 5 ++ doc/source/banlists/banlist_imports.rst | 5 ++ doc/source/{blacklists => banlists}/index.rst | 28 +++++----- doc/source/blacklists/blacklist_calls.rst | 5 -- doc/source/blacklists/blacklist_imports.rst | 5 -- doc/source/config.rst | 2 +- doc/source/index.rst | 2 +- doc/source/plugins/index.rst | 4 +- setup.cfg | 6 +- tests/functional/test_baseline.py | 2 +- tests/functional/test_functional.py | 8 +-- tests/functional/test_runtime.py | 4 +- tests/unit/core/test_blacklisting.py | 8 +-- tests/unit/core/test_config.py | 44 +++++++-------- tests/unit/core/test_docs_util.py | 4 +- tests/unit/core/test_test_set.py | 56 +++++++++---------- 33 files changed, 207 insertions(+), 206 deletions(-) rename bandit/{blacklists => banlists}/__init__.py (100%) rename bandit/{blacklists => banlists}/calls.py (97%) rename bandit/{blacklists => banlists}/imports.py (95%) rename bandit/{blacklists => banlists}/utils.py (83%) rename bandit/core/{blacklisting.py => banlisting.py} (77%) create mode 100644 doc/source/banlists/banlist_calls.rst create mode 100644 doc/source/banlists/banlist_imports.rst rename doc/source/{blacklists => banlists}/index.rst (70%) delete mode 100644 doc/source/blacklists/blacklist_calls.rst delete mode 100644 doc/source/blacklists/blacklist_imports.rst diff --git a/bandit/blacklists/__init__.py b/bandit/banlists/__init__.py similarity index 100% rename from bandit/blacklists/__init__.py rename to bandit/banlists/__init__.py diff --git a/bandit/blacklists/calls.py b/bandit/banlists/calls.py similarity index 97% rename from bandit/blacklists/calls.py rename to bandit/banlists/calls.py index 85bec160e..b274309de 100644 --- a/bandit/blacklists/calls.py +++ b/bandit/banlists/calls.py @@ -6,11 +6,11 @@ r""" ==================================================== -Blacklist various Python calls known to be dangerous +Banlist various Python calls known to be dangerous ==================================================== -This blacklist data checks for a number of Python calls known to have possible -security implications. The following blacklist tests are run against any +This banlist data checks for a number of Python calls known to have possible +security implications. The following banlist tests are run against any function calls encoutered in the scanned code base, triggered by encoutering ast.Call nodes. @@ -313,19 +313,19 @@ """ -from bandit.blacklists import utils +from bandit.banlists import utils -def gen_blacklist(): - """Generate a list of items to blacklist. +def gen_banlist(): + """Generate a list of items to banlist. - Methods of this type, "bandit.blacklist" plugins, are used to build a list - of items that bandit's built in blacklisting tests will use to trigger - issues. They replace the older blacklist* test plugins and allow - blacklisted items to have a unique bandit ID for filtering and profile + Methods of this type, "bandit.banlist" plugins, are used to build a list + of items that bandit's built in banlisting tests will use to trigger + issues. They replace the older banlist* test plugins and allow + banlisted items to have a unique bandit ID for filtering and profile usage. - :return: a dictionary mapping node types to a list of blacklist data + :return: a dictionary mapping node types to a list of banlist data """ sets = [] diff --git a/bandit/blacklists/imports.py b/bandit/banlists/imports.py similarity index 95% rename from bandit/blacklists/imports.py rename to bandit/banlists/imports.py index 4d9e180c1..1ebb1eac8 100644 --- a/bandit/blacklists/imports.py +++ b/bandit/banlists/imports.py @@ -6,11 +6,11 @@ r""" ====================================================== -Blacklist various Python imports known to be dangerous +Banlist various Python imports known to be dangerous ====================================================== -This blacklist data checks for a number of Python modules known to have -possible security implications. The following blacklist tests are run against +This banlist data checks for a number of Python modules known to have +possible security implications. The following banlist tests are run against any import statements or calls encountered in the scanned code base. Note that the XML rules listed here are mostly based off of Christian Heimes' @@ -193,7 +193,7 @@ B414: import_pycryptodome ------------------------- -This import blacklist has been removed. The information here has been +This import banlist has been removed. The information here has been left for historical purposes. pycryptodome is a direct fork of pycrypto that has not fully addressed @@ -216,19 +216,19 @@ """ -from bandit.blacklists import utils +from bandit.banlists import utils -def gen_blacklist(): - """Generate a list of items to blacklist. +def gen_banlist(): + """Generate a list of items to banlist. - Methods of this type, "bandit.blacklist" plugins, are used to build a list - of items that bandit's built in blacklisting tests will use to trigger - issues. They replace the older blacklist* test plugins and allow - blacklisted items to have a unique bandit ID for filtering and profile + Methods of this type, "bandit.banlist" plugins, are used to build a list + of items that bandit's built in banlisting tests will use to trigger + issues. They replace the older banlist* test plugins and allow + banlisted items to have a unique bandit ID for filtering and profile usage. - :return: a dictionary mapping node types to a list of blacklist data + :return: a dictionary mapping node types to a list of banlist data """ sets = [] diff --git a/bandit/blacklists/utils.py b/bandit/banlists/utils.py similarity index 83% rename from bandit/blacklists/utils.py rename to bandit/banlists/utils.py index bb1b24e91..6c9bd1ba4 100644 --- a/bandit/blacklists/utils.py +++ b/bandit/banlists/utils.py @@ -6,7 +6,7 @@ def build_conf_dict(name, bid, qualnames, message, level='MEDIUM'): - """Build and return a blacklist configuration dict.""" + """Build and return a banlist configuration dict.""" return {'name': name, 'id': bid, 'message': message, 'qualnames': qualnames, 'level': level} diff --git a/bandit/cli/config_generator.py b/bandit/cli/config_generator.py index 0a41949cc..e784ee97e 100644 --- a/bandit/cli/config_generator.py +++ b/bandit/cli/config_generator.py @@ -148,7 +148,7 @@ def main(): for t in extension_loader.MANAGER.plugins] others = [tpl.format(k, v['name']) for k, v in ( - extension_loader.MANAGER.blacklist_by_id.items())] + extension_loader.MANAGER.banlist_by_id.items())] test_list.extend(others) test_list.sort() diff --git a/bandit/cli/main.py b/bandit/cli/main.py index a96f6977b..4ae4e9b42 100644 --- a/bandit/cli/main.py +++ b/bandit/cli/main.py @@ -256,12 +256,12 @@ def main(): plugin_info = ["%s\t%s" % (a[0], a[1].name) for a in extension_mgr.plugins_by_id.items()] - blacklist_info = [] - for a in extension_mgr.blacklist.items(): + banlist_info = [] + for a in extension_mgr.banlist.items(): for b in a[1]: - blacklist_info.append('%s\t%s' % (b['id'], b['name'])) + banlist_info.append('%s\t%s' % (b['id'], b['name'])) - plugin_list = '\n\t'.join(sorted(set(plugin_info + blacklist_info))) + plugin_list = '\n\t'.join(sorted(set(plugin_info + banlist_info))) dedent_text = textwrap.dedent(''' CUSTOM FORMATTING ----------------- diff --git a/bandit/core/blacklisting.py b/bandit/core/banlisting.py similarity index 77% rename from bandit/core/blacklisting.py rename to bandit/core/banlisting.py index aecf1512f..aa5a575fb 100644 --- a/bandit/core/blacklisting.py +++ b/bandit/core/banlisting.py @@ -17,17 +17,17 @@ def report_issue(check, name): ident=name, test_id=check.get("id", 'LEGACY')) -def blacklist(context, config): - """Generic blacklist test, B001. +def banlist(context, config): + """Generic banlist test, B001. - This generic blacklist test will be called for any encountered node with - defined blacklist data available. This data is loaded via plugins using - the 'bandit.blacklists' entry point. Please see the documentation for more - details. Each blacklist datum has a unique bandit ID that may be used for - filtering purposes, or alternatively all blacklisting can be filtered using + This generic banlist test will be called for any encountered node with + defined banlist data available. This data is loaded via plugins using + the 'bandit.banlists' entry point. Please see the documentation for more + details. Each banlist datum has a unique bandit ID that may be used for + filtering purposes, or alternatively all banlisting can be filtered using the id of this built in test, 'B001'. """ - blacklists = config + banlists = config node_type = context.node.__class__.__name__ if node_type == 'Call': @@ -48,7 +48,7 @@ def blacklist(context, config): # Will produce None if argument is not a literal or identifier if name in ["importlib.import_module", "importlib.__import__"]: name = context.call_args[0] - for check in blacklists[node_type]: + for check in banlists[node_type]: for qn in check['qualnames']: if name is not None and fnmatch.fnmatch(name, qn): return report_issue(check, name) @@ -59,7 +59,7 @@ def blacklist(context, config): if context.node.module is not None: prefix = context.node.module + "." - for check in blacklists[node_type]: + for check in banlists[node_type]: for name in context.node.names: for qn in check['qualnames']: if (prefix + name.name).startswith(qn): diff --git a/bandit/core/config.py b/bandit/core/config.py index 422432bfb..003035f56 100644 --- a/bandit/core/config.py +++ b/bandit/core/config.py @@ -111,11 +111,11 @@ def _init_plugin_name_pattern(self): def convert_legacy_config(self): updated_profiles = self.convert_names_to_ids() - bad_calls, bad_imports = self.convert_legacy_blacklist_data() + bad_calls, bad_imports = self.convert_legacy_banlist_data() if updated_profiles: - self.convert_legacy_blacklist_tests(updated_profiles, - bad_calls, bad_imports) + self.convert_legacy_banlist_tests(updated_profiles, + bad_calls, bad_imports) self._config['profiles'] = updated_profiles def convert_names_to_ids(self): @@ -134,12 +134,12 @@ def convert_names_to_ids(self): updated_profiles[name] = {'include': include, 'exclude': exclude} return updated_profiles - def convert_legacy_blacklist_data(self): - '''Detect legacy blacklist data and convert it to new format.''' + def convert_legacy_banlist_data(self): + '''Detect legacy banlist data and convert it to new format.''' bad_calls_list = [] bad_imports_list = [] - bad_calls = self.get_option('blacklist_calls') or {} + bad_calls = self.get_option('banlist_calls') or {} bad_calls = bad_calls.get('bad_name_sets', {}) for item in bad_calls: for key, val in item.items(): @@ -147,7 +147,7 @@ def convert_legacy_blacklist_data(self): val['message'] = val['message'].replace('{func}', '{name}') bad_calls_list.append(val) - bad_imports = self.get_option('blacklist_imports') or {} + bad_imports = self.get_option('banlist_imports') or {} bad_imports = bad_imports.get('bad_import_sets', {}) for item in bad_imports: for key, val in item.items(): @@ -158,47 +158,47 @@ def convert_legacy_blacklist_data(self): bad_imports_list.append(val) if bad_imports_list or bad_calls_list: - LOG.warning('Legacy blacklist data found in config, overriding ' + LOG.warning('Legacy banlist data found in config, overriding ' 'data plugins') return bad_calls_list, bad_imports_list @staticmethod - def convert_legacy_blacklist_tests(profiles, bad_imports, bad_calls): - '''Detect old blacklist tests, convert to use new builtin.''' + def convert_legacy_banlist_tests(profiles, bad_imports, bad_calls): + '''Detect old banlist tests, convert to use new builtin.''' def _clean_set(name, data): if name in data: data.remove(name) data.add('B001') for name, profile in profiles.items(): - blacklist = {} + banlist = {} include = profile['include'] exclude = profile['exclude'] - name = 'blacklist_calls' + name = 'banlist_calls' if name in include and name not in exclude: - blacklist.setdefault('Call', []).extend(bad_calls) + banlist.setdefault('Call', []).extend(bad_calls) _clean_set(name, include) _clean_set(name, exclude) - name = 'blacklist_imports' + name = 'banlist_imports' if name in include and name not in exclude: - blacklist.setdefault('Import', []).extend(bad_imports) - blacklist.setdefault('ImportFrom', []).extend(bad_imports) - blacklist.setdefault('Call', []).extend(bad_imports) + banlist.setdefault('Import', []).extend(bad_imports) + banlist.setdefault('ImportFrom', []).extend(bad_imports) + banlist.setdefault('Call', []).extend(bad_imports) _clean_set(name, include) _clean_set(name, exclude) - _clean_set('blacklist_import_func', include) - _clean_set('blacklist_import_func', exclude) + _clean_set('banlist_import_func', include) + _clean_set('banlist_import_func', exclude) # This can happen with a legacy config that includes - # blacklist_calls but exclude blacklist_imports for example + # banlist_calls but exclude banlist_imports for example if 'B001' in include and 'B001' in exclude: exclude.remove('B001') - profile['blacklist'] = blacklist + profile['banlist'] = banlist def validate(self, path): '''Validate the config data.''' @@ -221,9 +221,9 @@ def _test(key, block, exclude, include): inc = profile.get('include') or set() exc = profile.get('exclude') or set() - _test('blacklist_imports', 'blacklist_imports', inc, exc) - _test('blacklist_import_func', 'blacklist_imports', inc, exc) - _test('blacklist_calls', 'blacklist_calls', inc, exc) + _test('banlist_imports', 'banlist_imports', inc, exc) + _test('banlist_import_func', 'banlist_imports', inc, exc) + _test('banlist_calls', 'banlist_calls', inc, exc) # show deprecation message if legacy: diff --git a/bandit/core/docs_utils.py b/bandit/core/docs_utils.py index f41722652..f11ab45fb 100644 --- a/bandit/core/docs_utils.py +++ b/bandit/core/docs_utils.py @@ -19,9 +19,9 @@ def get_url(bid): return '%splugins/%s_%s.html' % (BASE_URL, bid.lower(), info.plugin.__name__) - info = extension_loader.MANAGER.blacklist_by_id.get(bid) + info = extension_loader.MANAGER.banlist_by_id.get(bid) if info is not None: - template = 'blacklists/blacklist_{kind}.html#{id}-{name}' + template = 'banlists/banlist_{kind}.html#{id}-{name}' info['name'] = info['name'].replace('_', '-') if info['id'].startswith('B3'): # B3XX diff --git a/bandit/core/extension_loader.py b/bandit/core/extension_loader.py index 05f941102..4c0f1f41f 100644 --- a/bandit/core/extension_loader.py +++ b/bandit/core/extension_loader.py @@ -15,16 +15,16 @@ class Manager(object): # These IDs are for bandit built in tests builtin = [ - 'B001' # Built in blacklist test + 'B001' # Built in banlist test ] def __init__(self, formatters_namespace='bandit.formatters', plugins_namespace='bandit.plugins', - blacklists_namespace='bandit.blacklists'): + banlists_namespace='bandit.banlists'): # Cache the extension managers, loaded extensions, and extension names self.load_formatters(formatters_namespace) self.load_plugins(plugins_namespace) - self.load_blacklists(blacklists_namespace) + self.load_banlists(banlists_namespace) def load_formatters(self, formatters_namespace): self.formatters_mgr = extension.ExtensionManager( @@ -60,25 +60,25 @@ def get_plugin_id(self, plugin_name): return self.plugins_by_name[plugin_name].plugin._test_id return None - def load_blacklists(self, blacklist_namespace): - self.blacklists_mgr = extension.ExtensionManager( - namespace=blacklist_namespace, + def load_banlists(self, banlist_namespace): + self.banlists_mgr = extension.ExtensionManager( + namespace=banlist_namespace, invoke_on_load=False, verify_requirements=False, ) - self.blacklist = {} - blacklist = list(self.blacklists_mgr) - for item in blacklist: + self.banlist = {} + banlist = list(self.banlists_mgr) + for item in banlist: for key, val in item.plugin().items(): utils.check_ast_node(key) - self.blacklist.setdefault(key, []).extend(val) + self.banlist.setdefault(key, []).extend(val) - self.blacklist_by_id = {} - self.blacklist_by_name = {} - for val in six.itervalues(self.blacklist): + self.banlist_by_id = {} + self.banlist_by_name = {} + for val in six.itervalues(self.banlist): for b in val: - self.blacklist_by_id[b['id']] = b - self.blacklist_by_name[b['name']] = b + self.banlist_by_id[b['id']] = b + self.banlist_by_name[b['name']] = b def validate_profile(self, profile): '''Validate that everything in the configured profiles looks good.''' @@ -98,7 +98,7 @@ def validate_profile(self, profile): def check_id(self, test): return ( test in self.plugins_by_id or - test in self.blacklist_by_id or + test in self.banlist_by_id or test in self.builtin) diff --git a/bandit/core/test_set.py b/bandit/core/test_set.py index 2a472a0a8..28b16e185 100644 --- a/bandit/core/test_set.py +++ b/bandit/core/test_set.py @@ -9,7 +9,7 @@ import logging -from bandit.core import blacklisting +from bandit.core import banlisting from bandit.core import extension_loader @@ -34,22 +34,22 @@ def _get_filter(config, profile): inc = set(profile.get('include', [])) exc = set(profile.get('exclude', [])) - all_blacklist_tests = set() - for _, tests in extman.blacklist.items(): - all_blacklist_tests.update(t['id'] for t in tests) + all_banlist_tests = set() + for _, tests in extman.banlist.items(): + all_banlist_tests.update(t['id'] for t in tests) # this block is purely for backwards compatibility, the rules are as # follows: # B001,B401 means B401 # B401 means B401 - # B001 means all blacklist tests + # B001 means all banlist tests if 'B001' in inc: - if not inc.intersection(all_blacklist_tests): - inc.update(all_blacklist_tests) + if not inc.intersection(all_banlist_tests): + inc.update(all_banlist_tests) inc.discard('B001') if 'B001' in exc: - if not exc.intersection(all_blacklist_tests): - exc.update(all_blacklist_tests) + if not exc.intersection(all_banlist_tests): + exc.update(all_banlist_tests) exc.discard('B001') if inc: @@ -57,7 +57,7 @@ def _get_filter(config, profile): else: filtered = set(extman.plugins_by_id.keys()) filtered.update(extman.builtin) - filtered.update(all_blacklist_tests) + filtered.update(all_banlist_tests) return filtered - exc def _load_builtins(self, filtering, profile): @@ -69,25 +69,25 @@ def __init__(self, name, plugin): self.plugin = plugin extman = extension_loader.MANAGER - blacklist = profile.get('blacklist') - if not blacklist: # not overridden by legacy data - blacklist = {} - for node, tests in extman.blacklist.items(): + banlist = profile.get('banlist') + if not banlist: # not overridden by legacy data + banlist = {} + for node, tests in extman.banlist.items(): values = [t for t in tests if t['id'] in filtering] if values: - blacklist[node] = values + banlist[node] = values - if not blacklist: + if not banlist: return [] - # this dresses up the blacklist to look like a plugin, but - # the '_checks' data comes from the blacklist information. - # the '_config' is the filtered blacklist data set. - blacklisting.blacklist._test_id = "B001" - blacklisting.blacklist._checks = blacklist.keys() - blacklisting.blacklist._config = blacklist + # this dresses up the banlist to look like a plugin, but + # the '_checks' data comes from the banlist information. + # the '_config' is the filtered banlist data set. + banlisting.banlist._test_id = "B001" + banlisting.banlist._checks = banlist.keys() + banlisting.banlist._config = banlist - return [Wrapper('blacklist', blacklisting.blacklist)] + return [Wrapper('banlist', banlisting.banlist)] def _load_tests(self, config, plugins): '''Builds a dict mapping tests to node types.''' diff --git a/bandit/formatters/csv.py b/bandit/formatters/csv.py index 1fc5878e8..f7b459adb 100644 --- a/bandit/formatters/csv.py +++ b/bandit/formatters/csv.py @@ -15,7 +15,7 @@ filename,test_name,test_id,issue_severity,issue_confidence,issue_text, line_number,line_range,more_info - examples/yaml_load.py,blacklist_calls,B301,MEDIUM,HIGH,"Use of unsafe yaml + examples/yaml_load.py,banlist_calls,B301,MEDIUM,HIGH,"Use of unsafe yaml load. Allows instantiation of arbitrary objects. Consider yaml.safe_load(). ",5,[5],https://bandit.readthedocs.io/en/latest/ diff --git a/bandit/formatters/custom.py b/bandit/formatters/custom.py index eb39a9cc7..f27fab56a 100644 --- a/bandit/formatters/custom.py +++ b/bandit/formatters/custom.py @@ -74,6 +74,7 @@ def report(manager, fileobj, sev_level, conf_level, template=None): 'abspath': lambda issue: os.path.abspath(issue.fname), 'relpath': lambda issue: os.path.relpath(issue.fname), 'line': lambda issue: issue.lineno, + 'col_offset': lambda issue: issue.col_offset, 'test_id': lambda issue: issue.test_id, 'severity': lambda issue: issue.severity, 'msg': lambda issue: issue.text, @@ -107,7 +108,7 @@ def get_similar_tag(tag): for t, t_set in tag_sim_dict.items()] return sorted(similarity_list)[-1][1] - tag_blacklist = [] + tag_banlist = [] for tag in tag_set: # check if the tag is in dictionary if tag not in tag_mapper: @@ -116,7 +117,7 @@ def get_similar_tag(tag): "Tag '%s' was not recognized and will be skipped, " "did you mean to use '%s'?", tag, similar_tag ) - tag_blacklist += [tag] + tag_banlist += [tag] # Compose the message template back with the valid values only msg_parsed_template_list = [] @@ -128,7 +129,7 @@ def get_similar_tag(tag): msg_parsed_template_list.append(literal_text) if field_name is not None: - if field_name in tag_blacklist: + if field_name in tag_banlist: msg_parsed_template_list.append(field_name) continue # Append the fmt_spec part diff --git a/bandit/formatters/json.py b/bandit/formatters/json.py index 4c5e18720..d503372a4 100644 --- a/bandit/formatters/json.py +++ b/bandit/formatters/json.py @@ -56,7 +56,7 @@ 5 ], "more_info": "https://bandit.readthedocs.io/en/latest/", - "test_name": "blacklist_calls", + "test_name": "banlist_calls", "test_id": "B301" } ] diff --git a/bandit/formatters/text.py b/bandit/formatters/text.py index 10f044f61..031c224d8 100644 --- a/bandit/formatters/text.py +++ b/bandit/formatters/text.py @@ -14,7 +14,7 @@ .. code-block:: none - >> Issue: [B301:blacklist_calls] Use of unsafe yaml load. Allows + >> Issue: [B301:banlist_calls] Use of unsafe yaml load. Allows instantiation of arbitrary objects. Consider yaml.safe_load(). Severity: Medium Confidence: High diff --git a/bandit/formatters/xml.py b/bandit/formatters/xml.py index a21e80024..2fce474cb 100644 --- a/bandit/formatters/xml.py +++ b/bandit/formatters/xml.py @@ -15,7 +15,7 @@ Test ID: B301 diff --git a/bandit/plugins/hashlib_new_insecure_functions.py b/bandit/plugins/hashlib_new_insecure_functions.py index f40fc6a41..20ea015df 100644 --- a/bandit/plugins/hashlib_new_insecure_functions.py +++ b/bandit/plugins/hashlib_new_insecure_functions.py @@ -13,7 +13,7 @@ can be used to create insecure hash functions like MD4 and MD5 if they are passed as algorithm names to this function. -This is similar to B303 blacklist check, except that this checks for insecure +This is similar to B303 banlist check, except that this checks for insecure hash functions created using ``hashlib.new`` function. :Example: diff --git a/doc/source/banlists/banlist_calls.rst b/doc/source/banlists/banlist_calls.rst new file mode 100644 index 000000000..f5c7341ba --- /dev/null +++ b/doc/source/banlists/banlist_calls.rst @@ -0,0 +1,5 @@ +--------------- +banlist_calls +--------------- + +.. automodule:: bandit.banlists.calls diff --git a/doc/source/banlists/banlist_imports.rst b/doc/source/banlists/banlist_imports.rst new file mode 100644 index 000000000..4b0121239 --- /dev/null +++ b/doc/source/banlists/banlist_imports.rst @@ -0,0 +1,5 @@ +----------------- +banlist_imports +----------------- + +.. automodule:: bandit.banlists.imports diff --git a/doc/source/blacklists/index.rst b/doc/source/banlists/index.rst similarity index 70% rename from doc/source/blacklists/index.rst rename to doc/source/banlists/index.rst index cc5e5b805..dd391423b 100644 --- a/doc/source/blacklists/index.rst +++ b/doc/source/banlists/index.rst @@ -1,24 +1,24 @@ -Bandit Blacklist Plugins -======================== +Bandit Banlist Plugins +====================== -Bandit supports built in functionality to implement blacklisting of imports and +Bandit supports built in functionality to implement banlisting of imports and function calls, this functionality is provided by built in test 'B001'. This test may be filtered as per normal plugin filtering rules. -The exact calls and imports that are blacklisted, and the issues reported, are -controlled by plugin methods with the entry point 'bandit.blacklists' and can -be extended by third party plugins if desired. Blacklist plugins will be +The exact calls and imports that are banlisted, and the issues reported, are +controlled by plugin methods with the entry point 'bandit.banlists' and can +be extended by third party plugins if desired. Banlist plugins will be discovered by Bandit at startup and called. The returned results are combined into the final data set, subject to Bandit's normal test include/exclude rules -allowing for fine grained control over blacklisted items. By convention, -blacklisted calls should have IDs in the B3xx range and imports should have IDs +allowing for fine grained control over banlisted items. By convention, +banlisted calls should have IDs in the B3xx range and imports should have IDs in the B4xx range. Plugin functions should return a dictionary mapping AST node types to -lists of blacklist data. Currently the following node types are supported: +lists of banlist data. Currently the following node types are supported: -- Call, used for blacklisting calls. -- Import, used for blacklisting module imports (this also implicitly tests +- Call, used for banlisting calls. +- Import, used for banlisting module imports (this also implicitly tests ImportFrom and Call nodes where the invoked function is Pythons built in '__import__()' method). @@ -30,7 +30,7 @@ Items in the data lists are Python dictionaries with the following structure: | 'name' | The issue name string. | +-------------+----------------------------------------------------+ | 'id' | The bandit ID of the check, this must be unique | -| | and is used for filtering blacklist checks. | +| | and is used for filtering banlist checks. | +-------------+----------------------------------------------------+ | 'qualnames' | A Python list of fully qualified name strings. | +-------------+----------------------------------------------------+ @@ -42,13 +42,13 @@ Items in the data lists are Python dictionaries with the following structure: | 'level' | The severity level reported. | +-------------+----------------------------------------------------+ -A utility method bandit.blacklists.utils.build_conf_dict is provided to aid +A utility method bandit.banlists.utils.build_conf_dict is provided to aid building these dictionaries. :Example: .. code-block:: none - >> Issue: [B317:blacklist] Using xml.sax.parse to parse untrusted XML data + >> Issue: [B317:banlist] Using xml.sax.parse to parse untrusted XML data is known to be vulnerable to XML attacks. Replace xml.sax.parse with its defusedxml equivalent function. Severity: Medium Confidence: High diff --git a/doc/source/blacklists/blacklist_calls.rst b/doc/source/blacklists/blacklist_calls.rst deleted file mode 100644 index 0897b6d31..000000000 --- a/doc/source/blacklists/blacklist_calls.rst +++ /dev/null @@ -1,5 +0,0 @@ ---------------- -blacklist_calls ---------------- - -.. automodule:: bandit.blacklists.calls diff --git a/doc/source/blacklists/blacklist_imports.rst b/doc/source/blacklists/blacklist_imports.rst deleted file mode 100644 index 3242cf885..000000000 --- a/doc/source/blacklists/blacklist_imports.rst +++ /dev/null @@ -1,5 +0,0 @@ ------------------ -blacklist_imports ------------------ - -.. automodule:: bandit.blacklists.imports diff --git a/doc/source/config.rst b/doc/source/config.rst index c092e8ae1..4f9331a46 100644 --- a/doc/source/config.rst +++ b/doc/source/config.rst @@ -73,7 +73,7 @@ Generating a Config Bandit ships the tool `bandit-config-generator` designed to take the leg work out of configuration. This tool can generate a configuration file automatically. The generated configuration will include default config blocks -for all detected test and blacklist plugins. This data can then be deleted or +for all detected test and banlist plugins. This data can then be deleted or edited as needed to produce a minimal config as desired. The config generator supports `-t` and `-s` command line options to specify a list of test IDs that should be included or excluded respectively. If no options are given then the diff --git a/doc/source/index.rst b/doc/source/index.rst index 8b71f88a3..0c6fdbebd 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -16,7 +16,7 @@ Getting Started config plugins/index - blacklists/index + banlists/index formatters/index Indices and tables diff --git a/doc/source/plugins/index.rst b/doc/source/plugins/index.rst index 10ddd60e9..65cb13197 100644 --- a/doc/source/plugins/index.rst +++ b/doc/source/plugins/index.rst @@ -102,8 +102,8 @@ ID Description ======= =========== B1xx misc tests B2xx application/framework misconfiguration -B3xx blacklists (calls) -B4xx blacklists (imports) +B3xx banlists (calls) +B4xx banlists (imports) B5xx cryptography B6xx injection B7xx XSS diff --git a/setup.cfg b/setup.cfg index 8f8cfa0c7..152f713f0 100644 --- a/setup.cfg +++ b/setup.cfg @@ -30,9 +30,9 @@ console_scripts = bandit = bandit.cli.main:main bandit-config-generator = bandit.cli.config_generator:main bandit-baseline = bandit.cli.baseline:main -bandit.blacklists = - calls = bandit.blacklists.calls:gen_blacklist - imports = bandit.blacklists.imports:gen_blacklist +bandit.banlists = + calls = bandit.banlists.calls:gen_banlist + imports = bandit.banlists.imports:gen_banlist bandit.formatters = csv = bandit.formatters.csv:report json = bandit.formatters.json:report diff --git a/tests/functional/test_baseline.py b/tests/functional/test_baseline.py index fd8d831c3..94926bb91 100644 --- a/tests/functional/test_baseline.py +++ b/tests/functional/test_baseline.py @@ -15,7 +15,7 @@ new_candidates_skip_nosec_lines = "Total lines skipped (#nosec): 3" baseline_no_skipped_files = "Files skipped (0):" baseline_no_issues_found = "No issues identified." -xml_sax_issue_id = "Issue: [B317:blacklist]" +xml_sax_issue_id = "Issue: [B317:banlist]" yaml_load_issue_id = "Issue: [B506:yaml_load]" shell_issue_id = "Issue: [B602:subprocess_popen_with_shell_equals_true]" candidate_example_one = "subprocess.Popen('/bin/ls *', shell=True)" diff --git a/tests/functional/test_functional.py b/tests/functional/test_functional.py index e3b73702d..54340de99 100644 --- a/tests/functional/test_functional.py +++ b/tests/functional/test_functional.py @@ -754,7 +754,7 @@ def test_baseline_filter(self): self.assertEqual(1, len(self.b_mgr.baseline)) self.assertEqual({}, self.b_mgr.get_issue_list()) - def test_blacklist_input(self): + def test_banlist_input(self): expect = { 'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 1}, 'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 1} @@ -777,7 +777,7 @@ def test_hashlib_new_insecure_functions(self): } self.check_example('hashlib_new_insecure_functions.py', expect) - def test_blacklist_pycrypto(self): + def test_banlist_pycrypto(self): '''Test importing pycrypto module''' expect = { 'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 2}, @@ -785,10 +785,10 @@ def test_blacklist_pycrypto(self): } self.check_example('pycrypto.py', expect) - def test_no_blacklist_pycryptodome(self): + def test_no_banlist_pycryptodome(self): '''Test importing pycryptodome module - make sure it's no longer blacklisted + make sure it's no longer banlisted ''' expect = { 'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 0}, diff --git a/tests/functional/test_runtime.py b/tests/functional/test_runtime.py index b77a606b9..5d1f7a83c 100644 --- a/tests/functional/test_runtime.py +++ b/tests/functional/test_runtime.py @@ -41,7 +41,7 @@ def test_piped_input(self): self.assertIn("Low: 2", output) self.assertIn("High: 2", output) self.assertIn("Files skipped (0):", output) - self.assertIn("Issue: [B403:blacklist] Consider possible", output) + self.assertIn("Issue: [B403:banlist] Consider possible", output) self.assertIn(":2", output) self.assertIn(":4", output) @@ -117,7 +117,7 @@ def test_example_imports(self): self.assertIn("Low: 2", output) self.assertIn("High: 2", output) self.assertIn("Files skipped (0):", output) - self.assertIn("Issue: [B403:blacklist] Consider possible", + self.assertIn("Issue: [B403:banlist] Consider possible", output) self.assertIn("imports.py:2", output) self.assertIn("imports.py:4", output) diff --git a/tests/unit/core/test_blacklisting.py b/tests/unit/core/test_blacklisting.py index 2889fd3ed..d07d2b0bc 100644 --- a/tests/unit/core/test_blacklisting.py +++ b/tests/unit/core/test_blacklisting.py @@ -4,16 +4,16 @@ # # SPDX-License-Identifier: Apache-2.0 -from bandit.core import blacklisting +from bandit.core import banlisting import testtools -class BlacklistingTests(testtools.TestCase): +class BanlistingTests(testtools.TestCase): def test_report_issue(self): data = {'level': 'HIGH', 'message': 'test {name}', 'id': 'B000'} - issue = blacklisting.report_issue(data, 'name') + issue = banlisting.report_issue(data, 'name') issue_dict = issue.as_dict(with_code=False) self.assertIsInstance(issue_dict, dict) self.assertEqual('B000', issue_dict['test_id']) @@ -24,7 +24,7 @@ def test_report_issue(self): def test_report_issue_defaults(self): data = {'message': 'test {name}'} - issue = blacklisting.report_issue(data, 'name') + issue = banlisting.report_issue(data, 'name') issue_dict = issue.as_dict(with_code=False) self.assertIsInstance(issue_dict, dict) self.assertEqual('LEGACY', issue_dict['test_id']) diff --git a/tests/unit/core/test_config.py b/tests/unit/core/test_config.py index 9e028ad47..ffca7c29e 100644 --- a/tests/unit/core/test_config.py +++ b/tests/unit/core/test_config.py @@ -122,11 +122,11 @@ class TestConfigCompat(testtools.TestCase): test_2: include: - - blacklist_calls + - banlist_calls test_3: include: - - blacklist_imports + - banlist_imports test_4: exclude: @@ -134,23 +134,23 @@ class TestConfigCompat(testtools.TestCase): test_5: exclude: - - blacklist_calls - - blacklist_imports + - banlist_calls + - banlist_imports test_6: include: - - blacklist_calls + - banlist_calls exclude: - - blacklist_imports + - banlist_imports - blacklist_calls: + banlist_calls: bad_name_sets: - pickle: qualnames: [pickle.loads] message: "{func} library appears to be in use." - blacklist_imports: + banlist_imports: bad_import_sets: - telnet: imports: [telnetlib] @@ -166,7 +166,7 @@ def setUp(self): def test_converted_include(self): profiles = self.config.get_option('profiles') test = profiles['test_1'] - data = {'blacklist': {}, + data = {'banlist': {}, 'exclude': set(), 'include': set(['B101', 'B604'])} @@ -178,7 +178,7 @@ def test_converted_exclude(self): self.assertEqual(set(['B101']), test['exclude']) - def test_converted_blacklist_call_data(self): + def test_converted_banlist_call_data(self): profiles = self.config.get_option('profiles') test = profiles['test_2'] data = {'Call': [{'qualnames': ['telnetlib'], @@ -186,32 +186,32 @@ def test_converted_blacklist_call_data(self): 'message': '{name} is considered insecure.', 'name': 'telnet'}]} - self.assertEqual(data, test['blacklist']) + self.assertEqual(data, test['banlist']) - def test_converted_blacklist_import_data(self): + def test_converted_banlist_import_data(self): profiles = self.config.get_option('profiles') test = profiles['test_3'] data = [{'message': '{name} library appears to be in use.', 'name': 'pickle', 'qualnames': ['pickle.loads']}] - self.assertEqual(data, test['blacklist']['Call']) - self.assertEqual(data, test['blacklist']['Import']) - self.assertEqual(data, test['blacklist']['ImportFrom']) + self.assertEqual(data, test['banlist']['Call']) + self.assertEqual(data, test['banlist']['Import']) + self.assertEqual(data, test['banlist']['ImportFrom']) - def test_converted_blacklist_call_test(self): + def test_converted_banlist_call_test(self): profiles = self.config.get_option('profiles') test = profiles['test_2'] self.assertEqual(set(['B001']), test['include']) - def test_converted_blacklist_import_test(self): + def test_converted_banlist_import_test(self): profiles = self.config.get_option('profiles') test = profiles['test_3'] self.assertEqual(set(['B001']), test['include']) - def test_converted_exclude_blacklist(self): + def test_converted_exclude_banlist(self): profiles = self.config.get_option('profiles') test = profiles['test_5'] @@ -228,16 +228,16 @@ def test_deprecation_message(self): self.config.validate('') self.assertEqual((msg, ''), m.call_args_list[0][0]) - def test_blacklist_error(self): + def test_banlist_error(self): msg = (" : Config file has an include or exclude reference to legacy " "test '%s' but no configuration data for it. Configuration " "data is required for this test. Please consider switching to " "the new config file format, the tool " "'bandit-config-generator' can help you with this.") - for name in ["blacklist_call", - "blacklist_imports", - "blacklist_imports_func"]: + for name in ["banlist_call", + "banlist_imports", + "banlist_imports_func"]: self.config._config = ( {"profiles": {"test": {"include": [name]}}}) diff --git a/tests/unit/core/test_docs_util.py b/tests/unit/core/test_docs_util.py index a71fb8834..0323b845d 100644 --- a/tests/unit/core/test_docs_util.py +++ b/tests/unit/core/test_docs_util.py @@ -12,7 +12,7 @@ class DocsUtilTests(testtools.TestCase): '''This set of tests exercises bandit.core.docs_util functions.''' def test_overwrite_bib_info(self): - expected_url = BASE_URL + ("blacklists/blacklist_calls.html" + expected_url = BASE_URL + ("banlists/banlist_calls.html" "#b304-b305-ciphers-and-modes") self.assertEqual(get_url('B304'), get_url('B305')) self.assertEqual(expected_url, get_url('B304')) @@ -22,6 +22,6 @@ def test_plugin_call_bib(self): self.assertEqual(expected_url, get_url('B101')) def test_import_call_bib(self): - expected_url = BASE_URL + ("blacklists/blacklist_imports.html" + expected_url = BASE_URL + ("banlists/banlist_imports.html" "#b413-import-pycrypto") self.assertEqual(expected_url, get_url('B413')) diff --git a/tests/unit/core/test_test_set.py b/tests/unit/core/test_test_set.py index 280d112da..913eac5ee 100644 --- a/tests/unit/core/test_test_set.py +++ b/tests/unit/core/test_test_set.py @@ -8,7 +8,7 @@ from stevedore import extension import testtools -from bandit.blacklists import utils +from bandit.banlists import utils from bandit.core import extension_loader from bandit.core import test_properties as test from bandit.core import test_set @@ -78,73 +78,73 @@ def test_profile_exclude_none(self): ts = test_set.BanditTestSet(self.config, profile) self.assertEqual(1, len(ts.get_tests('Str'))) - def test_profile_has_builtin_blacklist(self): + def test_profile_has_builtin_banlist(self): ts = test_set.BanditTestSet(self.config) self.assertEqual(1, len(ts.get_tests('Import'))) self.assertEqual(1, len(ts.get_tests('ImportFrom'))) self.assertEqual(1, len(ts.get_tests('Call'))) - def test_profile_exclude_builtin_blacklist(self): + def test_profile_exclude_builtin_banlist(self): profile = {'exclude': ['B001']} ts = test_set.BanditTestSet(self.config, profile) self.assertEqual(0, len(ts.get_tests('Import'))) self.assertEqual(0, len(ts.get_tests('ImportFrom'))) self.assertEqual(0, len(ts.get_tests('Call'))) - def test_profile_exclude_builtin_blacklist_specific(self): + def test_profile_exclude_builtin_banlist_specific(self): profile = {'exclude': ['B302', 'B401']} ts = test_set.BanditTestSet(self.config, profile) self.assertEqual(0, len(ts.get_tests('Import'))) self.assertEqual(0, len(ts.get_tests('ImportFrom'))) self.assertEqual(0, len(ts.get_tests('Call'))) - def test_profile_filter_blacklist_none(self): + def test_profile_filter_banlist_none(self): ts = test_set.BanditTestSet(self.config) - blacklist = ts.get_tests('Import')[0] + banlist = ts.get_tests('Import')[0] - self.assertEqual(2, len(blacklist._config['Import'])) - self.assertEqual(2, len(blacklist._config['ImportFrom'])) - self.assertEqual(2, len(blacklist._config['Call'])) + self.assertEqual(2, len(banlist._config['Import'])) + self.assertEqual(2, len(banlist._config['ImportFrom'])) + self.assertEqual(2, len(banlist._config['Call'])) - def test_profile_filter_blacklist_one(self): + def test_profile_filter_banlist_one(self): profile = {'exclude': ['B401']} ts = test_set.BanditTestSet(self.config, profile) - blacklist = ts.get_tests('Import')[0] + banlist = ts.get_tests('Import')[0] - self.assertEqual(1, len(blacklist._config['Import'])) - self.assertEqual(1, len(blacklist._config['ImportFrom'])) - self.assertEqual(1, len(blacklist._config['Call'])) + self.assertEqual(1, len(banlist._config['Import'])) + self.assertEqual(1, len(banlist._config['ImportFrom'])) + self.assertEqual(1, len(banlist._config['Call'])) - def test_profile_filter_blacklist_include(self): + def test_profile_filter_banlist_include(self): profile = {'include': ['B001', 'B401']} ts = test_set.BanditTestSet(self.config, profile) - blacklist = ts.get_tests('Import')[0] + banlist = ts.get_tests('Import')[0] - self.assertEqual(1, len(blacklist._config['Import'])) - self.assertEqual(1, len(blacklist._config['ImportFrom'])) - self.assertEqual(1, len(blacklist._config['Call'])) + self.assertEqual(1, len(banlist._config['Import'])) + self.assertEqual(1, len(banlist._config['ImportFrom'])) + self.assertEqual(1, len(banlist._config['Call'])) - def test_profile_filter_blacklist_all(self): + def test_profile_filter_banlist_all(self): profile = {'exclude': ['B401', 'B302']} ts = test_set.BanditTestSet(self.config, profile) - # if there is no blacklist data for a node type then we wont add a - # blacklist test to it, as this would be pointless. + # if there is no banlist data for a node type then we wont add a + # banlist test to it, as this would be pointless. self.assertEqual(0, len(ts.get_tests('Import'))) self.assertEqual(0, len(ts.get_tests('ImportFrom'))) self.assertEqual(0, len(ts.get_tests('Call'))) - def test_profile_blacklist_compat(self): + def test_profile_banlist_compat(self): data = [utils.build_conf_dict( 'marshal', 'B302', ['marshal.load', 'marshal.loads'], ('Deserialization with the marshal module is possibly ' 'dangerous.'))] - profile = {'include': ['B001'], 'blacklist': {'Call': data}} + profile = {'include': ['B001'], 'banlist': {'Call': data}} ts = test_set.BanditTestSet(self.config, profile) - blacklist = ts.get_tests('Call')[0] + banlist = ts.get_tests('Call')[0] - self.assertNotIn('Import', blacklist._config) - self.assertNotIn('ImportFrom', blacklist._config) - self.assertEqual(1, len(blacklist._config['Call'])) + self.assertNotIn('Import', banlist._config) + self.assertNotIn('ImportFrom', banlist._config) + self.assertEqual(1, len(banlist._config['Call'])) From b6e647a198dff33fbdb30720c1eea5ac9486185a Mon Sep 17 00:00:00 2001 From: Anthony Shaw Date: Tue, 2 Jun 2020 11:31:58 +1000 Subject: [PATCH 02/17] Add a legacy backport (WIP) --- bandit/core/config.py | 32 +++++++++++++++++++------------- setup.cfg | 3 +++ 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/bandit/core/config.py b/bandit/core/config.py index 003035f56..b7ac8a32d 100644 --- a/bandit/core/config.py +++ b/bandit/core/config.py @@ -111,12 +111,18 @@ def _init_plugin_name_pattern(self): def convert_legacy_config(self): updated_profiles = self.convert_names_to_ids() - bad_calls, bad_imports = self.convert_legacy_banlist_data() + bad_calls, bad_imports = self.convert_legacy_blacklist_data() if updated_profiles: - self.convert_legacy_banlist_tests(updated_profiles, + self.convert_legacy_blacklist_tests(updated_profiles, bad_calls, bad_imports) self._config['profiles'] = updated_profiles + self.convert_blacklist_to_banlist() + + def convert_blacklist_to_banlist(self): + '''Blacklist was renamed to banlist, migrate any legacy config''' + # TODO : Copy any 'blacklist' config properties to banlist + pass def convert_names_to_ids(self): '''Convert test names to IDs, unknown names are left unchanged.''' @@ -134,12 +140,12 @@ def convert_names_to_ids(self): updated_profiles[name] = {'include': include, 'exclude': exclude} return updated_profiles - def convert_legacy_banlist_data(self): - '''Detect legacy banlist data and convert it to new format.''' + def convert_legacy_blacklist_data(self): + '''Detect legacy blacklist data and convert it to new format.''' bad_calls_list = [] bad_imports_list = [] - bad_calls = self.get_option('banlist_calls') or {} + bad_calls = self.get_option('blacklist_calls') or {} bad_calls = bad_calls.get('bad_name_sets', {}) for item in bad_calls: for key, val in item.items(): @@ -147,7 +153,7 @@ def convert_legacy_banlist_data(self): val['message'] = val['message'].replace('{func}', '{name}') bad_calls_list.append(val) - bad_imports = self.get_option('banlist_imports') or {} + bad_imports = self.get_option('blacklist_imports') or {} bad_imports = bad_imports.get('bad_import_sets', {}) for item in bad_imports: for key, val in item.items(): @@ -158,13 +164,13 @@ def convert_legacy_banlist_data(self): bad_imports_list.append(val) if bad_imports_list or bad_calls_list: - LOG.warning('Legacy banlist data found in config, overriding ' + LOG.warning('Legacy blacklist data found in config, overriding ' 'data plugins') return bad_calls_list, bad_imports_list @staticmethod - def convert_legacy_banlist_tests(profiles, bad_imports, bad_calls): - '''Detect old banlist tests, convert to use new builtin.''' + def convert_legacy_blacklist_tests(profiles, bad_imports, bad_calls): + '''Detect old blacklist tests, convert to use new builtin.''' def _clean_set(name, data): if name in data: data.remove(name) @@ -175,14 +181,14 @@ def _clean_set(name, data): include = profile['include'] exclude = profile['exclude'] - name = 'banlist_calls' + name = 'blacklist_calls' if name in include and name not in exclude: banlist.setdefault('Call', []).extend(bad_calls) _clean_set(name, include) _clean_set(name, exclude) - name = 'banlist_imports' + name = 'blacklist_imports' if name in include and name not in exclude: banlist.setdefault('Import', []).extend(bad_imports) banlist.setdefault('ImportFrom', []).extend(bad_imports) @@ -190,8 +196,8 @@ def _clean_set(name, data): _clean_set(name, include) _clean_set(name, exclude) - _clean_set('banlist_import_func', include) - _clean_set('banlist_import_func', exclude) + _clean_set('blacklist_import_func', include) + _clean_set('blacklist_import_func', exclude) # This can happen with a legacy config that includes # banlist_calls but exclude banlist_imports for example diff --git a/setup.cfg b/setup.cfg index 152f713f0..3b81c0313 100644 --- a/setup.cfg +++ b/setup.cfg @@ -33,6 +33,9 @@ console_scripts = bandit.banlists = calls = bandit.banlists.calls:gen_banlist imports = bandit.banlists.imports:gen_banlist +bandit.blacklists = + calls = bandit.banlists.calls:gen_banlist + imports = bandit.banlists.imports:gen_banlist bandit.formatters = csv = bandit.formatters.csv:report json = bandit.formatters.json:report From ffc16ea4f856658a9606935fd1240b7c8153233f Mon Sep 17 00:00:00 2001 From: Anthony Shaw Date: Thu, 9 Jul 2020 12:14:47 +1000 Subject: [PATCH 03/17] Refactor the tests and fully check the legacy configs --- bandit/core/config.py | 12 +++------- bandit/formatters/custom.py | 1 - ...est_blacklisting.py => test_banlisting.py} | 0 tests/unit/core/test_config.py | 24 +++++++++---------- 4 files changed, 15 insertions(+), 22 deletions(-) rename tests/unit/core/{test_blacklisting.py => test_banlisting.py} (100%) diff --git a/bandit/core/config.py b/bandit/core/config.py index b7ac8a32d..dfdf36ec3 100644 --- a/bandit/core/config.py +++ b/bandit/core/config.py @@ -117,12 +117,6 @@ def convert_legacy_config(self): self.convert_legacy_blacklist_tests(updated_profiles, bad_calls, bad_imports) self._config['profiles'] = updated_profiles - self.convert_blacklist_to_banlist() - - def convert_blacklist_to_banlist(self): - '''Blacklist was renamed to banlist, migrate any legacy config''' - # TODO : Copy any 'blacklist' config properties to banlist - pass def convert_names_to_ids(self): '''Convert test names to IDs, unknown names are left unchanged.''' @@ -227,9 +221,9 @@ def _test(key, block, exclude, include): inc = profile.get('include') or set() exc = profile.get('exclude') or set() - _test('banlist_imports', 'banlist_imports', inc, exc) - _test('banlist_import_func', 'banlist_imports', inc, exc) - _test('banlist_calls', 'banlist_calls', inc, exc) + _test('blacklist_imports', 'blacklist_imports', inc, exc) + _test('blacklist_import_func', 'blacklist_imports', inc, exc) + _test('blacklist_calls', 'blacklist_calls', inc, exc) # show deprecation message if legacy: diff --git a/bandit/formatters/custom.py b/bandit/formatters/custom.py index f27fab56a..e875b5ba7 100644 --- a/bandit/formatters/custom.py +++ b/bandit/formatters/custom.py @@ -74,7 +74,6 @@ def report(manager, fileobj, sev_level, conf_level, template=None): 'abspath': lambda issue: os.path.abspath(issue.fname), 'relpath': lambda issue: os.path.relpath(issue.fname), 'line': lambda issue: issue.lineno, - 'col_offset': lambda issue: issue.col_offset, 'test_id': lambda issue: issue.test_id, 'severity': lambda issue: issue.severity, 'msg': lambda issue: issue.text, diff --git a/tests/unit/core/test_blacklisting.py b/tests/unit/core/test_banlisting.py similarity index 100% rename from tests/unit/core/test_blacklisting.py rename to tests/unit/core/test_banlisting.py diff --git a/tests/unit/core/test_config.py b/tests/unit/core/test_config.py index ffca7c29e..3ce1afb0b 100644 --- a/tests/unit/core/test_config.py +++ b/tests/unit/core/test_config.py @@ -122,11 +122,11 @@ class TestConfigCompat(testtools.TestCase): test_2: include: - - banlist_calls + - blacklist_calls test_3: include: - - banlist_imports + - blacklist_imports test_4: exclude: @@ -134,23 +134,23 @@ class TestConfigCompat(testtools.TestCase): test_5: exclude: - - banlist_calls - - banlist_imports + - blacklist_calls + - blacklist_imports test_6: include: - - banlist_calls + - blacklist_calls exclude: - - banlist_imports + - blacklist_imports - banlist_calls: + blacklist_calls: bad_name_sets: - pickle: qualnames: [pickle.loads] message: "{func} library appears to be in use." - banlist_imports: + blacklist_imports: bad_import_sets: - telnet: imports: [telnetlib] @@ -228,16 +228,16 @@ def test_deprecation_message(self): self.config.validate('') self.assertEqual((msg, ''), m.call_args_list[0][0]) - def test_banlist_error(self): + def test_blacklist_error(self): msg = (" : Config file has an include or exclude reference to legacy " "test '%s' but no configuration data for it. Configuration " "data is required for this test. Please consider switching to " "the new config file format, the tool " "'bandit-config-generator' can help you with this.") - for name in ["banlist_call", - "banlist_imports", - "banlist_imports_func"]: + for name in ["blacklist_call", + "blacklist_imports", + "blacklist_imports_func"]: self.config._config = ( {"profiles": {"test": {"include": [name]}}}) From 7cd5ea2069672345ebaa7eac887aa6a2c38c1878 Mon Sep 17 00:00:00 2001 From: Anthony Shaw Date: Thu, 9 Jul 2020 12:16:50 +1000 Subject: [PATCH 04/17] Fix spacing issue --- bandit/core/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bandit/core/config.py b/bandit/core/config.py index dfdf36ec3..93d5e4354 100644 --- a/bandit/core/config.py +++ b/bandit/core/config.py @@ -115,7 +115,7 @@ def convert_legacy_config(self): if updated_profiles: self.convert_legacy_blacklist_tests(updated_profiles, - bad_calls, bad_imports) + bad_calls, bad_imports) self._config['profiles'] = updated_profiles def convert_names_to_ids(self): From 774fd0addbe4e6e23932fe17d616b6edca5a4f4f Mon Sep 17 00:00:00 2001 From: Anthony Shaw Date: Wed, 22 Jul 2020 13:02:34 +1000 Subject: [PATCH 05/17] Update bandit/banlists/calls.py Co-authored-by: Eric Brown --- bandit/banlists/calls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bandit/banlists/calls.py b/bandit/banlists/calls.py index b274309de..b94b1da11 100644 --- a/bandit/banlists/calls.py +++ b/bandit/banlists/calls.py @@ -5,7 +5,7 @@ # SPDX-License-Identifier: Apache-2.0 r""" -==================================================== +================================================== Banlist various Python calls known to be dangerous ==================================================== From 717ba6a5de79b32cc79cf94f6abbe317df9a5898 Mon Sep 17 00:00:00 2001 From: Anthony Shaw Date: Wed, 22 Jul 2020 13:02:41 +1000 Subject: [PATCH 06/17] Update bandit/banlists/calls.py Co-authored-by: Eric Brown --- bandit/banlists/calls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bandit/banlists/calls.py b/bandit/banlists/calls.py index b94b1da11..e951f3dd1 100644 --- a/bandit/banlists/calls.py +++ b/bandit/banlists/calls.py @@ -7,7 +7,7 @@ r""" ================================================== Banlist various Python calls known to be dangerous -==================================================== +================================================== This banlist data checks for a number of Python calls known to have possible security implications. The following banlist tests are run against any From 8ed3115e17d34a6bc041a6b08b7ac47bc49ab17d Mon Sep 17 00:00:00 2001 From: Anthony Shaw Date: Wed, 22 Jul 2020 13:02:49 +1000 Subject: [PATCH 07/17] Update bandit/banlists/imports.py Co-authored-by: Eric Brown --- bandit/banlists/imports.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bandit/banlists/imports.py b/bandit/banlists/imports.py index 1ebb1eac8..f7e6d8158 100644 --- a/bandit/banlists/imports.py +++ b/bandit/banlists/imports.py @@ -5,7 +5,7 @@ # SPDX-License-Identifier: Apache-2.0 r""" -====================================================== +==================================================== Banlist various Python imports known to be dangerous ====================================================== From 01082014dfbbf57f526d29530243fdea2a48b5ea Mon Sep 17 00:00:00 2001 From: Anthony Shaw Date: Wed, 22 Jul 2020 13:02:59 +1000 Subject: [PATCH 08/17] Update bandit/banlists/imports.py Co-authored-by: Eric Brown --- bandit/banlists/imports.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bandit/banlists/imports.py b/bandit/banlists/imports.py index f7e6d8158..5f41a18ba 100644 --- a/bandit/banlists/imports.py +++ b/bandit/banlists/imports.py @@ -7,7 +7,7 @@ r""" ==================================================== Banlist various Python imports known to be dangerous -====================================================== +==================================================== This banlist data checks for a number of Python modules known to have possible security implications. The following banlist tests are run against From 6c1768d0c7537092e821d046b32ed7547ff4068a Mon Sep 17 00:00:00 2001 From: Anthony Shaw Date: Wed, 22 Jul 2020 13:10:53 +1000 Subject: [PATCH 09/17] Add backward compatibility for loading legacy blacklist namespace as well --- bandit/core/extension_loader.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/bandit/core/extension_loader.py b/bandit/core/extension_loader.py index 4c0f1f41f..c21a48b14 100644 --- a/bandit/core/extension_loader.py +++ b/bandit/core/extension_loader.py @@ -20,11 +20,14 @@ class Manager(object): def __init__(self, formatters_namespace='bandit.formatters', plugins_namespace='bandit.plugins', - banlists_namespace='bandit.banlists'): + banlists_namespace='bandit.banlists', + load_legacy_blacklists=True): # Cache the extension managers, loaded extensions, and extension names self.load_formatters(formatters_namespace) self.load_plugins(plugins_namespace) self.load_banlists(banlists_namespace) + if load_legacy_blacklists: + self.load_banlists('bandit.blacklists') def load_formatters(self, formatters_namespace): self.formatters_mgr = extension.ExtensionManager( From ea1d9000aff4a1f632de8c25b8a9e174edbe07e5 Mon Sep 17 00:00:00 2001 From: Anthony Shaw Date: Wed, 22 Jul 2020 13:22:44 +1000 Subject: [PATCH 10/17] Added deprecation warning and merge logic for old and new namespaces --- bandit/core/extension_loader.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/bandit/core/extension_loader.py b/bandit/core/extension_loader.py index c21a48b14..181476089 100644 --- a/bandit/core/extension_loader.py +++ b/bandit/core/extension_loader.py @@ -5,6 +5,7 @@ from __future__ import print_function import sys +import warnings import six from stevedore import extension @@ -25,9 +26,7 @@ def __init__(self, formatters_namespace='bandit.formatters', # Cache the extension managers, loaded extensions, and extension names self.load_formatters(formatters_namespace) self.load_plugins(plugins_namespace) - self.load_banlists(banlists_namespace) - if load_legacy_blacklists: - self.load_banlists('bandit.blacklists') + self.load_banlists(banlists_namespace, load_legacy_blacklists) def load_formatters(self, formatters_namespace): self.formatters_mgr = extension.ExtensionManager( @@ -63,7 +62,7 @@ def get_plugin_id(self, plugin_name): return self.plugins_by_name[plugin_name].plugin._test_id return None - def load_banlists(self, banlist_namespace): + def load_banlists(self, banlist_namespace, load_legacy_blacklists=True): self.banlists_mgr = extension.ExtensionManager( namespace=banlist_namespace, invoke_on_load=False, @@ -71,6 +70,20 @@ def load_banlists(self, banlist_namespace): ) self.banlist = {} banlist = list(self.banlists_mgr) + + if load_legacy_blacklists: + self.legacy_banlists_mgr = extension.ExtensionManager( + namespace='bandit.blacklists', + invoke_on_load=False, + verify_requirements=False, + ) + legacy_banlist = list(self.legacy_banlists_mgr) + if len(legacy_banlist) > 0: + warnings.warn( + "bandit.blacklists will be deprecated in future versions, use bandit.banlists instead.", + PendingDeprecationWarning) + banlist = banlist + legacy_banlist + for item in banlist: for key, val in item.plugin().items(): utils.check_ast_node(key) From a21d4640559dfa61fb9b18cabf233ea3d2999e41 Mon Sep 17 00:00:00 2001 From: Anthony Shaw Date: Wed, 22 Jul 2020 13:25:27 +1000 Subject: [PATCH 11/17] Split line to keep target line length --- bandit/core/extension_loader.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bandit/core/extension_loader.py b/bandit/core/extension_loader.py index 181476089..17adf6282 100644 --- a/bandit/core/extension_loader.py +++ b/bandit/core/extension_loader.py @@ -80,7 +80,8 @@ def load_banlists(self, banlist_namespace, load_legacy_blacklists=True): legacy_banlist = list(self.legacy_banlists_mgr) if len(legacy_banlist) > 0: warnings.warn( - "bandit.blacklists will be deprecated in future versions, use bandit.banlists instead.", + "bandit.blacklists will be deprecated in future versions," + " use bandit.banlists instead.", PendingDeprecationWarning) banlist = banlist + legacy_banlist From 1d4e19b6acb7ce3b0082c9c0305ead7727eb5bf1 Mon Sep 17 00:00:00 2001 From: Anthony Shaw Date: Thu, 23 Jul 2020 08:19:10 +1000 Subject: [PATCH 12/17] Update doc/source/banlists/banlist_calls.rst Co-authored-by: Eric Brown --- doc/source/banlists/banlist_calls.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/banlists/banlist_calls.rst b/doc/source/banlists/banlist_calls.rst index f5c7341ba..f90c2477f 100644 --- a/doc/source/banlists/banlist_calls.rst +++ b/doc/source/banlists/banlist_calls.rst @@ -1,4 +1,4 @@ ---------------- +------------- banlist_calls --------------- From 5576bbc77c46d1e423df5d0d03c594fbf4ea5d66 Mon Sep 17 00:00:00 2001 From: Anthony Shaw Date: Thu, 23 Jul 2020 08:19:19 +1000 Subject: [PATCH 13/17] Update doc/source/banlists/banlist_calls.rst Co-authored-by: Eric Brown --- doc/source/banlists/banlist_calls.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/banlists/banlist_calls.rst b/doc/source/banlists/banlist_calls.rst index f90c2477f..bb1f9fd6e 100644 --- a/doc/source/banlists/banlist_calls.rst +++ b/doc/source/banlists/banlist_calls.rst @@ -1,5 +1,5 @@ ------------- banlist_calls ---------------- +------------- .. automodule:: bandit.banlists.calls From b3934b98061d40a3531792cb5d863cb639122599 Mon Sep 17 00:00:00 2001 From: Anthony Shaw Date: Thu, 23 Jul 2020 08:19:28 +1000 Subject: [PATCH 14/17] Update doc/source/banlists/banlist_imports.rst Co-authored-by: Eric Brown --- doc/source/banlists/banlist_imports.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/banlists/banlist_imports.rst b/doc/source/banlists/banlist_imports.rst index 4b0121239..bbbb6dbc6 100644 --- a/doc/source/banlists/banlist_imports.rst +++ b/doc/source/banlists/banlist_imports.rst @@ -1,4 +1,4 @@ ------------------ +--------------- banlist_imports ----------------- From f99b5e789d96ae3738c8033e79f9938e27f8daa8 Mon Sep 17 00:00:00 2001 From: Anthony Shaw Date: Thu, 23 Jul 2020 08:19:48 +1000 Subject: [PATCH 15/17] Update doc/source/banlists/banlist_imports.rst Co-authored-by: Eric Brown --- doc/source/banlists/banlist_imports.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/banlists/banlist_imports.rst b/doc/source/banlists/banlist_imports.rst index bbbb6dbc6..7e7894da4 100644 --- a/doc/source/banlists/banlist_imports.rst +++ b/doc/source/banlists/banlist_imports.rst @@ -1,5 +1,5 @@ --------------- banlist_imports ------------------ +--------------- .. automodule:: bandit.banlists.imports From 53526050aa0fd363a389c526cc30b76432d6349d Mon Sep 17 00:00:00 2001 From: Anthony Shaw Date: Thu, 23 Jul 2020 08:19:57 +1000 Subject: [PATCH 16/17] Update doc/source/banlists/index.rst Co-authored-by: Eric Brown --- doc/source/banlists/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/banlists/index.rst b/doc/source/banlists/index.rst index dd391423b..bde7de2b2 100644 --- a/doc/source/banlists/index.rst +++ b/doc/source/banlists/index.rst @@ -30,7 +30,7 @@ Items in the data lists are Python dictionaries with the following structure: | 'name' | The issue name string. | +-------------+----------------------------------------------------+ | 'id' | The bandit ID of the check, this must be unique | -| | and is used for filtering banlist checks. | +| | and is used for filtering banlist checks. | +-------------+----------------------------------------------------+ | 'qualnames' | A Python list of fully qualified name strings. | +-------------+----------------------------------------------------+ From de4bd530cbce1364f23062c744177dca79fce026 Mon Sep 17 00:00:00 2001 From: Anthony Shaw Date: Thu, 23 Jul 2020 08:20:09 +1000 Subject: [PATCH 17/17] Update bandit/core/extension_loader.py Co-authored-by: Eric Brown --- bandit/core/extension_loader.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bandit/core/extension_loader.py b/bandit/core/extension_loader.py index 17adf6282..89728f5a4 100644 --- a/bandit/core/extension_loader.py +++ b/bandit/core/extension_loader.py @@ -82,7 +82,7 @@ def load_banlists(self, banlist_namespace, load_legacy_blacklists=True): warnings.warn( "bandit.blacklists will be deprecated in future versions," " use bandit.banlists instead.", - PendingDeprecationWarning) + DeprecationWarning) banlist = banlist + legacy_banlist for item in banlist: