diff --git a/bandit.yaml b/bandit.yaml new file mode 100644 index 000000000..d41da69aa --- /dev/null +++ b/bandit.yaml @@ -0,0 +1,362 @@ +# optional: after how many files to update progress +#show_progress_every: 100 + +# optional: plugins directory name +#plugins_dir: plugins + +# optional: plugins discovery name pattern +plugin_name_pattern: '*.py' + +# optional: terminal escape sequences to display colors +#output_colors: +# DEFAULT: \033[0m +# HEADER: \033[95m +# LOW: \033[94m +# MEDIUM: \033[93m +# HIGH: \033[91m + +# optional: log format string +#log_format: "[%(module)s]\t%(levelname)s\t%(message)s" + +# globs of files which should be analyzed +include: + - '*.py' + - '*.pyw' + +# a list of strings, which if found in the path will cause files to be excluded +# for example /tests/ - to remove all files in tests directory +exclude_dirs: + - '/tests/' + +profiles: + oslo.messaging: + include: + - any_other_function_with_shell_equals_true + # Some occurrences in the olso.messaging code, but not much to do + # to get rid of these warnings, so just skip this. + # - assert_used + - blacklist_calls + - blacklist_import_func + - blacklist_imports + - exec_used + - execute_with_run_as_root_equals_true + - hardcoded_bind_all_interfaces + - hardcoded_password_string + - hardcoded_password_funcarg + - hardcoded_password_default + - hardcoded_sql_expressions + - hardcoded_tmp_directory + - jinja2_autoescape_false + - linux_commands_wildcard_injection + - paramiko_calls + - password_config_option_not_marked_secret + - request_with_no_cert_validation + - set_bad_file_permissions + - subprocess_popen_with_shell_equals_true + - subprocess_without_shell_equals_true + - start_process_with_a_shell + - start_process_with_no_shell + - start_process_with_partial_path + - ssl_with_bad_defaults + - ssl_with_bad_version + - ssl_with_no_version + # This might be nice to have, but we currently ignore a lot of + # exceptions during the cleanup phases, so this throws a lot + # false positives. + # - try_except_pass + - use_of_mako_templates + - weak_cryptographic_key + + XSS: + include: + - jinja2_autoescape_false + - use_of_mako_templates + + ShellInjection: + include: + - subprocess_popen_with_shell_equals_true + - subprocess_without_shell_equals_true + - any_other_function_with_shell_equals_true + - start_process_with_a_shell + - start_process_with_no_shell + - start_process_with_partial_path + exclude: + + SqlInjection: + include: + - hardcoded_sql_expressions + +blacklist_calls: + bad_name_sets: + - pickle: + qualnames: + - pickle.loads + - pickle.load + - pickle.Unpickler + - cPickle.loads + - cPickle.load + - cPickle.Unpickler + message: > + Pickle library appears to be in use, possible security issue. + - marshal: + qualnames: [marshal.load, marshal.loads] + message: > + Deserialization with the marshal module is possibly dangerous. + - md5: + qualnames: + - hashlib.md5 + - Crypto.Hash.MD2.new + - Crypto.Hash.MD4.new + - Crypto.Hash.MD5.new + - cryptography.hazmat.primitives.hashes.MD5 + message: Use of insecure MD2, MD4, or MD5 hash function. + - ciphers: + qualnames: + - Crypto.Cipher.ARC2.new + - Crypto.Cipher.ARC4.new + - Crypto.Cipher.Blowfish.new + - Crypto.Cipher.DES.new + - Crypto.Cipher.XOR.new + - cryptography.hazmat.primitives.ciphers.algorithms.ARC4 + - cryptography.hazmat.primitives.ciphers.algorithms.Blowfish + - cryptography.hazmat.primitives.ciphers.algorithms.IDEA + message: > + Use of insecure cipher {func}. Replace with a known secure + cipher such as AES. + level: HIGH + - cipher_modes: + qualnames: + - cryptography.hazmat.primitives.ciphers.modes.ECB + message: Use of insecure cipher mode {func}. + - mktemp_q: + qualnames: [tempfile.mktemp] + message: Use of insecure and deprecated function (mktemp). + - eval: + qualnames: [eval] + message: > + Use of possibly insecure function - consider using safer + ast.literal_eval. + - mark_safe: + names: [mark_safe] + message: > + Use of mark_safe() may expose cross-site scripting + vulnerabilities and should be reviewed. + - httpsconnection: + qualnames: [httplib.HTTPSConnection] + message: > + Use of HTTPSConnection does not provide security, see + https://wiki.openstack.org/wiki/OSSN/OSSN-0033 + - yaml_load: + qualnames: [yaml.load] + message: > + Use of unsafe yaml load. Allows instantiation of arbitrary + objects. Consider yaml.safe_load(). + - urllib_urlopen: + qualnames: + - urllib.urlopen + - urllib.urlretrieve + - urllib.URLopener + - urllib.FancyURLopener + - urllib2.urlopen + - urllib2.Request + message: > + Audit url open for permitted schemes. Allowing use of file:/ or + custom schemes is often unexpected. + - telnetlib: + qualnames: + - telnetlib.* + message: > + Telnet-related funtions are being called. Telnet is considered + insecure. Use SSH or some other encrypted protocol. + level: HIGH + # Most of this is based off of Christian Heimes' work on defusedxml: + # https://pypi.python.org/pypi/defusedxml/#defusedxml-sax + - xml_bad_cElementTree: + qualnames: + - xml.etree.cElementTree.parse + - xml.etree.cElementTree.iterparse + - xml.etree.cElementTree.fromstring + - xml.etree.cElementTree.XMLParser + message: > + Using {func} to parse untrusted XML data is known to be + vulnerable to XML attacks. Replace {func} with its defusedxml + equivalent function. + - xml_bad_ElementTree: + qualnames: + - xml.etree.ElementTree.parse + - xml.etree.ElementTree.iterparse + - xml.etree.ElementTree.fromstring + - xml.etree.ElementTree.XMLParser + message: > + Using {func} to parse untrusted XML data is known to be + vulnerable to XML attacks. Replace {func} with its defusedxml + equivalent function. + - xml_bad_expatreader: + qualnames: [xml.sax.expatreader.create_parser] + message: > + Using {func} to parse untrusted XML data is known to be + vulnerable to XML attacks. Replace {func} with its defusedxml + equivalent function. + - xml_bad_expatbuilder: + qualnames: + - xml.dom.expatbuilder.parse + - xml.dom.expatbuilder.parseString + message: > + Using {func} to parse untrusted XML data is known to be + vulnerable to XML attacks. Replace {func} with its defusedxml + equivalent function. + - xml_bad_sax: + qualnames: + - xml.sax.parse + - xml.sax.parseString + - xml.sax.make_parser + message: > + Using {func} to parse untrusted XML data is known to be + vulnerable to XML attacks. Replace {func} with its defusedxml + equivalent function. + - xml_bad_minidom: + qualnames: + - xml.dom.minidom.parse + - xml.dom.minidom.parseString + message: > + Using {func} to parse untrusted XML data is known to be + vulnerable to XML attacks. Replace {func} with its defusedxml + equivalent function. + - xml_bad_pulldom: + qualnames: + - xml.dom.pulldom.parse + - xml.dom.pulldom.parseString + message: > + Using {func} to parse untrusted XML data is known to be + vulnerable to XML attacks. Replace {func} with its defusedxml + equivalent function. + - xml_bad_etree: + qualnames: + - lxml.etree.parse + - lxml.etree.fromstring + - lxml.etree.RestrictedElement + - lxml.etree.GlobalParserTLS + - lxml.etree.getDefaultParser + - lxml.etree.check_docinfo + message: > + Using {func} to parse untrusted XML data is known to be + vulnerable to XML attacks. Replace {func} with its defusedxml + equivalent function. + + +shell_injection: + # Start a process using the subprocess module, or one of its wrappers. + subprocess: + - subprocess.Popen + - subprocess.call + - subprocess.check_call + - subprocess.check_output + - utils.execute + - utils.execute_with_timeout + # Start a process with a function vulnerable to shell injection. + shell: + - os.system + - os.popen + - os.popen2 + - os.popen3 + - os.popen4 + - popen2.popen2 + - popen2.popen3 + - popen2.popen4 + - popen2.Popen3 + - popen2.Popen4 + - commands.getoutput + - commands.getstatusoutput + # Start a process with a function that is not vulnerable to shell injection. + no_shell: + - os.execl + - os.execle + - os.execlp + - os.execlpe + - os.execv + - os.execve + - os.execvp + - os.execvpe + - os.spawnl + - os.spawnle + - os.spawnlp + - os.spawnlpe + - os.spawnv + - os.spawnve + - os.spawnvp + - os.spawnvpe + - os.startfile + +blacklist_imports: + bad_import_sets: + - telnet: + imports: [telnetlib] + level: HIGH + message: > + A telnet-related module is being imported. Telnet is + considered insecure. Use SSH or some other encrypted protocol. + - info_libs: + imports: [pickle, cPickle, subprocess, Crypto] + level: LOW + message: > + Consider possible security implications associated with + {module} module. + + # Most of this is based off of Christian Heimes' work on defusedxml: + # https://pypi.python.org/pypi/defusedxml/#defusedxml-sax + + - xml_libs: + imports: + - xml.etree.cElementTree + - xml.etree.ElementTree + - xml.sax.expatreader + - xml.sax + - xml.dom.expatbuilder + - xml.dom.minidom + - xml.dom.pulldom + - lxml.etree + - lxml + message: > + Using {module} to parse untrusted XML data is known to be + vulnerable to XML attacks. Replace {module} with the equivalent + defusedxml package. + level: LOW + - xml_libs_high: + imports: [xmlrpclib] + message: > + Using {module} to parse untrusted XML data is known to be + vulnerable to XML attacks. Use defused.xmlrpc.monkey_patch() + function to monkey-patch xmlrpclib and mitigate XML + vulnerabilities. + level: HIGH + +hardcoded_tmp_directory: + tmp_dirs: [/tmp, /var/tmp, /dev/shm] + +hardcoded_password: + # Support for full path, relative path and special "%(site_data_dir)s" + # substitution (/usr/{local}/share) + word_list: "%(site_data_dir)s/wordlist/default-passwords" + +ssl_with_bad_version: + bad_protocol_versions: + - PROTOCOL_SSLv2 + - SSLv2_METHOD + - SSLv23_METHOD + - PROTOCOL_SSLv3 # strict option + - PROTOCOL_TLSv1 # strict option + - SSLv3_METHOD # strict option + - TLSv1_METHOD # strict option + +password_config_option_not_marked_secret: + function_names: + - oslo.config.cfg.StrOpt + - oslo_config.cfg.StrOpt + +execute_with_run_as_root_equals_true: + function_names: + - ceilometer.utils.execute + - cinder.utils.execute + - neutron.agent.linux.utils.execute + - nova.utils.execute + - nova.utils.trycmd diff --git a/test-requirements.txt b/test-requirements.txt index 693f069b1..53d199ceb 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -36,3 +36,6 @@ oslosphinx>=2.5.0 # Apache-2.0 # AMQP 1.0 support depends on the Qpid Proton AMQP 1.0 # development libraries. pyngus>=2.0.0 # Apache-2.0 + +# Bandit security code scanner +bandit>=0.13.2 diff --git a/tox.ini b/tox.ini index c576bed72..1689b87a9 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py34,py27,pep8 +envlist = py34,py27,pep8,bandit [testenv] setenv = @@ -38,6 +38,10 @@ commands = {toxinidir}/setup-test-env-qpid.sh 1.0 python setup.py testr --slowes [testenv:py27-func-zeromq] commands = {toxinidir}/setup-test-env-zmq.sh python setup.py testr --slowest --testr-args='oslo_messaging.tests.functional' +[testenv:bandit] +deps = -r{toxinidir}/test-requirements.txt +commands = bandit -c bandit.yaml -r oslo_messaging -n5 -p oslo.messaging + [flake8] show-source = True ignore = H237,H402,H405,H904