|
| 1 | +# Contributing to Bandit |
| 2 | +Thanks for considering to take part in the improvement of Bandit project, contributions are always welcome! |
| 3 | +Here are guidelines and rules that can be helpful if you plan to want to get involved in the project. |
| 4 | + |
| 5 | +#### Table Of Contents |
| 6 | +[Code of Conduct](#code-of-conduct) |
| 7 | + |
| 8 | +[How Can I Contribute?](#how-can-i-contribute) |
| 9 | + * [Reporting Bugs](#reporting-bugs) |
| 10 | + * [Suggesting Enhancements](#suggesting-enhancements) |
| 11 | + * [Your First Code Contribution](#your-first-code-contribution) |
| 12 | + * [Pull Requests](#pull-requests) |
| 13 | + * [Commit Message Guidelines](#commit-message-guidelines) |
| 14 | + * [Squash Commits](#squash-commits) |
| 15 | + * [Things You Should Know Before Getting Started](#things-you-should-know-before-getting-started) |
| 16 | + |
| 17 | +## Code of Conduct |
| 18 | +Everyone who participates in this project is governed by [Bandit Code of Conduct](https://github.com/Glyphack/bandit/blob/master/CODE_OF_CONDUCT.md#contributor-covenant-code-of-conduct). |
| 19 | + |
| 20 | +## Reporting Bugs |
| 21 | +If you encountered a bug and want to let us know use [GitHub issues](https://guides.github.com/features/issues/). |
| 22 | + |
| 23 | +**Before submitting a new issue** you might want to check [existsing issue](https://github.com/PyCQA/bandit/issues) to know if there is already a reported issue and the issue is still open |
| 24 | +in that case you can add a comment to the existing issue instead of creating a new one. |
| 25 | + |
| 26 | +### Submitting your first issue |
| 27 | +We encourage using a issue template to improve quality of reported issues, however if you feel limited by the template please format the issue in a manner that best allows you to describe the problem. |
| 28 | +Navigate to the issues tab and select `new issue`, then select the **bug report** template and fill out the form, |
| 29 | +to submit a good bug report keep in mind that: |
| 30 | +* Use a descriptive title so other people can understand what the issue is about. |
| 31 | +* Be specific about the details, for e.g. what command did you use, what version of Bandit did you use or in what |
| 32 | +environment you observed the bug(CI or development) and other things that may be useful. |
| 33 | + |
| 34 | +## Suggesting Enhancements |
| 35 | +If you want to suggest and enhancement open a new issue and use the **feature request** template. |
| 36 | + |
| 37 | +**Before submitting an enhancement** please check for existing [feature requests](https://github.com/PyCQA/bandit/issues?q=is%3Aopen+is%3Aissue+label%3Aenhancement) |
| 38 | +and make sure the feature does not exist or requested already. |
| 39 | + |
| 40 | +Useful things to point out in your feature request: |
| 41 | +* Explain your feature request in a way that everyone can understand maybe with an example from another project or pictures |
| 42 | +* Please try to explain how this feature can help Bandit project |
| 43 | + |
| 44 | +## Your First Code Contribution |
| 45 | +You can start contributing to Bandit project by picking [bug issues](https://github.com/PyCQA/bandit/issues?q=is%3Aopen+is%3Aissue+label%3Abug) |
| 46 | +These issues can be easier to resolve rather than a feature request and can get you up and running with the code base. |
| 47 | + |
| 48 | +## Pull Requests |
| 49 | +The best way to get started with Bandit is to grab the source: |
| 50 | + |
| 51 | +`git clone https://github.com/PyCQA/bandit.git` |
| 52 | + |
| 53 | +Create you own branch to start writing code: |
| 54 | +```shell script |
| 55 | +git checkout -b mybranch |
| 56 | +git push origin mybranch |
| 57 | +``` |
| 58 | +You can test any changes with tox: |
| 59 | + |
| 60 | +``` |
| 61 | +pip install tox |
| 62 | +tox -e pep8 |
| 63 | +tox -e py27 |
| 64 | +tox -e py35 |
| 65 | +tox -e docs |
| 66 | +tox -e cover |
| 67 | +``` |
| 68 | +If everything is done, proceed with [opening a new pull request](https://help.github.com/en/desktop/contributing-to-projects/creating-a-pull-request) |
| 69 | + |
| 70 | +### Commit Message Guidelines |
| 71 | + |
| 72 | +We follow the commit formatting recommendations found on [Chris Beams' How to Write a Git Commit Message article](https://chris.beams.io/posts/git-commit/). |
| 73 | + |
| 74 | +Well formed commit messages not only help reviewers understand the nature of |
| 75 | +the Pull Request, but also assists the release process where commit messages |
| 76 | +are used to generate release notes. |
| 77 | + |
| 78 | +A good example of a commit message would be as follows: |
| 79 | + |
| 80 | +``` |
| 81 | +Summarize changes in around 50 characters or less |
| 82 | +
|
| 83 | +More detailed explanatory text, if necessary. Wrap it to about 72 |
| 84 | +characters or so. In some contexts, the first line is treated as the |
| 85 | +subject of the commit and the rest of the text as the body. The |
| 86 | +blank line separating the summary from the body is critical (unless |
| 87 | +you omit the body entirely); various tools like `log`, `shortlog` |
| 88 | +and `rebase` can get confused if you run the two together. |
| 89 | +
|
| 90 | +Explain the problem that this commit is solving. Focus on why you |
| 91 | +are making this change as opposed to how (the code explains that). |
| 92 | +Are there side effects or other unintuitive consequences of this |
| 93 | +change? Here's the place to explain them. |
| 94 | +
|
| 95 | +Further paragraphs come after blank lines. |
| 96 | +
|
| 97 | + - Bullet points are okay, too |
| 98 | +
|
| 99 | + - Typically a hyphen or asterisk is used for the bullet, preceded |
| 100 | + by a single space, with blank lines in between, but conventions |
| 101 | + vary here |
| 102 | +
|
| 103 | +If you use an issue tracker, put references to them at the bottom, |
| 104 | +like this: |
| 105 | +
|
| 106 | +Resolves: #123 |
| 107 | +See also: #456, #789 |
| 108 | +``` |
| 109 | + |
| 110 | +Note the `Resolves #123` tag, this references the issue raised and allows us to |
| 111 | +ensure issues are associated and closed when a pull request is merged. |
| 112 | + |
| 113 | +Please refer to [the github help page on message types](https://help.github.com/articles/closing-issues-using-keywords/) |
| 114 | +for a complete list of issue references. |
| 115 | + |
| 116 | +### Squash Commits |
| 117 | + |
| 118 | +Should your pull request consist of more than one commit (perhaps due to |
| 119 | +a change being requested during the review cycle), please perform a git squash |
| 120 | +once a reviewer has approved your pull request. |
| 121 | + |
| 122 | +A squash can be performed as follows. Let's say you have the following commits: |
| 123 | + |
| 124 | + initial commit |
| 125 | + second commit |
| 126 | + final commit |
| 127 | + |
| 128 | +Run the command below with the number set to the total commits you wish to |
| 129 | +squash (in our case 3 commits): |
| 130 | + |
| 131 | + git rebase -i HEAD~3 |
| 132 | + |
| 133 | +You default text editor will then open up and you will see the following:: |
| 134 | + |
| 135 | + pick eb36612 initial commit |
| 136 | + pick 9ac8968 second commit |
| 137 | + pick a760569 final commit |
| 138 | + |
| 139 | + # Rebase eb1429f..a760569 onto eb1429f (3 commands) |
| 140 | + |
| 141 | +We want to rebase on top of our first commit, so we change the other two commits |
| 142 | +to `squash`: |
| 143 | + |
| 144 | + pick eb36612 initial commit |
| 145 | + squash 9ac8968 second commit |
| 146 | + squash a760569 final commit |
| 147 | + |
| 148 | +After this, should you wish to update your commit message to better summarise |
| 149 | +all of your pull request, run: |
| 150 | + |
| 151 | + git commit --amend |
| 152 | + |
| 153 | +You will then need to force push (assuming your initial commit(s) were posted |
| 154 | +to github): |
| 155 | + |
| 156 | + git push origin your-branch --force |
| 157 | + |
| 158 | +## Things You Should Know Before Getting Started |
| 159 | + |
| 160 | +### Vulnerability Tests |
| 161 | +Vulnerability tests or "plugins" are defined in files in the plugins directory. |
| 162 | + |
| 163 | +Tests are written in Python and are autodiscovered from the plugins directory. |
| 164 | +Each test can examine one or more type of Python statements. Tests are marked |
| 165 | +with the types of Python statements they examine (for example: function call, |
| 166 | +string, import, etc). |
| 167 | + |
| 168 | +Tests are executed by the ``BanditNodeVisitor`` object as it visits each node |
| 169 | +in the AST. |
| 170 | + |
| 171 | +Test results are managed in the ``Manager`` and aggregated for |
| 172 | +output at the completion of a test run through the method `output_result` from ``Manager`` instance. |
| 173 | + |
| 174 | +### Writing Tests |
| 175 | +To write a test: |
| 176 | + - Identify a vulnerability to build a test for, and create a new file in |
| 177 | + examples/ that contains one or more cases of that vulnerability. |
| 178 | + - Consider the vulnerability you're testing for, mark the function with one |
| 179 | + or more of the appropriate decorators: |
| 180 | + - @checks('Call') |
| 181 | + - @checks('Import', 'ImportFrom') |
| 182 | + - @checks('Str') |
| 183 | + - Create a new Python source file to contain your test, you can reference |
| 184 | + existing tests for examples. |
| 185 | + - The function that you create should take a parameter "context" which is |
| 186 | + an instance of the context class you can query for information about the |
| 187 | + current element being examined. You can also get the raw AST node for |
| 188 | + more advanced use cases. Please see the context.py file for more. |
| 189 | + - Extend your Bandit configuration file as needed to support your new test. |
| 190 | + - Execute Bandit against the test file you defined in examples/ and ensure |
| 191 | + that it detects the vulnerability. Consider variations on how this |
| 192 | + vulnerability might present itself and extend the example file and the test |
| 193 | + function accordingly. |
| 194 | + |
| 195 | + |
| 196 | +### Extending Bandit |
| 197 | + |
| 198 | +Bandit allows users to write and register extensions for checks and formatters. |
| 199 | +Bandit will load plugins from two entry-points: |
| 200 | + |
| 201 | +- `bandit.formatters` |
| 202 | +- `bandit.plugins` |
| 203 | + |
| 204 | +Formatters need to accept 5 things: |
| 205 | + |
| 206 | +- `manager`: an instance of `bandit manager` |
| 207 | +- `fileobj`: the output file object, which may be sys.stdout |
| 208 | +- `sev_level` : Filtering severity level |
| 209 | +- `conf_level`: Filtering confidence level |
| 210 | +- `lines=-1`: number of lines to report |
| 211 | + |
| 212 | +Plugins tend to take advantage of the `bandit.checks` decorator which allows |
| 213 | +the author to register a check for a particular type of AST node. For example |
| 214 | + |
| 215 | +:: |
| 216 | + |
| 217 | + @bandit.checks('Call') |
| 218 | + def prohibit_unsafe_deserialization(context): |
| 219 | + if 'unsafe_load' in context.call_function_name_qual: |
| 220 | + return bandit.Issue( |
| 221 | + severity=bandit.HIGH, |
| 222 | + confidence=bandit.HIGH, |
| 223 | + text="Unsafe deserialization detected." |
| 224 | + ) |
| 225 | + |
| 226 | +To register your plugin, you have two options: |
| 227 | + |
| 228 | +1. If you're using setuptools directly, add something like the following to |
| 229 | + your ``setup`` call:: |
| 230 | + |
| 231 | + # If you have an imaginary bson formatter in the bandit_bson module |
| 232 | + # and a function called `formatter`. |
| 233 | + entry_points={'bandit.formatters': ['bson = bandit_bson:formatter']} |
| 234 | + # Or a check for using mako templates in bandit_mako that |
| 235 | + entry_points={'bandit.plugins': ['mako = bandit_mako']} |
| 236 | + |
| 237 | +2. If you're using pbr, add something like the following to your `setup.cfg` |
| 238 | + file:: |
| 239 | + |
| 240 | + [entry_points] |
| 241 | + bandit.formatters = |
| 242 | + bson = bandit_bson:formatter |
| 243 | + bandit.plugins = |
| 244 | + mako = bandit_mako |
0 commit comments