bandit icon indicating copy to clipboard operation
bandit copied to clipboard

#nosec not working for multi-line strings in python 3.8

Open Stannislav opened this issue 4 years ago • 13 comments

The Problem

Starting python3.8 adding #nosec after a multi-line string has no effect. This was not the case in python 3.6 (and I think also 3.7)

How to Reproduce

Prepare two sample python source files

success.py:

table = "my_table"
query = f"SELECT * FROM {table}"  # nosec

fail.py

table = "my_table"
query = f"""
SELECT *
FROM {table}
"""  # nosec

Set up python3.6 and python3.8 environments

$ python3.6 -m venv venv36
$ python3.8 -m venv venv38

Run bandit using python3.6

$ source ./venv36/bin/activate
$ pip install bandit==1.6.3

Run bandit on success.py -- no issues.

$ bandit success.py
[main]  INFO    profile include tests: None
[main]  INFO    profile exclude tests: None
[main]  INFO    cli include tests: None
[main]  INFO    cli exclude tests: None
[main]  INFO    running on Python 3.6.12
[node_visitor]  INFO    Unable to find qualified name for module: success.py
Run started:2020-12-07 14:35:50.699373

Test results:
        No issues identified.

Code scanned:
        Total lines of code: 2
        Total lines skipped (#nosec): 1

Run metrics:
        Total issues (by severity):
                Undefined: 0.0
                Low: 0.0
                Medium: 0.0
                High: 0.0
        Total issues (by confidence):
                Undefined: 0.0
                Low: 0.0
                Medium: 0.0
                High: 0.0
Files skipped (0):

Run bandit on fail.py -- no issues either.

$ bandit fail.py
[main]  INFO    profile include tests: None
[main]  INFO    profile exclude tests: None
[main]  INFO    cli include tests: None
[main]  INFO    cli exclude tests: None
[main]  INFO    running on Python 3.6.12
[node_visitor]  INFO    Unable to find qualified name for module: fail.py
Run started:2020-12-07 14:25:36.277457

Test results:
        No issues identified.

Code scanned:
        Total lines of code: 5
        Total lines skipped (#nosec): 1

Run metrics:
        Total issues (by severity):
                Undefined: 0.0
                Low: 0.0
                Medium: 0.0
                High: 0.0
        Total issues (by confidence):
                Undefined: 0.0
                Low: 0.0
                Medium: 0.0
                High: 0.0
Files skipped (0):
$ deactivate

Run bandit in python3.8

$ source ./venv38/bin/activate
$ pip install bandit==1.6.3

Run bandit on success.py -- no issues.

$ bandit success.py 
[main]  INFO    profile include tests: None
[main]  INFO    profile exclude tests: None
[main]  INFO    cli include tests: None
[main]  INFO    cli exclude tests: None
[main]  INFO    running on Python 3.8.6
[node_visitor]  INFO    Unable to find qualified name for module: success.py
Run started:2020-12-07 14:37:02.909155

Test results:
        No issues identified.

Code scanned:
        Total lines of code: 2
        Total lines skipped (#nosec): 1

Run metrics:
        Total issues (by severity):
                Undefined: 0.0
                Low: 0.0
                Medium: 0.0
                High: 0.0
        Total issues (by confidence):
                Undefined: 0.0
                Low: 0.0
                Medium: 0.0
                High: 0.0
Files skipped (0):

Run bandit on fail.py -- one issue is reported.

$ bandit fail.py           
[main]  INFO    profile include tests: None
[main]  INFO    profile exclude tests: None
[main]  INFO    cli include tests: None
[main]  INFO    cli exclude tests: None
[main]  INFO    running on Python 3.8.6
[node_visitor]  INFO    Unable to find qualified name for module: fail.py
Run started:2020-12-07 14:26:41.664117

Test results:
>> Issue: [B608:hardcoded_sql_expressions] Possible SQL injection vector through string-based query construction.
   Severity: Medium   Confidence: Low
   Location: fail.py:2
   More Info: https://bandit.readthedocs.io/en/latest/plugins/b608_hardcoded_sql_expressions.html
1       table = "my_table"
2       query = f"""
3       SELECT *
4       FROM {table}
5       """  # nosec

--------------------------------------------------

Code scanned:
        Total lines of code: 5
        Total lines skipped (#nosec): 0

Run metrics:
        Total issues (by severity):
                Undefined: 0.0
                Low: 0.0
                Medium: 1.0
                High: 0.0
        Total issues (by confidence):
                Undefined: 0.0
                Low: 1.0
                Medium: 0.0
                High: 0.0
Files skipped (0):
$ deactivate

Expected Behaviour

The #nosec clause should work both in python3.6 and python3.8. In this concrete example bandit fail.py should not fail in python3.8.

Bandit Version

On python3.6:

$ bandit --version
bandit 1.6.3
  python version = 3.6.12 (default, Nov  6 2020, 13:08:49) [GCC Apple LLVM 12.0.0 (clang-1200.0.32.21)]

On python3.8

$ bandit --version
bandit 1.6.3
  python version = 3.8.6 (default, Nov  6 2020, 13:26:24) [Clang 12.0.0 (clang-1200.0.32.21)]

Stannislav avatar Dec 07 '20 14:12 Stannislav

Confirming it's also a problem on 3.9.7 on Windows

C:\test> bandit --version
bandit 1.7.0
  python version = 3.9.7 (tags/v3.9.7:1016ef3, Aug 30 2021, 20:19:38) [MSC v.1929 64 bit (AMD64)]

Peterl777 avatar Sep 16 '21 07:09 Peterl777

Confirmed with 3.8 & 3.9 on Linux.

It looks like the line number of the error is being reported as the first line of the multi line string (where we cannot put a nosec comment) whereas before it was the last line.

Using the report above as an example:

Test results:
>> Issue: [B608:hardcoded_sql_expressions] Possible SQL injection vector through string-based query construction.
   Severity: Medium   Confidence: Low
   Location: fail.py:2
   More Info: https://bandit.readthedocs.io/en/latest/plugins/b608_hardcoded_sql_expressions.html
1       table = "my_table"
2       query = f"""
3       SELECT *
4       FROM {table}
5       """  # nosec

The error is reported on line 2:

Location: fail.py:2

oliver-sanders avatar Oct 04 '21 13:10 oliver-sanders

My workaround:

"""# nosec"""; query = f"""
SELECT *
FROM {table}
"""

ryan-gontarek avatar Jan 24 '22 18:01 ryan-gontarek

My workaround:

"""# nosec"""; query = f"""
SELECT *
FROM {table}
"""

very nice. you also don't need that comma.

"""# nosec"""
query = f""" 
select...
""""

works too.

waltertschwe avatar Feb 08 '22 22:02 waltertschwe

A black compatible workaround

        # fmt: off
        query = (  # nosec
            f"""
            SELECT something,
            WHERE foobar = {bar} 
            """
        )
        # fmt: on

Still please fix. Especially using black this can be a pain in the ass ;-)

CarliJoy avatar Feb 10 '22 16:02 CarliJoy

I also just experienced this in my pipeline. Checked with python:

  • 3.7.12 working
  • 3.8.10 not working
  • 3.9.10 not working

DrakezulsMinimalism avatar Feb 28 '22 16:02 DrakezulsMinimalism

I'm not able to get any of the mentioned workarounds to work. Only thing that worked for me for now was downgrading back to bandit 1.6.2.

michiel-nwa avatar Mar 04 '22 09:03 michiel-nwa

I think this can be closed now. It is fixed by the linked pull request.

kfrydel avatar Mar 03 '23 07:03 kfrydel

I have this problem with bandit 1.7.5 and Python 3.10.9. I'm using this version of the workaround.

                connection,
                sql=(  # nosec
                    f"""

nevdelap avatar Mar 31 '23 04:03 nevdelap

Can you share the whole piece of code (or minimal example) for which the bandit does not behave as expected?

kfrydel avatar Mar 31 '23 06:03 kfrydel

@nevdelap after switching to the latest bandit version I had to move SQL nosec comments to the end of multiline strings before:

sql(
    f"""  # nosec
    some SQL query
    """,
)

after:

sql(
    f"""
    some SQL query
    """,  # nosec
)

GeyseR avatar Mar 31 '23 08:03 GeyseR

Thanks @GeyseR. That works. All good.

nevdelap avatar Mar 31 '23 09:03 nevdelap

A black compatible workaround

        # fmt: off
        query = (  # nosec
            f"""
            SELECT something,
            WHERE foobar = {bar} 
            """
        )
        # fmt: on

Thank you so much @CarliJoy!

rikkiprince avatar Mar 19 '24 17:03 rikkiprince