Project Migration to PyCQA

This change rehomes the project to PyCQA[1] as reported to the
openstack-dev mailing list [1]

[0] https://github.com/PyCQA/bandit
[1] http://lists.openstack.org/pipermail/openstack-dev/2018-April/129386.html

Change-Id: I6aad329a60799ea24a3d9bc49e35c3c35ed9dc3b
changes/53/564453/3
lhinds 5 years ago committed by Andreas Jaeger
parent 209182c3ee
commit 2d2170273b
  1. 3
      .coveragerc
  2. 19
      .gitignore
  3. 4
      .stestr.conf
  4. 179
      .zuul.yaml
  5. 176
      LICENSE
  6. 429
      README.rst
  7. 31
      bandit/__init__.py
  8. 0
      bandit/blacklists/__init__.py
  9. 544
      bandit/blacklists/calls.py
  10. 305
      bandit/blacklists/imports.py
  11. 22
      bandit/blacklists/utils.py
  12. 0
      bandit/cli/__init__.py
  13. 224
      bandit/cli/baseline.py
  14. 186
      bandit/cli/config_generator.py
  15. 401
      bandit/cli/main.py
  16. 27
      bandit/core/__init__.py
  17. 75
      bandit/core/blacklisting.py
  18. 243
      bandit/core/config.py
  19. 42
      bandit/core/constants.py
  20. 339
      bandit/core/context.py
  21. 53
      bandit/core/docs_utils.py
  22. 118
      bandit/core/extension_loader.py
  23. 139
      bandit/core/issue.py
  24. 398
      bandit/core/manager.py
  25. 57
      bandit/core/meta_ast.py
  26. 103
      bandit/core/metrics.py
  27. 279
      bandit/core/node_visitor.py
  28. 85
      bandit/core/test_properties.py
  29. 123
      bandit/core/test_set.py
  30. 111
      bandit/core/tester.py
  31. 336
      bandit/core/utils.py
  32. 0
      bandit/formatters/__init__.py
  33. 76
      bandit/formatters/csv.py
  34. 163
      bandit/formatters/custom.py
  35. 387
      bandit/formatters/html.py
  36. 152
      bandit/formatters/json.py
  37. 182
      bandit/formatters/screen.py
  38. 164
      bandit/formatters/text.py
  39. 43
      bandit/formatters/utils.py
  40. 91
      bandit/formatters/xml.py
  41. 131
      bandit/formatters/yaml.py
  42. 0
      bandit/plugins/__init__.py
  43. 69
      bandit/plugins/app_debug.py
  44. 65
      bandit/plugins/asserts.py
  45. 72
      bandit/plugins/crypto_request_no_cert_validation.py
  46. 67
      bandit/plugins/exec.py
  47. 94
      bandit/plugins/exec_as_root.py
  48. 89
      bandit/plugins/general_bad_file_permissions.py
  49. 59
      bandit/plugins/general_bind_all_interfaces.py
  50. 215
      bandit/plugins/general_hardcoded_password.py
  51. 86
      bandit/plugins/general_hardcoded_tmp.py
  52. 63
      bandit/plugins/hashlib_new_insecure_functions.py
  53. 74
      bandit/plugins/injection_paramiko.py
  54. 634
      bandit/plugins/injection_shell.py
  55. 115
      bandit/plugins/injection_sql.py
  56. 149
      bandit/plugins/injection_wildcard.py
  57. 274
      bandit/plugins/insecure_ssl_tls.py
  58. 131
      bandit/plugins/jinja2_templates.py
  59. 76
      bandit/plugins/mako_templates.py
  60. 115
      bandit/plugins/secret_config_option.py
  61. 110
      bandit/plugins/try_except_continue.py
  62. 110
      bandit/plugins/try_except_pass.py
  63. 140
      bandit/plugins/weak_cryptographic_key.py
  64. 69
      bandit/plugins/yaml_load.py
  65. 2
      bindep.txt
  66. 7
      doc/requirements.txt
  67. 5
      doc/source/blacklists/blacklist_calls.rst
  68. 5
      doc/source/blacklists/blacklist_imports.rst
  69. 69
      doc/source/blacklists/index.rst
  70. 88
      doc/source/conf.py
  71. 82
      doc/source/config.rst
  72. 5
      doc/source/formatters/csv.rst
  73. 5
      doc/source/formatters/html.rst
  74. 42
      doc/source/formatters/index.rst
  75. 5
      doc/source/formatters/json.rst
  76. 5
      doc/source/formatters/screen.rst
  77. 5
      doc/source/formatters/text.rst
  78. 5
      doc/source/formatters/xml.rst
  79. 5
      doc/source/formatters/yaml.rst
  80. 27
      doc/source/index.rst
  81. 128
      doc/source/man/bandit.rst
  82. 5
      doc/source/plugins/b101_assert_used.rst
  83. 5
      doc/source/plugins/b102_exec_used.rst
  84. 5
      doc/source/plugins/b103_set_bad_file_permissions.rst
  85. 5
      doc/source/plugins/b104_hardcoded_bind_all_interfaces.rst
  86. 8
      doc/source/plugins/b105_hardcoded_password_string.rst
  87. 8
      doc/source/plugins/b106_hardcoded_password_funcarg.rst
  88. 8
      doc/source/plugins/b107_hardcoded_password_funcdef.rst
  89. 5
      doc/source/plugins/b108_hardcoded_tmp_directory.rst
  90. 5
      doc/source/plugins/b109_password_config_option_not_marked_secret.rst
  91. 5
      doc/source/plugins/b110_try_except_pass.rst
  92. 5
      doc/source/plugins/b111_execute_with_run_as_root_equals_true.rst
  93. 5
      doc/source/plugins/b112_try_except_continue.rst
  94. 5
      doc/source/plugins/b201_flask_debug_true.rst
  95. 5
      doc/source/plugins/b501_request_with_no_cert_validation.rst
  96. 8
      doc/source/plugins/b502_ssl_with_bad_version.rst
  97. 8
      doc/source/plugins/b503_ssl_with_bad_defaults.rst
  98. 8
      doc/source/plugins/b504_ssl_with_no_version.rst
  99. 5
      doc/source/plugins/b505_weak_cryptographic_key.rst
  100. 5
      doc/source/plugins/b506_yaml_load.rst
  101. Some files were not shown because too many files have changed in this diff Show More

@ -1,3 +0,0 @@
[report]
include = bandit/*
omit = bandit/tests/functional/*

19
.gitignore vendored

@ -1,19 +0,0 @@
env*
venv*
*.pyc
.DS_Store
*.egg
*.egg-info
.eggs/
.idea/
.tox
.stestr
build/*
cover/*
.coverage*
doc/build/*
ChangeLog
doc/source/api
.*.sw?
AUTHORS
releasenotes/build

@ -1,4 +0,0 @@
[DEFAULT]
test_path=${OS_TEST_PATH:-./tests/unit}
top_dir=./
group_regex=.*(test_cert_setup)

@ -1,179 +0,0 @@
- job:
name: bandit-integration-barbican
parent: legacy-base
run: playbooks/legacy/bandit-integration-barbican/run.yaml
timeout: 1800
required-projects:
- openstack/bandit
- openstack/barbican
- openstack/requirements
- job:
name: bandit-integration-glance
parent: legacy-base
run: playbooks/legacy/bandit-integration-glance/run.yaml
timeout: 1800
required-projects:
- openstack/bandit
- openstack/glance
- openstack/requirements
- job:
name: bandit-integration-glance_store
parent: legacy-base
run: playbooks/legacy/bandit-integration-glance_store/run.yaml
timeout: 1800
required-projects:
- openstack/bandit
- openstack/glance
- openstack/glance_store
- openstack/requirements
- job:
name: bandit-integration-keystone
parent: legacy-base
run: playbooks/legacy/bandit-integration-keystone/run.yaml
timeout: 1800
required-projects:
- openstack/bandit
- openstack/keystone
- openstack/requirements
- job:
name: bandit-integration-keystonemiddleware
parent: legacy-base
run: playbooks/legacy/bandit-integration-keystonemiddleware/run.yaml
timeout: 1800
required-projects:
- openstack/bandit
- openstack/keystone
- openstack/keystonemiddleware
- openstack/requirements
- job:
name: bandit-integration-magnum
parent: legacy-base
run: playbooks/legacy/bandit-integration-magnum/run.yaml
timeout: 1800
required-projects:
- openstack/bandit
- openstack/magnum
- openstack/requirements
- job:
name: bandit-integration-oslo.config
parent: legacy-base
run: playbooks/legacy/bandit-integration-oslo.config/run.yaml
timeout: 1800
required-projects:
- openstack/bandit
- openstack/oslo.config
- openstack/requirements
- job:
name: bandit-integration-oslo.log
parent: legacy-base
run: playbooks/legacy/bandit-integration-oslo.log/run.yaml
timeout: 1800
required-projects:
- openstack/bandit
- openstack/oslo.log
- openstack/requirements
- job:
name: bandit-integration-oslo.service
parent: legacy-base
run: playbooks/legacy/bandit-integration-oslo.service/run.yaml
timeout: 1800
required-projects:
- openstack/bandit
- openstack/oslo.service
- openstack/requirements
- job:
name: bandit-integration-oslo.utils
parent: legacy-base
run: playbooks/legacy/bandit-integration-oslo.utils/run.yaml
timeout: 1800
required-projects:
- openstack/bandit
- openstack/oslo.utils
- openstack/requirements
- job:
name: bandit-integration-oslo.vmware
parent: legacy-base
run: playbooks/legacy/bandit-integration-oslo.vmware/run.yaml
timeout: 1800
required-projects:
- openstack/bandit
- openstack/oslo.vmware
- openstack/requirements
- job:
name: bandit-integration-python-keystoneclient
parent: legacy-base
run: playbooks/legacy/bandit-integration-python-keystoneclient/run.yaml
timeout: 1800
required-projects:
- openstack/bandit
- openstack/keystone
- openstack/python-keystoneclient
- openstack/requirements
- job:
name: bandit-integration-python-magnumclient
parent: legacy-base
run: playbooks/legacy/bandit-integration-python-magnumclient/run.yaml
timeout: 1800
required-projects:
- openstack/bandit
- openstack/magnum
- openstack/python-magnumclient
- openstack/requirements
- job:
name: bandit-integration-sahara
parent: legacy-base
run: playbooks/legacy/bandit-integration-sahara/run.yaml
timeout: 1800
required-projects:
- openstack/ara
- openstack/bandit
- openstack/requirements
- openstack/sahara
- project:
check:
jobs:
- bandit-integration-barbican
- bandit-integration-glance
- bandit-integration-keystone
- bandit-integration-glance_store
- bandit-integration-keystonemiddleware
- bandit-integration-magnum
- bandit-integration-oslo.config
- bandit-integration-oslo.log
- bandit-integration-oslo.service
- bandit-integration-oslo.utils
- bandit-integration-oslo.vmware
- bandit-integration-python-keystoneclient
- bandit-integration-python-magnumclient
- bandit-integration-sahara
- openstack-tox-lower-constraints
gate:
jobs:
- bandit-integration-barbican
- bandit-integration-glance
- bandit-integration-keystone
- bandit-integration-glance_store
- bandit-integration-keystonemiddleware
- bandit-integration-magnum
- bandit-integration-oslo.config
- bandit-integration-oslo.log
- bandit-integration-oslo.service
- bandit-integration-oslo.utils
- bandit-integration-oslo.vmware
- bandit-integration-python-keystoneclient
- bandit-integration-python-magnumclient
- openstack-tox-lower-constraints

@ -1,176 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.

@ -1,428 +1,13 @@
Bandit
======
.. image:: https://governance.openstack.org/badges/bandit.svg
:target: https://governance.openstack.org/reference/tags/index.html
:alt: Bandit team and repository tags
This project is no longer maintained in OpenStack.
.. image:: https://img.shields.io/pypi/v/bandit.svg
:target: https://pypi.python.org/pypi/bandit/
:alt: Latest Version
Please visit PyCQA to raise issues or make contributions:
.. image:: https://img.shields.io/pypi/pyversions/bandit.svg
:target: https://pypi.python.org/pypi/bandit/
:alt: Python Versions
https://github.com/PyCQA/bandit
.. image:: https://img.shields.io/pypi/format/bandit.svg
:target: https://pypi.python.org/pypi/bandit/
:alt: Format
.. image:: https://img.shields.io/badge/license-Apache%202-blue.svg
:target: https://git.openstack.org/cgit/openstack/bandit/plain/LICENSE
:alt: License
A security linter from OpenStack Security
* Free software: Apache license
* Documentation: https://wiki.openstack.org/wiki/Security/Projects/Bandit
* Source: https://git.openstack.org/cgit/openstack/bandit
* Bugs: https://bugs.launchpad.net/bandit
Overview
--------
Bandit is a tool designed to find common security issues in Python code. To do
this Bandit processes each file, builds an AST from it, and runs appropriate
plugins against the AST nodes. Once Bandit has finished scanning all the files
it generates a report.
Installation
------------
Bandit is distributed on PyPI. The best way to install it is with pip:
Create a virtual environment (optional)::
virtualenv bandit-env
Install Bandit::
pip install bandit
# Or if you're working with a Python 3.5 project
pip3.5 install bandit
Run Bandit::
bandit -r path/to/your/code
Bandit can also be installed from source. To do so, download the source tarball
from PyPI, then install it::
python setup.py install
Usage
-----
Example usage across a code tree::
bandit -r ~/openstack-repo/keystone
Example usage across the ``examples/`` directory, showing three lines of
context and only reporting on the high-severity issues::
bandit examples/*.py -n 3 -lll
Bandit can be run with profiles. To run Bandit against the examples directory
using only the plugins listed in the ``ShellInjection`` profile::
bandit examples/*.py -p ShellInjection
Bandit also supports passing lines of code to scan using standard input. To
run Bandit with standard input::
cat examples/imports.py | bandit -
Usage::
$ bandit -h
usage: bandit [-h] [-r] [-a {file,vuln}] [-n CONTEXT_LINES] [-c CONFIG_FILE]
[-p PROFILE] [-t TESTS] [-s SKIPS] [-l] [-i]
[-f {csv,custom,html,json,screen,txt,xml,yaml}]
[--msg-template MSG_TEMPLATE] [-o [OUTPUT_FILE]] [-v] [-d]
[--ignore-nosec] [-x EXCLUDED_PATHS] [-b BASELINE]
[--ini INI_PATH] [--version]
[targets [targets ...]]
Bandit - a Python source code security analyzer
positional arguments:
targets source file(s) or directory(s) to be tested
optional arguments:
-h, --help show this help message and exit
-r, --recursive find and process files in subdirectories
-a {file,vuln}, --aggregate {file,vuln}
aggregate output by vulnerability (default) or by
filename
-n CONTEXT_LINES, --number CONTEXT_LINES
maximum number of code lines to output for each issue
-c CONFIG_FILE, --configfile CONFIG_FILE
optional config file to use for selecting plugins and
overriding defaults
-p PROFILE, --profile PROFILE
profile to use (defaults to executing all tests)
-t TESTS, --tests TESTS
comma-separated list of test IDs to run
-s SKIPS, --skip SKIPS
comma-separated list of test IDs to skip
-l, --level report only issues of a given severity level or higher
(-l for LOW, -ll for MEDIUM, -lll for HIGH)
-i, --confidence report only issues of a given confidence level or
higher (-i for LOW, -ii for MEDIUM, -iii for HIGH)
-f {csv,custom,html,json,screen,txt,xml,yaml}, --format {csv,custom,html,json,screen,txt,xml,yaml}
specify output format
--msg-template MSG_TEMPLATE
specify output message template (only usable with
--format custom), see CUSTOM FORMAT section for list
of available values
-o [OUTPUT_FILE], --output [OUTPUT_FILE]
write report to filename
-v, --verbose output extra information like excluded and included
files
-d, --debug turn on debug mode
--ignore-nosec do not skip lines with # nosec comments
-x EXCLUDED_PATHS, --exclude EXCLUDED_PATHS
comma-separated list of paths to exclude from scan
(note that these are in addition to the excluded paths
provided in the config file)
-b BASELINE, --baseline BASELINE
path of a baseline report to compare against (only
JSON-formatted files are accepted)
--ini INI_PATH path to a .bandit file that supplies command line
arguments
--version show program's version number and exit
CUSTOM FORMATTING
-----------------
Available tags:
{abspath}, {relpath}, {line}, {test_id},
{severity}, {msg}, {confidence}, {range}
Example usage:
Default template:
bandit -r examples/ --format custom --msg-template \
"{abspath}:{line}: {test_id}[bandit]: {severity}: {msg}"
Provides same output as:
bandit -r examples/ --format custom
Tags can also be formatted in python string.format() style:
bandit -r examples/ --format custom --msg-template \
"{relpath:20.20s}: {line:03}: {test_id:^8}: DEFECT: {msg:>20}"
See python documentation for more information about formatting style:
https://docs.python.org/3.4/library/string.html
The following tests were discovered and loaded:
-----------------------------------------------
B101 assert_used
B102 exec_used
B103 set_bad_file_permissions
B104 hardcoded_bind_all_interfaces
B105 hardcoded_password_string
B106 hardcoded_password_funcarg
B107 hardcoded_password_default
B108 hardcoded_tmp_directory
B109 password_config_option_not_marked_secret
B110 try_except_pass
B111 execute_with_run_as_root_equals_true
B112 try_except_continue
B201 flask_debug_true
B301 pickle
B302 marshal
B303 md5
B304 ciphers
B305 cipher_modes
B306 mktemp_q
B307 eval
B308 mark_safe
B309 httpsconnection
B310 urllib_urlopen
B311 random
B312 telnetlib
B313 xml_bad_cElementTree
B314 xml_bad_ElementTree
B315 xml_bad_expatreader
B316 xml_bad_expatbuilder
B317 xml_bad_sax
B318 xml_bad_minidom
B319 xml_bad_pulldom
B320 xml_bad_etree
B321 ftplib
B322 input
B323 unverified_context
B324 hashlib_new_insecure_functions
B401 import_telnetlib
B402 import_ftplib
B403 import_pickle
B404 import_subprocess
B405 import_xml_etree
B406 import_xml_sax
B407 import_xml_expat
B408 import_xml_minidom
B409 import_xml_pulldom
B410 import_lxml
B411 import_xmlrpclib
B412 import_httpoxy
B501 request_with_no_cert_validation
B502 ssl_with_bad_version
B503 ssl_with_bad_defaults
B504 ssl_with_no_version
B505 weak_cryptographic_key
B506 yaml_load
B601 paramiko_calls
B602 subprocess_popen_with_shell_equals_true
B603 subprocess_without_shell_equals_true
B604 any_other_function_with_shell_equals_true
B605 start_process_with_a_shell
B606 start_process_with_no_shell
B607 start_process_with_partial_path
B608 hardcoded_sql_expressions
B609 linux_commands_wildcard_injection
B701 jinja2_autoescape_false
B702 use_of_mako_templates
Configuration
-------------
An optional config file may be supplied and may include:
- lists of tests which should or shouldn't be run
- exclude_dirs - sections of the path, that if matched, will be excluded from
scanning
- overridden plugin settings - may provide different settings for some
plugins
Per Project Command Line Args
-----------------------------
Projects may include a `.bandit` file that specifies command line arguments
that should be supplied for that project. The currently supported arguments
are:
- targets: comma separated list of target dirs/files to run bandit on
- exclude: comma separated list of excluded paths
- skips: comma separated list of tests to skip
- tests: comma separated list of tests to run
To use this, put a .bandit file in your project's directory. For example:
::
[bandit]
exclude: /test
::
[bandit]
tests: B101,B102,B301
Exclusions
----------
In the event that a line of code triggers a Bandit issue, but that the line
has been reviewed and the issue is a false positive or acceptable for some
other reason, the line can be marked with a ``# nosec`` and any results
associated with it will not be reported.
For example, although this line may cause Bandit to report a potential
security issue, it will not be reported::
self.process = subprocess.Popen('/bin/echo', shell=True) # nosec
Vulnerability Tests
-------------------
Vulnerability tests or "plugins" are defined in files in the plugins directory.
Tests are written in Python and are autodiscovered from the plugins directory.
Each test can examine one or more type of Python statements. Tests are marked
with the types of Python statements they examine (for example: function call,
string, import, etc).
Tests are executed by the ``BanditNodeVisitor`` object as it visits each node
in the AST.
Test results are maintained in the ``BanditResultStore`` and aggregated for
output at the completion of a test run.
Writing Tests
-------------
To write a test:
- Identify a vulnerability to build a test for, and create a new file in
examples/ that contains one or more cases of that vulnerability.
- Consider the vulnerability you're testing for, mark the function with one
or more of the appropriate decorators:
- @checks('Call')
- @checks('Import', 'ImportFrom')
- @checks('Str')
- Create a new Python source file to contain your test, you can reference
existing tests for examples.
- The function that you create should take a parameter "context" which is
an instance of the context class you can query for information about the
current element being examined. You can also get the raw AST node for
more advanced use cases. Please see the context.py file for more.
- Extend your Bandit configuration file as needed to support your new test.
- Execute Bandit against the test file you defined in examples/ and ensure
that it detects the vulnerability. Consider variations on how this
vulnerability might present itself and extend the example file and the test
function accordingly.
Extending Bandit
----------------
Bandit allows users to write and register extensions for checks and formatters.
Bandit will load plugins from two entry-points:
- `bandit.formatters`
- `bandit.plugins`
Formatters need to accept 4 things:
- `result_store`: An instance of `bandit.core.BanditResultStore`
- `file_list`: The list of files which were inspected in the scope
- `scores`: The scores awarded to each file in the scope
- `excluded_files`: The list of files that were excluded from the scope
Plugins tend to take advantage of the `bandit.checks` decorator which allows
the author to register a check for a particular type of AST node. For example
::
@bandit.checks('Call')
def prohibit_unsafe_deserialization(context):
if 'unsafe_load' in context.call_function_name_qual:
return bandit.Issue(
severity=bandit.HIGH,
confidence=bandit.HIGH,
text="Unsafe deserialization detected."
)
To register your plugin, you have two options:
1. If you're using setuptools directly, add something like the following to
your ``setup`` call::
# If you have an imaginary bson formatter in the bandit_bson module
# and a function called `formatter`.
entry_points={'bandit.formatters': ['bson = bandit_bson:formatter']}
# Or a check for using mako templates in bandit_mako that
entry_points={'bandit.plugins': ['mako = bandit_mako']}
2. If you're using pbr, add something like the following to your `setup.cfg`
file::
[entry_points]
bandit.formatters =
bson = bandit_bson:formatter
bandit.plugins =
mako = bandit_mako
Contributing
------------
Contributions to Bandit are always welcome! We can be found on
#openstack-security on Freenode IRC.
The best way to get started with Bandit is to grab the source::
git clone https://git.openstack.org/openstack/bandit.git
You can test any changes with tox::
pip install tox
tox -e pep8
tox -e py27
tox -e py35
tox -e docs
tox -e cover
Reporting Bugs
--------------
Bugs should be reported on Launchpad. To file a bug against Bandit, visit:
https://bugs.launchpad.net/bandit/+filebug
Under Which Version of Python Should I Install Bandit?
------------------------------------------------------
The answer to this question depends on the project(s) you will be running
Bandit against. If your project is only compatible with Python 2.7, you
should install Bandit to run under Python 2.7. If your project is only
compatible with Python 3.5, then use 3.5 respectively. If your project supports
both, you *could* run Bandit with both versions but you don't have to.
Bandit uses the `ast` module from Python's standard library in order to
analyze your Python code. The `ast` module is only able to parse Python code
that is valid in the version of the interpreter from which it is imported. In
other words, if you try to use Python 2.7's `ast` module to parse code written
for 3.5 that uses, for example, `yield from` with asyncio, then you'll have
syntax errors that will prevent Bandit from working properly. Alternatively,
if you are relying on 2.7's octal notation of `0777` then you'll have a syntax
error if you run Bandit on 3.x.
References
==========
Bandit wiki: https://wiki.openstack.org/wiki/Security/Projects/Bandit
Python AST module documentation: https://docs.python.org/2/library/ast.html
Green Tree Snakes - the missing Python AST docs:
https://greentreesnakes.readthedocs.org/en/latest/
Documentation of the various types of AST nodes that Bandit currently covers
or could be extended to cover:
https://greentreesnakes.readthedocs.org/en/latest/nodes.html
The contents of this repository are still available in the Git
source code management system. To see the contents of this
repository before it reached its end of life, please check out the
previous commit with "git checkout HEAD^1".

@ -1,31 +0,0 @@
# -*- 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 pbr.version
from bandit.core import config # noqa
from bandit.core import context # noqa
from bandit.core import manager # noqa
from bandit.core import meta_ast # noqa
from bandit.core import node_visitor # noqa
from bandit.core import test_set # noqa
from bandit.core import tester # noqa
from bandit.core import utils # noqa
from bandit.core.constants import * # noqa
from bandit.core.issue import * # noqa
from bandit.core.test_properties import * # noqa
__version__ = pbr.version.VersionInfo('bandit').version_string()

@ -1,544 +0,0 @@
# -*- coding:utf-8 -*-
#
# Copyright 2016 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.
r"""
====================================================
Blacklist 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
function calls encoutered in the scanned code base, triggered by encoutering
ast.Call nodes.
B301: pickle
------------
Pickle library appears to be in use, possible security issue.
+------+---------------------+------------------------------------+-----------+
| ID | Name | Calls | Severity |
+======+=====================+====================================+===========+
| B301 | pickle | - pickle.loads | Medium |
| | | - pickle.load | |
| | | - pickle.Unpickler | |
| | | - cPickle.loads | |
| | | - cPickle.load | |
| | | - cPickle.Unpickler | |
+------+---------------------+------------------------------------+-----------+
B302: marshal
-------------
Deserialization with the marshal module is possibly dangerous.
+------+---------------------+------------------------------------+-----------+
| ID | Name | Calls | Severity |
+======+=====================+====================================+===========+
| B302 | marshal | - marshal.load | Medium |
| | | - marshal.loads | |
+------+---------------------+------------------------------------+-----------+
B303: md5
---------
Use of insecure MD2, MD4, MD5, or SHA1 hash function.
+------+---------------------+------------------------------------+-----------+
| ID | Name | Calls | Severity |
+======+=====================+====================================+===========+
| B303 | md5 | - hashlib.md5 | Medium |
| | | - hashlib.sha1 | |
| | | - Crypto.Hash.MD2.new | |
| | | - Crypto.Hash.MD4.new | |
| | | - Crypto.Hash.MD5.new | |
| | | - Crypto.Hash.SHA.new | |
| | | - Cryptodome.Hash.MD2.new | |
| | | - Cryptodome.Hash.MD4.new | |
| | | - Cryptodome.Hash.MD5.new | |
| | | - Cryptodome.Hash.SHA.new | |
| | | - cryptography.hazmat.primitives | |
| | | .hashes.MD5 | |
| | | - cryptography.hazmat.primitives | |
| | | .hashes.SHA1 | |
+------+---------------------+------------------------------------+-----------+
B304 - B305: ciphers and modes
------------------------------
Use of insecure cipher or cipher mode. Replace with a known secure cipher such
as AES.
+------+---------------------+------------------------------------+-----------+
| ID | Name | Calls | Severity |
+======+=====================+====================================+===========+
| B304 | ciphers | - Crypto.Cipher.ARC2.new | High |
| | | - Crypto.Cipher.ARC4.new | |
| | | - Crypto.Cipher.Blowfish.new | |
| | | - Crypto.Cipher.DES.new | |
| | | - Crypto.Cipher.XOR.new | |
| | | - Cryptodome.Cipher.ARC2.new | |
| | | - Cryptodome.Cipher.ARC4.new | |
| | | - Cryptodome.Cipher.Blowfish.new | |
| | | - Cryptodome.Cipher.DES.new | |
| | | - Cryptodome.Cipher.XOR.new | |
| | | - cryptography.hazmat.primitives | |
| | | .ciphers.algorithms.ARC4 | |
| | | - cryptography.hazmat.primitives | |
| | | .ciphers.algorithms.Blowfish | |
| | | - cryptography.hazmat.primitives | |
| | | .ciphers.algorithms.IDEA | |
+------+---------------------+------------------------------------+-----------+
| B305 | cipher_modes | - cryptography.hazmat.primitives | Medium |
| | | .ciphers.modes.ECB | |
+------+---------------------+------------------------------------+-----------+
B306: mktemp_q
--------------
Use of insecure and deprecated function (mktemp).
+------+---------------------+------------------------------------+-----------+
| ID | Name | Calls | Severity |
+======+=====================+====================================+===========+
| B306 | mktemp_q | - tempfile.mktemp | Medium |
+------+---------------------+------------------------------------+-----------+
B307: eval
----------
Use of possibly insecure function - consider using safer ast.literal_eval.
+------+---------------------+------------------------------------+-----------+
| ID | Name | Calls | Severity |
+======+=====================+====================================+===========+
| B307 | eval | - eval | Medium |
+------+---------------------+------------------------------------+-----------+
B308: mark_safe
---------------
Use of mark_safe() may expose cross-site scripting vulnerabilities and should
be reviewed.
+------+---------------------+------------------------------------+-----------+
| ID | Name | Calls | Severity |
+======+=====================+====================================+===========+
| B308 | mark_safe | - django.utils.safestring.mark_safe| Medium |
+------+---------------------+------------------------------------+-----------+
B309: httpsconnection
---------------------
Use of HTTPSConnection on older versions of Python prior to 2.7.9 and 3.4.3 do
not provide security, see https://wiki.openstack.org/wiki/OSSN/OSSN-0033
+------+---------------------+------------------------------------+-----------+
| ID | Name | Calls | Severity |
+======+=====================+====================================+===========+
| B309 | httpsconnection | - httplib.HTTPSConnection | Medium |
| | | - http.client.HTTPSConnection | |
| | | - six.moves.http_client | |
| | | .HTTPSConnection | |
+------+---------------------+------------------------------------+-----------+
B310: urllib_urlopen
--------------------
Audit url open for permitted schemes. Allowing use of 'file:'' or custom
schemes is often unexpected.
+------+---------------------+------------------------------------+-----------+
| ID | Name | Calls | Severity |
+======+=====================+====================================+===========+
| B310 | urllib_urlopen | - urllib.urlopen | Medium |
| | | - urllib.request.urlopen | |
| | | - urllib.urlretrieve | |
| | | - urllib.request.urlretrieve | |
| | | - urllib.URLopener | |
| | | - urllib.request.URLopener | |
| | | - urllib.FancyURLopener | |
| | | - urllib.request.FancyURLopener | |
| | | - urllib2.urlopen | |
| | | - urllib2.Request | |
| | | - six.moves.urllib.request.urlopen | |
| | | - six.moves.urllib.request | |
| | | .urlretrieve | |
| | | - six.moves.urllib.request | |
| | | .URLopener | |
| | | - six.moves.urllib.request | |
| | | .FancyURLopener | |
+------+---------------------+------------------------------------+-----------+
B311: random
------------
Standard pseudo-random generators are not suitable for security/cryptographic
purposes.
+------+---------------------+------------------------------------+-----------+
| ID | Name | Calls | Severity |
+======+=====================+====================================+===========+
| B311 | random | - random.random | Low |
| | | - random.randrange | |
| | | - random.randint | |
| | | - random.choice | |
| | | - random.uniform | |
| | | - random.triangular | |
+------+---------------------+------------------------------------+-----------+
B312: telnetlib
---------------
Telnet-related functions are being called. Telnet is considered insecure. Use
SSH or some other encrypted protocol.
+------+---------------------+------------------------------------+-----------+
| ID | Name | Calls | Severity |
+======+=====================+====================================+===========+
| B312 | telnetlib | - telnetlib.\* | High |
+------+---------------------+------------------------------------+-----------+
B313 - B320: XML
----------------
Most of this is based off of Christian Heimes' work on defusedxml:
https://pypi.python.org/pypi/defusedxml/#defusedxml-sax
Using various XLM methods to parse untrusted XML data is known to be vulnerable
to XML attacks. Methods should be replaced with their defusedxml equivalents.
+------+---------------------+------------------------------------+-----------+
| ID | Name | Calls | Severity |
+======+=====================+====================================+===========+
| B313 | xml_bad_cElementTree| - xml.etree.cElementTree.parse | Medium |
| | | - xml.etree.cElementTree.iterparse | |
| | | - xml.etree.cElementTree.fromstring| |
| | | - xml.etree.cElementTree.XMLParser | |
+------+---------------------+------------------------------------+-----------+
| B314 | xml_bad_ElementTree | - xml.etree.ElementTree.parse | Medium |
| | | - xml.etree.ElementTree.iterparse | |
| | | - xml.etree.ElementTree.fromstring | |
| | | - xml.etree.ElementTree.XMLParser | |
+------+---------------------+------------------------------------+-----------+
| B315 | xml_bad_expatreader | - xml.sax.expatreader.create_parser| Medium |
+------+---------------------+------------------------------------+-----------+
| B316 | xml_bad_expatbuilder| - xml.dom.expatbuilder.parse | Medium |
| | | - xml.dom.expatbuilder.parseString | |
+------+---------------------+------------------------------------+-----------+
| B317 | xml_bad_sax | - xml.sax.parse | Medium |
| | | - xml.sax.parseString | |
| | | - xml.sax.make_parser | |
+------+---------------------+------------------------------------+-----------+
| B318 | xml_bad_minidom | - xml.dom.minidom.parse | Medium |
| | | - xml.dom.minidom.parseString | |
+------+---------------------+------------------------------------+-----------+
| B319 | xml_bad_pulldom | - xml.dom.pulldom.parse | Medium |
| | | - xml.dom.pulldom.parseString | |
+------+---------------------+------------------------------------+-----------+
| B320 | xml_bad_etree | - lxml.etree.parse | Medium |
| | | - lxml.etree.fromstring | |
| | | - lxml.etree.RestrictedElement | |
| | | - lxml.etree.GlobalParserTLS | |
| | | - lxml.etree.getDefaultParser | |
| | | - lxml.etree.check_docinfo | |
+------+---------------------+------------------------------------+-----------+
B321: ftplib
------------
FTP-related functions are being called. FTP is considered insecure. Use
SSH/SFTP/SCP or some other encrypted protocol.
+------+---------------------+------------------------------------+-----------+
| ID | Name | Calls | Severity |
+======+=====================+====================================+===========+
| B321 | ftplib | - ftplib.\* | High |
+------+---------------------+------------------------------------+-----------+
B322: input
------------
The input method in Python 2 will read from standard input, evaluate and
run the resulting string as python source code. This is similar, though in
many ways worse, then using eval. On Python 2, use raw_input instead, input
is safe in Python 3.
+------+---------------------+------------------------------------+-----------+
| ID | Name | Calls | Severity |
+======+=====================+====================================+===========+
| B322 | input | - input | High |
+------+---------------------+------------------------------------+-----------+
B323: unverified_context
------------------------
By default, Python will create a secure, verified ssl context for use in such
classes as HTTPSConnection. However, it still allows using an insecure
context via the _create_unverified_context that reverts to the previous
behavior that does not validate certificates or perform hostname checks.
+------+---------------------+------------------------------------+-----------+
| ID | Name | Calls | Severity |
+======+=====================+====================================+===========+
| B323 | unverified_context | - ssl._create_unverified_context | Medium |
+------+---------------------+------------------------------------+-----------+
"""
from bandit.blacklists import utils
def gen_blacklist():
"""Generate a list of items to blacklist.
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
usage.
:return: a dictionary mapping node types to a list of blacklist data
"""
sets = []
sets.append(utils.build_conf_dict(
'pickle', 'B301',
['pickle.loads',
'pickle.load',
'pickle.Unpickler',
'cPickle.loads',
'cPickle.load',
'cPickle.Unpickler'],
'Pickle library appears to be in use, possible security issue.'
))
sets.append(utils.build_conf_dict(
'marshal', 'B302', ['marshal.load', 'marshal.loads'],
'Deserialization with the marshal module is possibly dangerous.'
))
sets.append(utils.build_conf_dict(
'md5', 'B303',
['hashlib.md5',
'hashlib.sha1',
'Crypto.Hash.MD2.new',
'Crypto.Hash.MD4.new',
'Crypto.Hash.MD5.new',
'Crypto.Hash.SHA.new',
'Cryptodome.Hash.MD2.new',
'Cryptodome.Hash.MD4.new',
'Cryptodome.Hash.MD5.new',
'Cryptodome.Hash.SHA.new',
'cryptography.hazmat.primitives.hashes.MD5',
'cryptography.hazmat.primitives.hashes.SHA1'],
'Use of insecure MD2, MD4, MD5, or SHA1 hash function.'
))
sets.append(utils.build_conf_dict(
'ciphers', 'B304',
['Crypto.Cipher.ARC2.new',
'Crypto.Cipher.ARC4.new',
'Crypto.Cipher.Blowfish.new',
'Crypto.Cipher.DES.new',
'Crypto.Cipher.XOR.new',
'Cryptodome.Cipher.ARC2.new',
'Cryptodome.Cipher.ARC4.new',
'Cryptodome.Cipher.Blowfish.new',
'Cryptodome.Cipher.DES.new',
'Cryptodome.Cipher.XOR.new',
'cryptography.hazmat.primitives.ciphers.algorithms.ARC4',
'cryptography.hazmat.primitives.ciphers.algorithms.Blowfish',
'cryptography.hazmat.primitives.ciphers.algorithms.IDEA'],
'Use of insecure cipher {name}. Replace with a known secure'
' cipher such as AES.',
'HIGH'
))
sets.append(utils.build_conf_dict(
'cipher_modes', 'B305',
['cryptography.hazmat.primitives.ciphers.modes.ECB'],
'Use of insecure cipher mode {name}.'
))
sets.append(utils.build_conf_dict(
'mktemp_q', 'B306', ['tempfile.mktemp'],
'Use of insecure and deprecated function (mktemp).'
))
sets.append(utils.build_conf_dict(
'eval', 'B307', ['eval'],
'Use of possibly insecure function - consider using safer '
'ast.literal_eval.'
))
sets.append(utils.build_conf_dict(
'mark_safe', 'B308', ['django.utils.safestring.mark_safe'],
'Use of mark_safe() may expose cross-site scripting '
'vulnerabilities and should be reviewed.'
))
sets.append(utils.build_conf_dict(
'httpsconnection', 'B309',
['httplib.HTTPSConnection',
'http.client.HTTPSConnection',
'six.moves.http_client.HTTPSConnection'],
'Use of HTTPSConnection on older versions of Python prior to 2.7.9 '
'and 3.4.3 do not provide security, see '
'https://wiki.openstack.org/wiki/OSSN/OSSN-0033'
))
sets.append(utils.build_conf_dict(
'urllib_urlopen', 'B310',
['urllib.urlopen',
'urllib.request.urlopen',
'urllib.urlretrieve',
'urllib.request.urlretrieve',
'urllib.URLopener',
'urllib.request.URLopener',
'urllib.FancyURLopener',
'urllib.request.FancyURLopener',
'urllib2.urlopen',
'urllib2.Request',
'six.moves.urllib.request.urlopen',
'six.moves.urllib.request.urlretrieve',
'six.moves.urllib.request.URLopener',
'six.moves.urllib.request.FancyURLopener'],
'Audit url open for permitted schemes. Allowing use of file:/ or '
'custom schemes is often unexpected.'
))
sets.append(utils.build_conf_dict(
'random', 'B311',
['random.random',
'random.randrange',
'random.randint',
'random.choice',
'random.uniform',
'random.triangular'],
'Standard pseudo-random generators are not suitable for '
'security/cryptographic purposes.',
'LOW'
))
sets.append(utils.build_conf_dict(
'telnetlib', 'B312', ['telnetlib.*'],
'Telnet-related functions are being called. Telnet is considered '
'insecure. Use SSH or some other encrypted protocol.',
'HIGH'
))
# Most of this is based off of Christian Heimes' work on defusedxml:
# https://pypi.python.org/pypi/defusedxml/#defusedxml-sax
xml_msg = ('Using {name} to parse untrusted XML data is known to be '
'vulnerable to XML attacks. Replace {name} with its '