What is the way to ignore/skip some issues from python bandit security issues report?

53k views Asked by At

I've got a bunch of django_mark_safe errors

>> Issue: [B703:django_mark_safe] Potential XSS on mark_safe function.
   Severity: Medium   Confidence: High
   Location: ...
   More Info: https://bandit.readthedocs.io/en/latest/plugins/b703_django_mark_safe.html
54 return mark_safe(f'<a href="{url}" target="_blank">{title}</a>')

>> Issue: [B308:blacklist] Use of mark_safe() may expose cross-site scripting vulnerabilities and should be reviewed.
   Severity: Medium   Confidence: High
   Location: ...
   More Info: https://bandit.readthedocs.io/en/latest/blacklists/blacklist_calls.html#b308-mark-safe
54 return mark_safe(f'<a href="{url}" target="_blank">{title}</a>')

And I'm curious if there is a way to skip or ignore such lines? I understand that using mark_safe could be dangerous, but what if I want to take the risk? For example this method is the only way to display custom link in Django admin, so I don't know any other option how to do it without mark_safe

5

There are 5 answers

0
ramusus On BEST ANSWER

I've got an answer here:

Two ways:

  1. You can skip the B703 and B308 using the --skip argument to the command line.
  2. Or you can affix a comment # nosec on the line to skip.

https://bandit.readthedocs.io/en/latest/config.html#exclusions

0
rafaljusiak On

Just to complete the topic - in my case I had to rid of B322: input rule, and didn't wanted to write # nosec each time I found this problem in the code, or to always execute Bandit with a --skip flag.

So if you want to omit a certain rule for whole solution, you can create a .bandit file in the root of your project. Then you can write which rules should be skipped every time, for example:

[bandit]
skips: B322

And then Bandit will skip this check by default without need to give additional comments in the code.

2
JL Peyret On

Heads up for annotating multilines with # nosec:

given:

li_without_nosec = [
    "select * from %s where 1 = 1 "
    % "foo"
]

li_nosec_at_start_works = [  # nosec - ✅ and you can put a comment
    "select * from %s where 1 = 1 "
    % "foo"
]  

# nosec - there's an enhancement request to marker above line
li_nosec_on_top_doesntwork = [  
    "select * from %s where 1 = 1 "
    % "foo"
]  

li_nosec_at_end_doesntwork = [
    "select * from %s where 1 = 1 "
    % "foo"
]  # nosec 

output:

>> Issue: [B608:hardcoded_sql_expressions] Possible SQL injection vector through string-based query construction.
   Severity: Medium   Confidence: Low
   Location: test.py:3
   More Info: https://bandit.readthedocs.io/en/latest/plugins/b608_hardcoded_sql_expressions.html
2   li_without_nosec = [
3       "select * from %s where 1 = 1 "
4       % "foo"
5   ]

--------------------------------------------------
>> Issue: [B608:hardcoded_sql_expressions] Possible SQL injection vector through string-based query construction.
   Severity: Medium   Confidence: Low
   Location: test.py:15
   More Info: https://bandit.readthedocs.io/en/latest/plugins/b608_hardcoded_sql_expressions.html
14  li_nosec_on_top_doesntwork = [
15      "select * from %s where 1 = 1 "
16      % "foo"
17  ]

--------------------------------------------------
>> Issue: [B608:hardcoded_sql_expressions] Possible SQL injection vector through string-based query construction.
   Severity: Medium   Confidence: Low
   Location: test.py:21
   More Info: https://bandit.readthedocs.io/en/latest/plugins/b608_hardcoded_sql_expressions.html
20  li_nosec_at_end_doesntwork = [
21      "select * from %s where 1 = 1 "
22      % "foo"
23  ]  # nosec

Black

Here's hoping that black won't get involved and restructure the lines, moving the # nosec around.

so much for hope... black does move things around, just like it does with pylint directives, whenever the line length becomes too long. At which point # nosec ends up at the end.

You can either proactively break up the line and position # nosec at the first one. Or you can just wait out black and adjust if needed.

1
Noam Nol On

You can config Bandit with .bandit INI file (only if it is invoked with -r option):

[bandit]
tests = B101,B102,B301

Or with pyproject.toml file:

[tool.bandit]
tests = ["B201", "B301"]
skips = ["B101", "B601"]

Or with yaml file:

skips: ['B101', 'B601']
assert_used:
  skips: ["*/test_*.py", "*/test_*.py"]

See https://bandit.readthedocs.io/en/latest/config.html

0
allexiusw On

If you want to apply the rule in a local piece of your code you can do something like the following:

# this is my very basic python script

def foo():
   do_something_unsecure()  # nosec B703, B308

In that way you will skip those validations just in that line. In real work it can be probably the most appropriated way to skip some rules.