bandit icon indicating copy to clipboard operation
bandit copied to clipboard

Add an auto-fix or auto-correct feature

Open ericwb opened this issue 6 years ago • 5 comments

Is your feature request related to a problem? Please describe. It's nice that Bandit flags lines of code that require attention, but it would be even more valuable to suggest fixes for problem lines. Other linters such as ESLint provide a --fix command line option to automatically fix problems it finds.

See https://eslint.org/docs/user-guide/command-line-interface#options

Describe the solution you'd like A start might be that Bandit includes another field in the output data called suggested fix or something. It would include the modified line of code it found to be wrong with the proposed solution.

For example, if the yaml_load plugin found a case of yaml.load(), it would replace with yaml.load(Loader=yaml.SafeLoader).

Each plugin would need to handle fixes it could address.

Describe alternatives you've considered n/a

Additional context https://developer.ibm.com/articles/auto-fix-and-format-your-javascript-with-eslint/

ericwb avatar Dec 19 '18 02:12 ericwb

Nice idea. Would it give a generic example, or try to amend and suggest the flagged line of code from the project being scanned?

lukehinds avatar Dec 19 '18 18:12 lukehinds

@lukehinds Yeah, I was thinking Bandit would output a new field of the suggested fix. But it could also have a command line option to actually make the changes in the file automatically. Similar to what ESLint offers.

ericwb avatar Dec 19 '18 23:12 ericwb

I think this is a great idea. Maybe could be added on the Issue class a new optional field.

ehooo avatar Mar 14 '19 23:03 ehooo

I investigated this some. The ast includes a NodeTransformer that enables rewriting the tree. And in Python 3.9 and later, ast can do an unparse in addition to parse. So in effect, you can create a suggested fix and even automatically fix the code.

However, Python's ast is not a CST (comcrete syntax tree) and therefore doesn't include things like trailing comments. The undesirable effect is that suggested code wouldn't retain these elements.

We could look at switching Bandit to use something like libcst. But this would be a major change to the base parsing mechanism of Bandit and adds another dependency.

ericwb avatar Feb 13 '22 02:02 ericwb

Here's a short example using libcst to auto-correct a problem in code, all while preserving the comments.

import libcst as cst

code = '''
from paramiko import client

class foo:
    def test(self):
        if True:
            ssh_client = client.SSHClient()
            # test test test
            ssh_client.set_missing_host_key_policy(client.AutoAddPolicy) # comment test
'''

class PolicyFix(cst.CSTTransformer):
    def leave_Call(self, original_node: cst.Call, updated_node: cst.Call) -> cst.Call:
        if (cst.ensure_type(original_node.func, cst.Attribute)
            and original_node.func.attr.value == "set_missing_host_key_policy"
            and original_node.args[0].value.attr.value == "AutoAddPolicy"
        ):
            return updated_node.with_deep_changes(
                old_node=updated_node.args[0].value,
                attr=cst.Name("RejectPolicy")
            )
        else:
            return original_node


tree = cst.parse_module(code)
new_tree = tree.visit(PolicyFix())
print(new_tree.code)

ericwb avatar Feb 13 '22 17:02 ericwb