bandit/tests/functional/test_functional.py

700 lines
27 KiB
Python

# -*- coding:utf-8 -*-
#
# Copyright 2014 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import os
import six
import testtools
from bandit.core import config as b_config
from bandit.core import constants as C
from bandit.core import manager as b_manager
from bandit.core import metrics
from bandit.core import test_set as b_test_set
class FunctionalTests(testtools.TestCase):
'''Functional tests for bandit test plugins.
This set of tests runs bandit against each example file in turn
and records the score returned. This is compared to a known good value.
When new tests are added to an example the expected result should be
adjusted to match.
'''
def setUp(self):
super(FunctionalTests, self).setUp()
# NOTE(tkelsey): bandit is very sensitive to paths, so stitch
# them up here for the testing environment.
#
path = os.path.join(os.getcwd(), 'bandit', 'plugins')
b_conf = b_config.BanditConfig()
self.b_mgr = b_manager.BanditManager(b_conf, 'file')
self.b_mgr.b_conf._settings['plugins_dir'] = path
self.b_mgr.b_ts = b_test_set.BanditTestSet(config=b_conf)
def run_example(self, example_script, ignore_nosec=False):
'''A helper method to run the specified test
This method runs the test, which populates the self.b_mgr.scores
value. Call this directly if you need to run a test, but do not
need to test the resulting scores against specified values.
:param example_script: Filename of an example script to test
'''
path = os.path.join(os.getcwd(), 'examples', example_script)
self.b_mgr.ignore_nosec = ignore_nosec
self.b_mgr.discover_files([path], True)
self.b_mgr.run_tests()
def check_example(self, example_script, expect, ignore_nosec=False):
'''A helper method to test the scores for example scripts.
:param example_script: Filename of an example script to test
:param expect: dict with expected counts of issue types
'''
# reset scores for subsequent calls to check_example
self.b_mgr.scores = []
self.run_example(example_script, ignore_nosec=ignore_nosec)
result = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 0}
}
for test_scores in self.b_mgr.scores:
for score_type in test_scores:
self.assertIn(score_type, expect)
for idx, rank in enumerate(C.RANKING):
result[score_type][rank] = (test_scores[score_type][idx] /
C.RANKING_VALUES[rank])
self.assertDictEqual(expect, result)
def check_metrics(self, example_script, expect):
'''A helper method to test the metrics being returned.
:param example_script: Filename of an example script to test
:param expect: dict with expected values of metrics
'''
self.b_mgr.metrics = metrics.Metrics()
self.b_mgr.scores = []
self.run_example(example_script)
# test general metrics (excludes issue counts)
m = self.b_mgr.metrics.data
for k in expect:
if k != 'issues':
self.assertEqual(expect[k], m['_totals'][k])
# test issue counts
if 'issues' in expect:
for (criteria, default) in C.CRITERIA:
for rank in C.RANKING:
label = '{0}.{1}'.format(criteria, rank)
expected = 0
if expect['issues'].get(criteria).get(rank):
expected = expect['issues'][criteria][rank]
self.assertEqual(expected, m['_totals'][label])
def test_binding(self):
'''Test the bind-to-0.0.0.0 example.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 1, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 1, 'HIGH': 0}
}
self.check_example('binding.py', expect)
def test_crypto_md5(self):
'''Test the `hashlib.md5` example.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 15, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 15}
}
self.check_example('crypto-md5.py', expect)
def test_ciphers(self):
'''Test the `Crypto.Cipher` example.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 1, 'HIGH': 13},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 14}
}
self.check_example('ciphers.py', expect)
def test_cipher_modes(self):
'''Test for insecure cipher modes.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 1, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 1}
}
self.check_example('cipher-modes.py', expect)
def test_eval(self):
'''Test the `eval` example.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 3, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 3}
}
self.check_example('eval.py', expect)
def test_mark_safe(self):
'''Test the `mark_safe` example.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 1, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 1}
}
self.check_example('mark_safe.py', expect)
def test_exec(self):
'''Test the `exec` example.'''
filename = 'exec-{}.py'
if six.PY2:
filename = filename.format('py2')
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 2, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0,
'HIGH': 2}
}
else:
filename = filename.format('py3')
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 1, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0,
'HIGH': 1}
}
self.check_example(filename, expect)
def test_exec_as_root(self):
'''Test for the `run_as_root=True` keyword argument.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 5, 'MEDIUM': 0, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 5, 'HIGH': 0}
}
self.check_example('exec-as-root.py', expect)
def test_hardcoded_passwords(self):
'''Test for hard-coded passwords.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 8, 'MEDIUM': 0, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 8, 'HIGH': 0}
}
self.check_example('hardcoded-passwords.py', expect)
def test_hardcoded_tmp(self):
'''Test for hard-coded /tmp, /var/tmp, /dev/shm.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 3, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 3, 'HIGH': 0}
}
self.check_example('hardcoded-tmp.py', expect)
def test_httplib_https(self):
'''Test for `httplib.HTTPSConnection`.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 3, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 3}
}
self.check_example('httplib_https.py', expect)
def test_imports_aliases(self):
'''Test the `import X as Y` syntax.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 4, 'MEDIUM': 5, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 9}
}
self.check_example('imports-aliases.py', expect)
def test_imports_from(self):
'''Test the `from X import Y` syntax.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 3, 'MEDIUM': 0, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 3}
}
self.check_example('imports-from.py', expect)
def test_imports_function(self):
'''Test the `__import__` function.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 2, 'MEDIUM': 0, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 2}
}
self.check_example('imports-function.py', expect)
def test_telnet_usage(self):
'''Test for `import telnetlib` and Telnet.* calls.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 2},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 2}
}
self.check_example('telnetlib.py', expect)
def test_ftp_usage(self):
'''Test for `import ftplib` and FTP.* calls.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 2},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 2}
}
self.check_example('ftplib.py', expect)
def test_imports(self):
'''Test for dangerous imports.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 2, 'MEDIUM': 0, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 2}
}
self.check_example('imports.py', expect)
def test_mktemp(self):
'''Test for `tempfile.mktemp`.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 4, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 4}
}
self.check_example('mktemp.py', expect)
def test_nonsense(self):
'''Test that a syntactically invalid module is skipped.'''
self.run_example('nonsense.py')
self.assertEqual(1, len(self.b_mgr.skipped))
def test_okay(self):
'''Test a vulnerability-free file.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 0}
}
self.check_example('okay.py', expect)
def test_os_chmod(self):
'''Test setting file permissions.'''
filename = 'os-chmod-{}.py'
if six.PY2:
filename = filename.format('py2')
else:
filename = filename.format('py3')
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 2, 'HIGH': 8},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 1, 'HIGH': 9}
}
self.check_example(filename, expect)
def test_os_exec(self):
'''Test for `os.exec*`.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 8, 'MEDIUM': 0, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 8, 'HIGH': 0}
}
self.check_example('os-exec.py', expect)
def test_os_popen(self):
'''Test for `os.popen`.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 8, 'MEDIUM': 0, 'HIGH': 1},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 9}
}
self.check_example('os-popen.py', expect)
def test_os_spawn(self):
'''Test for `os.spawn*`.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 8, 'MEDIUM': 0, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 8, 'HIGH': 0}
}
self.check_example('os-spawn.py', expect)
def test_os_startfile(self):
'''Test for `os.startfile`.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 3, 'MEDIUM': 0, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 3, 'HIGH': 0}
}
self.check_example('os-startfile.py', expect)
def test_os_system(self):
'''Test for `os.system`.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 1, 'MEDIUM': 0, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 1}
}
self.check_example('os_system.py', expect)
def test_pickle(self):
'''Test for the `pickle` module.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 2, 'MEDIUM': 6, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 8}
}
self.check_example('pickle_deserialize.py', expect)
def test_popen_wrappers(self):
'''Test the `popen2` and `commands` modules.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 7, 'MEDIUM': 0, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 7}
}
self.check_example('popen_wrappers.py', expect)
def test_random_module(self):
'''Test for the `random` module.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 6, 'MEDIUM': 0, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 6}
}
self.check_example('random_module.py', expect)
def test_requests_ssl_verify_disabled(self):
'''Test for the `requests` library skipping verification.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 7},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 7}
}
self.check_example('requests-ssl-verify-disabled.py', expect)
def test_skip(self):
'''Test `#nosec` and `#noqa` comments.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 5, 'MEDIUM': 0, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 5}
}
self.check_example('skip.py', expect)
def test_ignore_skip(self):
'''Test --ignore-nosec flag.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 7, 'MEDIUM': 0, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 7}
}
self.check_example('skip.py', expect, ignore_nosec=True)
def test_sql_statements(self):
'''Test for SQL injection through string building.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 14, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 8, 'MEDIUM': 6, 'HIGH': 0}
}
self.check_example('sql_statements.py', expect)
def test_ssl_insecure_version(self):
'''Test for insecure SSL protocol versions.'''
expect = {
'SEVERITY': {'LOW': 1, 'MEDIUM': 10, 'HIGH': 7},
'CONFIDENCE': {'LOW': 0, 'MEDIUM': 11, 'HIGH': 7}
}
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 1, 'MEDIUM': 10, 'HIGH': 7},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 11, 'HIGH': 7}
}
self.check_example('ssl-insecure-version.py', expect)
def test_subprocess_shell(self):
'''Test for `subprocess.Popen` with `shell=True`.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 14, 'MEDIUM': 1, 'HIGH': 3},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 1, 'MEDIUM': 0, 'HIGH': 17}
}
self.check_example('subprocess_shell.py', expect)
def test_urlopen(self):
'''Test for dangerous URL opening.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 14, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 14}
}
self.check_example('urlopen.py', expect)
def test_utils_shell(self):
'''Test for `utils.execute*` with `shell=True`.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 5, 'MEDIUM': 0, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 5}
}
self.check_example('utils-shell.py', expect)
def test_wildcard_injection(self):
'''Test for wildcard injection in shell commands.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 10, 'MEDIUM': 0, 'HIGH': 4},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 5, 'HIGH': 9}
}
self.check_example('wildcard-injection.py', expect)
def test_yaml(self):
'''Test for `yaml.load`.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 1, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 1}
}
self.check_example('yaml_load.py', expect)
def test_jinja2_templating(self):
'''Test jinja templating for potential XSS bugs.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 5},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 2, 'HIGH': 3}
}
self.check_example('jinja2_templating.py', expect)
def test_secret_config_option(self):
'''Test for `secret=True` in Oslo's config.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 3, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 1, 'MEDIUM': 2, 'HIGH': 0}
}
self.check_example('secret-config-option.py', expect)
def test_mako_templating(self):
'''Test Mako templates for XSS.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 3, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 3}
}
self.check_example('mako_templating.py', expect)
def test_xml(self):
'''Test xml vulnerabilities.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 1, 'MEDIUM': 4, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 5}
}
self.check_example('xml_etree_celementtree.py', expect)
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 1, 'MEDIUM': 2, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 3}
}
self.check_example('xml_expatbuilder.py', expect)
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 3, 'MEDIUM': 1, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 4}
}
self.check_example('xml_lxml.py', expect)
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 2, 'MEDIUM': 2, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 4}
}
self.check_example('xml_pulldom.py', expect)
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 1},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 1}
}
self.check_example('xml_xmlrpc.py', expect)
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 1, 'MEDIUM': 4, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 5}
}
self.check_example('xml_etree_elementtree.py', expect)
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 1, 'MEDIUM': 1, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 2}
}
self.check_example('xml_expatreader.py', expect)
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 2, 'MEDIUM': 2, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 4}
}
self.check_example('xml_minidom.py', expect)
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 2, 'MEDIUM': 6, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 8}
}
self.check_example('xml_sax.py', expect)
def test_httpoxy(self):
'''Test httpoxy vulnerability.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 1},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 1}
}
self.check_example('httpoxy_cgihandler.py', expect)
self.check_example('httpoxy_twisted_script.py', expect)
self.check_example('httpoxy_twisted_directory.py', expect)
def test_asserts(self):
'''Test catching the use of assert.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 1, 'MEDIUM': 0, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 1}
}
self.check_example('assert.py', expect)
def test_paramiko_injection(self):
'''Test paramiko command execution.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 2, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 2, 'HIGH': 0}
}
self.check_example('paramiko_injection.py', expect)
def test_partial_path(self):
'''Test process spawning with partial file paths.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 11, 'MEDIUM': 0, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 11}
}
self.check_example('partial_path_process.py', expect)
def test_try_except_continue(self):
'''Test try, except, continue detection.'''
test = next((x for x in self.b_mgr.b_ts.tests['ExceptHandler']
if x.__name__ == 'try_except_continue'))
test._config = {'check_typed_exception': True}
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 3, 'MEDIUM': 0, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 3}
}
self.check_example('try_except_continue.py', expect)
test._config = {'check_typed_exception': False}
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 2, 'MEDIUM': 0, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 2}
}
self.check_example('try_except_continue.py', expect)
def test_try_except_pass(self):
'''Test try, except pass detection.'''
test = next((x for x in self.b_mgr.b_ts.tests['ExceptHandler']
if x.__name__ == 'try_except_pass'))
test._config = {'check_typed_exception': True}
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 3, 'MEDIUM': 0, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 3}
}
self.check_example('try_except_pass.py', expect)
test._config = {'check_typed_exception': False}
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 2, 'MEDIUM': 0, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 2}
}
self.check_example('try_except_pass.py', expect)
def test_metric_gathering(self):
expect = {
'nosec': 2, 'loc': 7,
'issues': {'CONFIDENCE': {'HIGH': 5}, 'SEVERITY': {'LOW': 5}}
}
self.check_metrics('skip.py', expect)
expect = {
'nosec': 0, 'loc': 4,
'issues': {'CONFIDENCE': {'HIGH': 2}, 'SEVERITY': {'LOW': 2}}
}
self.check_metrics('imports.py', expect)
def test_weak_cryptographic_key(self):
'''Test for weak key sizes.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 8, 'HIGH': 6},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 14}
}
self.check_example('weak_cryptographic_key_sizes.py', expect)
def test_multiline_code(self):
'''Test issues in multiline statements return code as expected.'''
self.run_example('multiline_statement.py')
self.assertEqual(0, len(self.b_mgr.skipped))
self.assertEqual(1, len(self.b_mgr.files_list))
self.assertTrue(self.b_mgr.files_list[0].endswith(
'multiline_statement.py'))
issues = self.b_mgr.get_issue_list()
self.assertEqual(2, len(issues))
self.assertTrue(
issues[0].fname.endswith('examples/multiline_statement.py')
)
self.assertEqual(1, issues[0].lineno)
self.assertEqual(list(range(1, 3)), issues[0].linerange)
self.assertIn('subprocess', issues[0].get_code())
self.assertEqual(5, issues[1].lineno)
self.assertEqual(list(range(3, 6 + 1)), issues[1].linerange)
self.assertIn('shell=True', issues[1].get_code())
def test_code_line_numbers(self):
self.run_example('binding.py')
issues = self.b_mgr.get_issue_list()
code_lines = issues[0].get_code().splitlines()
lineno = issues[0].lineno
self.assertEqual("%i " % (lineno - 1), code_lines[0][:2])
self.assertEqual("%i " % (lineno), code_lines[1][:2])
self.assertEqual("%i " % (lineno + 1), code_lines[2][:2])
def test_flask_debug_true(self):
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 1},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 1, 'HIGH': 0}
}
self.check_example('flask_debug.py', expect)
def test_nosec(self):
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 0}
}
self.check_example('nosec.py', expect)
def test_baseline_filter(self):
issue_text = ('A Flask app appears to be run with debug=True, which '
'exposes the Werkzeug debugger and allows the execution '
'of arbitrary code.')
json = """{
"results": [
{
"code": "...",
"filename": "%s/examples/flask_debug.py",
"issue_confidence": "MEDIUM",
"issue_severity": "HIGH",
"issue_text": "%s",
"line_number": 10,
"line_range": [
10
],
"test_name": "flask_debug_true",
"test_id": "B201"
}
]
}
""" % (os.getcwd(), issue_text)
self.b_mgr.populate_baseline(json)
self.run_example('flask_debug.py')
self.assertEqual(1, len(self.b_mgr.baseline))
self.assertEqual({}, self.b_mgr.get_issue_list())
def test_blacklist_input(self):
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 1},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 1}
}
self.check_example('input.py', expect)
def test_unverified_context(self):
'''Test for `ssl._create_unverified_context`.'''
expect = {
'SEVERITY': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 1, 'HIGH': 0},
'CONFIDENCE': {'UNDEFINED': 0, 'LOW': 0, 'MEDIUM': 0, 'HIGH': 1}
}
self.check_example('unverified_context.py', expect)