~ubuntu-branches/ubuntu/wily/bandit/wily-proposed

« back to all changes in this revision

Viewing changes to README.md

  • Committer: Package Import Robot
  • Author(s): Dave Walker (Daviey)
  • Date: 2015-07-22 09:01:39 UTC
  • Revision ID: package-import@ubuntu.com-20150722090139-fl0nluy0x8m9ctx4
Tags: upstream-0.12.0
ImportĀ upstreamĀ versionĀ 0.12.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
Bandit
 
2
======
 
3
 
 
4
A security linter from OpenStack Security
 
5
 
 
6
 
 
7
Overview
 
8
--------
 
9
Bandit is a tool designed to find common security issues in Python code. To do
 
10
this Bandit processes each file, builds an AST from it, and runs appropriate
 
11
plugins against the AST nodes.  Once Bandit has finished scanning all the files
 
12
it generates a report.
 
13
 
 
14
Installation
 
15
------------
 
16
Bandit is distributed on PyPI.  The best way to install it is with pip:
 
17
 
 
18
 
 
19
***Create a virtual environment (optional):***
 
20
 
 
21
    virtualenv bandit-env
 
22
 
 
23
***Install Bandit:***
 
24
 
 
25
    pip install bandit
 
26
    # Or, if you're working with a Python 3 project
 
27
    pip3.4 install bandit
 
28
 
 
29
***Run Bandit:***
 
30
 
 
31
    bandit -r path/to/your/code
 
32
 
 
33
 
 
34
Bandit can also be installed from source.  To do so, download the source
 
35
tarball from PyPI, then install it:
 
36
 
 
37
    python setup.py install
 
38
 
 
39
 
 
40
Usage
 
41
-----
 
42
Example usage across a code tree:
 
43
 
 
44
    bandit -r ~/openstack-repo/keystone
 
45
 
 
46
Example usage across the examples/ directory, showing three lines of context
 
47
and only reporting on the high-severity issues:
 
48
 
 
49
    bandit examples/*.py -n 3 -lll
 
50
 
 
51
Bandit can be run with profiles.  To run Bandit against the examples directory
 
52
using only the plugins listed in the ShellInjection profile:
 
53
 
 
54
    bandit examples/*.py -p ShellInjection
 
55
 
 
56
Usage::
 
57
 
 
58
    bandit -h
 
59
    usage: bandit [-h] [-r] [-a {file,vuln}] [-n CONTEXT_LINES] [-c CONFIG_FILE]
 
60
                  [-p PROFILE] [-l] [-f {txt,json,csv,xml}] [-o OUTPUT_FILE] [-v]
 
61
                  [-d]
 
62
                  targets [targets ...]
 
63
 
 
64
    Bandit - a Python source code analyzer.
 
65
 
 
66
    positional arguments:
 
67
      targets               source file(s) or directory(s) to be tested
 
68
 
 
69
    optional arguments:
 
70
      -h, --help            show this help message and exit
 
71
      -r, --recursive       process files in subdirectories
 
72
      -a {file,vuln}, --aggregate {file,vuln}
 
73
                            group results by vulnerability type or file it occurs
 
74
                            in
 
75
      -n CONTEXT_LINES, --number CONTEXT_LINES
 
76
                            max number of code lines to display for each issue
 
77
                            identified
 
78
      -c CONFIG_FILE, --configfile CONFIG_FILE
 
79
                            test config file, defaults to /etc/bandit/bandit.yaml,
 
80
                            or./bandit.yaml if not given
 
81
      -p PROFILE, --profile PROFILE
 
82
                            test set profile in config to use (defaults to all
 
83
                            tests)
 
84
      -l, --level           results level filter
 
85
      -f {csv,json,txt,xml}, --format {csv,json,txt,xml}
 
86
                            specify output format
 
87
      -o OUTPUT_FILE, --output OUTPUT_FILE
 
88
                            write report to filename
 
89
      -v, --verbose         show extra information like excluded and included
 
90
                            files
 
91
      -d, --debug           turn on debug mode
 
92
 
 
93
 
 
94
Configuration
 
95
-------------
 
96
The Bandit config file is used to set several things, including:
 
97
 - profiles - defines group of tests which should or shouldn't be run
 
98
 - exclude_dirs - sections of the path, that if matched, will be excluded from
 
99
 scanning
 
100
 - plugin configs - used to tune plugins, for example: by tuning
 
101
 blacklist_imports, you can set which imports should be flagged
 
102
 - other - plugins directory, included file types, shell display
 
103
 colors, etc.
 
104
 
 
105
Bandit requires a config file.  Bandit will use bandit.yaml in the following
 
106
preference order:
 
107
 
 
108
 - Bandit config file specified with -c command line option
 
109
 - bandit.yaml file from current working directory
 
110
 - bandit.yaml file from ~/.config/bandit/
 
111
 - bandit.yaml file in config/ directory of the Bandit package
 
112
 
 
113
 
 
114
Exclusions
 
115
----------
 
116
In the event that a line of code triggers a Bandit issue, but that the line
 
117
has been reviewed and the issue is a false positive or acceptable for some
 
118
other reason, the line can be marked with a '# nosec' and any results
 
119
associated with it will not be reported.
 
120
 
 
121
For example, although this line may cause Bandit to report a potential
 
122
security issue, it will not be reported::
 
123
 
 
124
    self.process = subprocess.Popen('/bin/echo', shell=True)  # nosec
 
125
 
 
126
 
 
127
Vulnerability Tests
 
128
-------------------
 
129
Vulnerability tests or 'plugins' are defined in files in the plugins directory.
 
130
 
 
131
Tests are written in Python and are autodiscovered from the plugins directory.
 
132
Each test can examine one or more type of Python statements.  Tests are marked
 
133
with the types of Python statements they examine (for example: function call,
 
134
string, import, etc).
 
135
 
 
136
Tests are executed by the BanditNodeVisitor object as it visits each node in
 
137
the AST.
 
138
 
 
139
Test results are maintained in the BanditResultStore and aggregated for output
 
140
at the completion of a test run.
 
141
 
 
142
 
 
143
Writing Tests
 
144
-------------
 
145
To write a test:
 
146
 - Identify a vulnerability to build a test for, and create a new file in
 
147
   examples/ that contains one or more cases of that vulnerability.
 
148
 - Consider the vulnerability you're testing for, mark the function with one
 
149
   or more of the appropriate decorators:
 
150
   - @checks('Call')
 
151
   - @checks('Import', 'ImportFrom')
 
152
   - @checks('Str')
 
153
 - Create a new Python source file to contain your test, you can reference
 
154
   existing tests for examples.
 
155
 - The function that you create should take a parameter "context" which is
 
156
   an instance of the context class you can query for information about the
 
157
   current element being examined.  You can also get the raw AST node for
 
158
   more advanced use cases.  Please see the context.py file for more.
 
159
 - Extend your Bandit configuration file as needed to support your new test.
 
160
 - Execute Bandit against the test file you defined in examples/ and ensure
 
161
   that it detects the vulnerability.  Consider variations on how this
 
162
   vulnerability might present itself and extend the example file and the test
 
163
   function accordingly.
 
164
 
 
165
Extending Bandit
 
166
----------------
 
167
 
 
168
Bandit allows users to write and register extensions for checks and formatters.
 
169
Bandit will load plugins from two entry-points:
 
170
 
 
171
- `bandit.formatters`
 
172
- `bandit.plugins`
 
173
 
 
174
Formatters need to accept 4 things:
 
175
 
 
176
- `result_store`: An instance of `bandit.core.BanditResultStore`
 
177
- `file_list`: The list of files which were inspected in the scope
 
178
- `scores`: The scores awarded to each file in the scope
 
179
- `excluded_files`: The list of files that were excluded from the scope
 
180
 
 
181
Plugins tend to take advantage of the `bandit.checks` decorator which allows
 
182
the author to register a check for a particular type of AST node. For example,
 
183
 
 
184
    @bandit.checks('Call')
 
185
    def prohibit_unsafe_deserialization(context):
 
186
        if 'unsafe_load' in context.call_function_name_qual:
 
187
            return bandit.Issue(
 
188
                severity=bandit.HIGH,
 
189
                confidence=bandit.HIGH,
 
190
                text="Unsafe deserialization detected."
 
191
            )
 
192
 
 
193
To register your plugin, you have two options:
 
194
 
 
195
1. If you're using setuptools directly, add something like the following to
 
196
   your `setup` call:
 
197
 
 
198
        # If you have an imaginary bson formatter in the bandit_bson module
 
199
        # and a function called `formatter`.
 
200
        entry_points={'bandit.formatters': ['bson = bandit_bson:formatter']}
 
201
        # Or a check for using mako templates in bandit_mako that
 
202
        entry_points={'bandit.plugins': ['mako = bandit_mako']}
 
203
 
 
204
2. If you're using pbr, add something like the following to your `setup.cfg`
 
205
   file:
 
206
 
 
207
        [entry_points]
 
208
        bandit.formatters =
 
209
            bson = bandit_bson:formatter
 
210
        bandit.plugins =
 
211
            mako = bandit_mako
 
212
 
 
213
Contributing
 
214
------------
 
215
Contributions to Bandit are always welcome!  We can be found on #openstack-security
 
216
on Freenode IRC.
 
217
 
 
218
The best way to get started with Bandit is to grab the source:
 
219
 
 
220
    git clone https://git.openstack.org/stackforge/bandit.git
 
221
 
 
222
You can test any changes with tox:
 
223
 
 
224
    pip install tox
 
225
    tox -e pep8
 
226
    tox -e py27
 
227
    tox -e py34
 
228
    tox -e cover
 
229
 
 
230
 
 
231
Under Which Version of Python Should I Install Bandit?
 
232
------------------------------------------------------
 
233
The answer to this question depends on the project(s) you will be running
 
234
Bandit against. If your project is only compatible with Python 2.7, you
 
235
should install Bandit to run under Python 2.7. If your project is only
 
236
compatible with Python 3.4, then use 3.4. If your project supports both, you
 
237
*could* run Bandit with both versions but you don't have to.
 
238
 
 
239
Bandit uses the `ast` module from Python's standard library in order to
 
240
analyze your Python code. The `ast` module is only able to parse Python code
 
241
that is valid in the version of the interpreter from which it is imported. In
 
242
other words, if you try to use Python 2.7's `ast` module to parse code written
 
243
for 3.4 that uses, for example, `yield from` with asyncio, then you'll have
 
244
syntax errors that will prevent Bandit from working properly. Alternatively,
 
245
if you are relying on 2.7's octal notation of `0777` then you'll have a syntax
 
246
error if you run Bandit on 3.4.
 
247
 
 
248
 
 
249
References
 
250
==========
 
251
 
 
252
Bandit wiki: https://wiki.openstack.org/wiki/Security/Projects/Bandit
 
253
 
 
254
Python AST module documentation: https://docs.python.org/2/library/ast.html
 
255
 
 
256
Green Tree Snakes - the missing Python AST docs:
 
257
http://greentreesnakes.readthedocs.org/en/latest/
 
258
 
 
259
Documentation of the various types of AST nodes that Bandit currently covers
 
260
or could be extended to cover:
 
261
http://greentreesnakes.readthedocs.org/en/latest/nodes.html