Bandit - Tool Designed To Discovery Mutual Safety Issues Inwards Python Code
Bandit is a tool designed to discovery mutual safety issues inward Python code. To produce this Bandit processes each file, builds an AST from it, in addition to runs appropriate plugins against the AST nodes. Once Bandit has finished scanning all the files it generates a report.
Bandit was originally developed inside the OpenStack Security Project in addition to after rehomed to PyCQA.
Installation
Bandit is distributed on PyPI. The best means to install it is amongst pip:
Create a virtual environs (optional):
virtualenv bandit-env
Install Bandit:pip install bandit # Or if you're working amongst a Python 3 projection pip3 install bandit
Run Bandit:bandit -r path/to/your/code
Bandit tin give the sack also live on installed from source. To produce so, download the source tarball from PyPI, in addition to hence install it:python setup.py install
Usage
Example usage across a code tree:
bandit -r /your_repos/project
Example usage across the examples/
directory, showing 3 lines of context in addition to entirely reporting on the high-severity issues:bandit examples/*.py -n 3 -lll
Bandit tin give the sack live on run amongst profiles. To run Bandit against the examples directory using entirely the plugins listed inward the ShellInjection
profile:bandit examples/*.py -p ShellInjection
Bandit also supports passing lines of code to scan using criterion input. To run Bandit amongst criterion 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] [-q] [--ignore-nosec] [-x EXCLUDED_PATHS] [-b BASELINE] [--ini INI_PATH] [--version] [targets [targets ...]] Bandit - a Python source code safety analyzer positional arguments: targets source file(s) or directory(s) to live on tested optional arguments: -h, --help demonstrate this assistance message in addition to instruct out -r, --recursive discovery in addition to procedure files inward subdirectories -a {file,vuln}, --aggregate {file,vuln} aggregate output past times vulnerability (default) or past times filename -n CONTEXT_LINES, --number CONTEXT_LINES maximum number of code lines to output for each number -c CONFIG_FILE, --configfile CONFIG_FILE optional config file to occupation for selecting plugins in addition to overriding defaults -p PROFILE, --profile PROFILE profile to occupation (defaults to executing all tests) -t TESTS, --tests TESTS comma-separated listing of seek out IDs to run -s SKIPS, --skip SKIPS comma-separated listing of seek out IDs to skip -l, --level study entirely issues of a given severity grade or higher (-l for LOW, -ll for MEDIUM, -lll for HIGH) -i, --confidence study entirely issues of a given confidence grade or higher (-i for LOW, -ii for MEDIUM, -iii for HIGH) -f {cs v,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 amongst --format custom), meet CUSTOM FORMAT department for listing of available values -o [OUTPUT_FILE], --output [OUTPUT_FILE] write study to filename -v, --verbose output extra information similar excluded in addition to included files -d, --debug plow on debug means -q, --quiet, --silent entirely demonstrate output inward the instance of an fault --ignore-nosec produce non skip lines amongst # nosec comments -x EXCLUDED_PATHS, --exclude EXCLUDED_PATHS comma-separated listing of paths (glob patterns supported) to exclude from scan (not e that these are inward add-on to the excluded paths provided inward the config file) -b BASELINE, --baseline BASELINE path of a baseline study to compare against (only JSON-formatted files are accepted) --ini INI_PATH path to a .bandit file that supplies command draw of piece of work arguments --version demonstrate program's version number in addition to instruct out 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 tin give the sack also live on formatted inward python string.format() style: ban dit -r examples/ --format custom --msg-template \ "{relpath:20.20s}: {line:03}: {test_id:^8}: DEFECT: {msg:>20}" See python documentation for to a greater extent than information virtually formatting style: https://docs.python.org/3.4/library/string.html The next tests were discovered in addition to 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 B110 try_except_pass 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 telnetli b 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 B325 tempnam 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 B413 import_pycrypto 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 B507 ssh_no_host_key_verification 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 B610 django_extra_used B611 django_rawsql_used B701 jinja2_autoescape_false B702 use_of_mako_templates B703 django_mark_safe
Baseline
Bandit allows specifying the path of a baseline study to compare against using the base of operations draw of piece of work declaration (i.e.
-b BASELINE
or --baseline BASELINE
).bandit -b BASELINE
This is useful for ignoring known vulnerabilities that you lot believe are non-issues (e.g. a cleartext password inward a unit of measurement test). To generate a baseline study only run Bandit amongst the output format ready to json
(only JSON-formatted files are accepted every bit a baseline) in addition to output file path specified:bandit -f json -o PATH_TO_OUTPUT_FILE
Version command integration
Use pre-commit. Once you lot have it installed, add together this to the .pre-commit-config.yaml inward your repository (be certain to update rev to indicate to a existent git tag/revision!):
repos: - repo: https://github.com/PyCQA/bandit rev: '' # Update me! hooks: - id: bandit
Then run pre-commit install in addition to you're create to go.Configuration
- An optional config file may live on supplied in addition to may include:
- lists of tests which should or shouldn't live on run
- exclude_dirs - sections of the path, that if matched, volition live on excluded from scanning (glob patterns supported)
- overridden plugin settings - may render unlike settings for to a greater extent than or less plugins
Per Project Command Line Args
Projects may include a .bandit file that specifies command draw of piece of work arguments that should live on supplied for that project. The currently supported arguments are:
To occupation this, pose a .bandit file inward your project's directory. For example:
- targets: comma separated listing of target dirs/files to run bandit on
- exclude: comma separated listing of excluded paths
- skips: comma separated listing of tests to skip
- tests: comma separated listing of tests to run
[bandit] exclude: /test
[bandit] tests: B101,B102,B301
Exclusions
In the trial that a draw of piece of work of code triggers a Bandit issue, but that the draw of piece of work has been reviewed in addition to the number is a fake positive or acceptable for to a greater extent than or less other reason, the draw of piece of work tin give the sack live on marked amongst a
# nosec
in addition to whatever results associated amongst it volition non live on reported.For example, although this draw of piece of work may campaign Bandit to study a potential safety issue, it volition non live on reported:
self.process = subprocess.Popen('/bin/echo', shell=True) # nosec
Vulnerability Tests
Vulnerability tests or "plugins" are defined inward files inward the plugins directory.
Tests are written inward Python in addition to are autodiscovered from the plugins directory. Each seek out tin give the sack examine i or to a greater extent than type of Python statements. Tests are marked amongst the types of Python statements they examine (for example: business office call, string, import, etc).
Tests are executed past times the
BanditNodeVisitor
object every bit it visits each node inward the AST.Test results are maintained inward the
BanditResultStore
in addition to aggregated for output at the completion of a seek out run.Writing Tests
- To write a test:
- Identify a vulnerability to create a seek out for, in addition to create a novel file inward examples/ that contains i or to a greater extent than cases of that vulnerability.
- Consider the vulnerability you're testing for, grade the business office amongst i or to a greater extent than of the appropriate decorators: - @checks('Call') - @checks('Import', 'ImportFrom') - @checks('Str')
- Create a novel Python source file to incorporate your test, you lot tin give the sack reference existing tests for examples.
- The business office that you lot create should bring a parameter "context" which is an instance of the context shape you lot tin give the sack query for information virtually the electrical current chemical constituent existence examined. You tin give the sack also instruct the raw AST node for to a greater extent than advanced occupation cases. Please meet the context.py file for more.
- Extend your Bandit configuration file every bit needed to back upward your novel test.
- Execute Bandit against the seek out file you lot defined inward examples/ in addition to ensure that it detects the vulnerability. Consider variations on how this vulnerability mightiness introduce itself in addition to extend the instance file in addition to the seek out business office accordingly.
Extending Bandit
Bandit allows users to write in addition to register extensions for checks in addition to formatters. Bandit volition charge plugins from 2 entry-points:
- bandit.formatters
- bandit.plugins
- result_store: An instance of bandit.core.BanditResultStore
- file_list: The listing of files which were inspected inward the scope
- scores: The scores awarded to each file inward the scope
- excluded_files: The listing of files that were excluded from the scope
@bandit.checks('Call') def prohibit_unsafe_deserialization(context): if 'unsafe_load' inward context.call_function_name_qual: render bandit.Issue( severity=bandit.HIGH, confidence=bandit.HIGH, text="Unsafe deserialization detected." )
To register your plugin, you lot conduct hold 2 options:- If you're using setuptools directly, add together something similar the next to your
setup
call:
# If you lot conduct hold an imaginary bson formatter inward the bandit_bson module # in addition to a business office called `formatter`. entry_points={'bandit.formatters': ['bson = bandit_bson:formatter']} # Or a banking venture check for using mako templates inward bandit_mako that entry_points={'bandit.plugins': ['mako = bandit_mako']}
- If you're using pbr, add together something similar the next to your setup.cfg file:
[entry_points] bandit.formatters = bson = bandit_bson:formatter bandit.plugins = mako = bandit_mako
Contributing
Contributions to Bandit are ever welcome!
The best means to instruct started amongst Bandit is to select care of the source:
git clone https://github.com/PyCQA/bandit.git
You tin give the sack seek out whatever changes amongst tox:pip install tox tox -e pep8 tox -e py27 tox -e py35 tox -e docs tox -e cover
Please brand PR requests using your ain branch, in addition to non master:git checkout -b mychange git force source mychange
Reporting Bugs
Bugs should live on reported on github. To file a põrnikas against Bandit, visit: https://github.com/PyCQA/bandit/issues
Under Which Version of Python Should I Install Bandit?
The response to this query depends on the project(s) you lot volition live on running Bandit against. If your projection is entirely compatible amongst Python 2.7, you lot should install Bandit to run nether Python 2.7. If your projection is entirely compatible amongst Python 3.5, in addition to hence occupation 3.5 respectively. If your projection supports both, you lot could run Bandit amongst both versions but you lot don't conduct hold to.
Bandit uses the ast module from Python's criterion library inward venture to analyze your Python code. The ast module is entirely able to parse Python code that is valid inward the version of the interpreter from which it is imported. In other words, if you lot endeavor to occupation Python 2.7's ast module to parse code written for 3.5 that uses, for example, yield from amongst asyncio, in addition to hence you'll conduct hold syntax errors that volition foreclose Bandit from working properly. Alternatively, if you lot are relying on 2.7's octal musical note of 0777 in addition to hence you'll conduct hold a syntax fault if you lot run Bandit on 3.x.
References
Bandit docs: https://bandit.readthedocs.io/en/latest/
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 diverse types of AST nodes that Bandit currently covers or could live on extended to cover: https://greentreesnakes.readthedocs.org/en/latest/nodes.html