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:
  • 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
To occupation this, pose a .bandit file inward your project's directory. For example:
[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
Formatters demand to bring iv things:
  • 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
Plugins tend to bring payoff of the bandit.checks decorator which allows the writer to register a banking venture check for a item type of AST node. For example
@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:
  1. 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']}
  2. 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