Skip to content

Commit

Permalink
Add CWE mappings to bandit issues and update formatters accordingly.
Browse files Browse the repository at this point in the history
  • Loading branch information
julianthome committed May 14, 2020
1 parent 59cd94e commit e812ae3
Show file tree
Hide file tree
Showing 41 changed files with 116 additions and 52 deletions.
2 changes: 1 addition & 1 deletion bandit/core/blacklisting.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

def report_issue(check, name):
return issue.Issue(
severity=check.get('level', 'MEDIUM'), confidence='HIGH',
severity=check.get('level', 'MEDIUM'), cwe=0, confidence='HIGH',
text=check['message'].replace('{name}', name),
ident=name, test_id=check.get("id", 'LEGACY'))

Expand Down
21 changes: 13 additions & 8 deletions bandit/core/issue.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@


class Issue(object):
def __init__(self, severity, confidence=constants.CONFIDENCE_DEFAULT,
def __init__(self, severity, cwe,
confidence=constants.CONFIDENCE_DEFAULT,
text="", ident=None, lineno=None, test_id=""):
self.severity = severity
self.cwe = cwe
self.confidence = confidence
if isinstance(text, bytes):
text = text.decode('utf-8')
Expand All @@ -30,16 +32,17 @@ def __init__(self, severity, confidence=constants.CONFIDENCE_DEFAULT,
self.linerange = []

def __str__(self):
return ("Issue: '%s' from %s:%s: Severity: %s Confidence: "
return ("Issue: '%s' from %s:%s: CWE: %i, Severity: %s Confidence: "
"%s at %s:%i") % (self.text, self.test_id,
(self.ident or self.test), self.severity,
self.confidence, self.fname, self.lineno)
(self.ident or self.test), self.cwe,
self.severity, self.confidence, self.fname,
self.lineno)

def __eq__(self, other):
# if the issue text, severity, confidence, and filename match, it's
# the same issue from our perspective
match_types = ['text', 'severity', 'confidence', 'fname', 'test',
'test_id']
match_types = ['text', 'severity', 'cwe', 'confidence', 'fname',
'test', 'test_id']
return all(getattr(self, field) == getattr(other, field)
for field in match_types)

Expand Down Expand Up @@ -101,11 +104,12 @@ def as_dict(self, with_code=True):
'test_name': self.test,
'test_id': self.test_id,
'issue_severity': self.severity,
'issue_cwe': self.cwe,
'issue_confidence': self.confidence,
'issue_text': self.text.encode('utf-8').decode('utf-8'),
'line_number': self.lineno,
'line_range': self.linerange,
}
}

if with_code:
out['code'] = self.get_code()
Expand All @@ -115,6 +119,7 @@ def from_dict(self, data, with_code=True):
self.code = data["code"]
self.fname = data["filename"]
self.severity = data["issue_severity"]
self.cwe = int(data["issue_cwe"])
self.confidence = data["issue_confidence"]
self.text = data["issue_text"]
self.test = data["test_name"]
Expand All @@ -124,6 +129,6 @@ def from_dict(self, data, with_code=True):


def issue_from_dict(data):
i = Issue(severity=data["issue_severity"])
i = Issue(severity=data["issue_severity"], cwe=int(data["issue_cwe"]))
i.from_dict(data)
return i
1 change: 1 addition & 0 deletions bandit/formatters/csv.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ def report(manager, fileobj, sev_level, conf_level, lines=-1):
'test_name',
'test_id',
'issue_severity',
'issue_cwe',
'issue_confidence',
'issue_text',
'line_number',
Expand Down
2 changes: 2 additions & 0 deletions bandit/formatters/html.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ def report(manager, fileobj, sev_level, conf_level, lines=-1):
<b>{test_name}: </b> {test_text}<br>
<b>Test ID:</b> {test_id}<br>
<b>Severity: </b>{severity}<br>
<b>CWE: </b>{cwe}<br>
<b>Confidence: </b>{confidence}<br>
<b>File: </b><a href="{path}" target="_blank">{path}</a> <br>
<b>More info: </b><a href="{url}" target="_blank">{url}</a><br>
Expand Down Expand Up @@ -360,6 +361,7 @@ def report(manager, fileobj, sev_level, conf_level, lines=-1):
test_id=issue.test_id,
test_text=issue.text,
severity=issue.severity,
cwe=issue.cwe,
confidence=issue.confidence,
path=issue.fname, code=code,
candidates=candidates,
Expand Down
10 changes: 6 additions & 4 deletions bandit/formatters/screen.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,12 @@ def _output_issue_str(issue, indent, show_lineno=True, show_code=True,
# returns a list of lines that should be added to the existing lines list
bits = []
bits.append("%s%s>> Issue: [%s:%s] %s" % (
indent, COLOR[issue.severity], issue.test_id, issue.test, issue.text))
indent, COLOR[issue.severity], issue.test_id, issue.test,
issue.text))

bits.append("%s Severity: %s Confidence: %s" % (
indent, issue.severity.capitalize(), issue.confidence.capitalize()))
bits.append("%s Severity: %s CWE: %i Confidence: %s" % (
indent, issue.severity.capitalize(), issue.cwe,
issue.confidence.capitalize()))

bits.append("%s Location: %s:%s" % (
indent, issue.fname,
Expand All @@ -110,7 +112,7 @@ def _output_issue_str(issue, indent, show_lineno=True, show_code=True,
indent, docs_utils.get_url(issue.test_id), COLOR['DEFAULT']))

if show_code:
bits.extend([indent + l for l in
bits.extend([indent + x for x in
issue.get_code(lines, True).split('\n')])

return '\n'.join([bit for bit in bits])
Expand Down
7 changes: 4 additions & 3 deletions bandit/formatters/text.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,9 @@ def _output_issue_str(issue, indent, show_lineno=True, show_code=True,
bits.append("%s>> Issue: [%s:%s] %s" % (
indent, issue.test_id, issue.test, issue.text))

bits.append("%s Severity: %s Confidence: %s" % (
indent, issue.severity.capitalize(), issue.confidence.capitalize()))
bits.append("%s Severity: %s CWE: %i Confidence: %s" % (
indent, issue.severity.capitalize(), issue.cwe,
issue.confidence.capitalize()))

bits.append("%s Location: %s:%s" % (
indent, issue.fname, issue.lineno if show_lineno else ""))
Expand All @@ -83,7 +84,7 @@ def _output_issue_str(issue, indent, show_lineno=True, show_code=True,
indent, docs_utils.get_url(issue.test_id)))

if show_code:
bits.extend([indent + l for l in
bits.extend([indent + x for x in
issue.get_code(lines, True).split('\n')])

return '\n'.join([bit for bit in bits])
Expand Down
8 changes: 5 additions & 3 deletions bandit/formatters/xml.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,11 @@ def report(manager, fileobj, sev_level, conf_level, lines=-1):
testcase = ET.SubElement(root, 'testcase',
classname=issue.fname, name=test)

text = 'Test ID: %s Severity: %s Confidence: %s\n%s\nLocation %s:%s'
text = text % (issue.test_id, issue.severity, issue.confidence,
issue.text, issue.fname, issue.lineno)
text = 'Test ID: %s Severity: %s CWE: %s ' \
'Confidence: %s\n%s\nLocation %s:%s'
text = text % (issue.test_id, issue.severity, issue.cwe,
issue.confidence, issue.text, issue.fname,
issue.lineno)
ET.SubElement(testcase, 'error',
more_info=docs_utils.get_url(issue.test_id),
type=issue.severity,
Expand Down
1 change: 1 addition & 0 deletions bandit/plugins/app_debug.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ def flask_debug_true(context):
if context.check_call_arg_value('debug', 'True'):
return bandit.Issue(
severity=bandit.HIGH,
cwe=94,
confidence=bandit.MEDIUM,
text="A Flask app appears to be run with debug=True, "
"which exposes the Werkzeug debugger and allows "
Expand Down
1 change: 1 addition & 0 deletions bandit/plugins/asserts.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
def assert_used(context):
return bandit.Issue(
severity=bandit.LOW,
cwe=703,
confidence=bandit.HIGH,
text=("Use of assert detected. The enclosed code "
"will be removed when compiling to optimised byte code.")
Expand Down
1 change: 1 addition & 0 deletions bandit/plugins/crypto_request_no_cert_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ def request_with_no_cert_validation(context):
if context.check_call_arg_value('verify', 'False'):
issue = bandit.Issue(
severity=bandit.HIGH,
cwe=295,
confidence=bandit.HIGH,
text="Requests call with verify=False disabling SSL "
"certificate checks, security issue.",
Expand Down
2 changes: 2 additions & 0 deletions bandit/plugins/django_sql_injection.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ def django_extra_used(context):
if insecure:
return bandit.Issue(
severity=bandit.MEDIUM,
cwe=89,
confidence=bandit.MEDIUM,
text=description
)
Expand All @@ -102,6 +103,7 @@ def django_rawsql_used(context):
if not isinstance(sql, ast.Str):
return bandit.Issue(
severity=bandit.MEDIUM,
cwe=89,
confidence=bandit.MEDIUM,
text=description
)
1 change: 1 addition & 0 deletions bandit/plugins/django_xss.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ def check_risk(node):
if not secure:
return bandit.Issue(
severity=bandit.MEDIUM,
cwe=80,
confidence=bandit.HIGH,
text=description
)
Expand Down
1 change: 1 addition & 0 deletions bandit/plugins/exec.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
def exec_issue():
return bandit.Issue(
severity=bandit.MEDIUM,
cwe=78,
confidence=bandit.HIGH,
text="Use of exec detected."
)
Expand Down
1 change: 1 addition & 0 deletions bandit/plugins/general_bad_file_permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ def set_bad_file_permissions(context):
filename = 'NOT PARSED'
return bandit.Issue(
severity=sev_level,
cwe=78,
confidence=bandit.HIGH,
text="Chmod setting a permissive mask %s on file (%s)." %
(oct(mode), filename)
Expand Down
1 change: 1 addition & 0 deletions bandit/plugins/general_bind_all_interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ def hardcoded_bind_all_interfaces(context):
if context.string_val == '0.0.0.0':
return bandit.Issue(
severity=bandit.MEDIUM,
cwe=605,
confidence=bandit.MEDIUM,
text="Possible binding to all interfaces."
)
1 change: 1 addition & 0 deletions bandit/plugins/general_hardcoded_password.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
def _report(value):
return bandit.Issue(
severity=bandit.LOW,
cwe=259,
confidence=bandit.MEDIUM,
text=("Possible hardcoded password: '%s'" % value))

Expand Down
1 change: 1 addition & 0 deletions bandit/plugins/general_hardcoded_tmp.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ def hardcoded_tmp_directory(context, config):
if any(context.string_val.startswith(s) for s in tmp_dirs):
return bandit.Issue(
severity=bandit.MEDIUM,
cwe=377,
confidence=bandit.MEDIUM,
text="Probable insecure usage of temp file/directory."
)
1 change: 1 addition & 0 deletions bandit/plugins/hashlib_new_insecure_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ def hashlib_new(context):
name.lower() in ('md4', 'md5', 'sha', 'sha1')):
return bandit.Issue(
severity=bandit.MEDIUM,
cwe=327,
confidence=bandit.HIGH,
text="Use of insecure MD4 or MD5 hash function.",
lineno=context.node.lineno,
Expand Down
1 change: 1 addition & 0 deletions bandit/plugins/injection_paramiko.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,6 @@ def paramiko_calls(context):
if context.is_module_imported_like(module):
if context.call_function_name in ['exec_command']:
return bandit.Issue(severity=bandit.MEDIUM,
cwe=78,
confidence=bandit.MEDIUM,
text=issue_text)
8 changes: 8 additions & 0 deletions bandit/plugins/injection_shell.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ def subprocess_popen_with_shell_equals_true(context, config):
if sev == bandit.LOW:
return bandit.Issue(
severity=bandit.LOW,
cwe=78,
confidence=bandit.HIGH,
text='subprocess call with shell=True seems safe, but '
'may be changed in the future, consider '
Expand All @@ -208,6 +209,7 @@ def subprocess_popen_with_shell_equals_true(context, config):
else:
return bandit.Issue(
severity=bandit.HIGH,
cwe=78,
confidence=bandit.HIGH,
text='subprocess call with shell=True identified, '
'security issue.',
Expand Down Expand Up @@ -287,6 +289,7 @@ def subprocess_without_shell_equals_true(context, config):
if not has_shell(context):
return bandit.Issue(
severity=bandit.LOW,
cwe=78,
confidence=bandit.HIGH,
text='subprocess call - check for execution of untrusted '
'input.',
Expand Down Expand Up @@ -365,6 +368,7 @@ def any_other_function_with_shell_equals_true(context, config):
if has_shell(context):
return bandit.Issue(
severity=bandit.MEDIUM,
cwe=78,
confidence=bandit.LOW,
text='Function call with shell=True parameter identified, '
'possible security issue.',
Expand Down Expand Up @@ -451,6 +455,7 @@ def start_process_with_a_shell(context, config):
if sev == bandit.LOW:
return bandit.Issue(
severity=bandit.LOW,
cwe=78,
confidence=bandit.HIGH,
text='Starting a process with a shell: '
'Seems safe, but may be changed in the future, '
Expand All @@ -459,6 +464,7 @@ def start_process_with_a_shell(context, config):
else:
return bandit.Issue(
severity=bandit.HIGH,
cwe=78,
confidence=bandit.HIGH,
text='Starting a process with a shell, possible injection'
' detected, security issue.'
Expand Down Expand Up @@ -547,6 +553,7 @@ def start_process_with_no_shell(context, config):
if config and context.call_function_name_qual in config['no_shell']:
return bandit.Issue(
severity=bandit.LOW,
cwe=78,
confidence=bandit.MEDIUM,
text='Starting a process without a shell.'
)
Expand Down Expand Up @@ -642,6 +649,7 @@ def start_process_with_partial_path(context, config):
if isinstance(node, ast.Str) and not full_path_match.match(node.s):
return bandit.Issue(
severity=bandit.LOW,
cwe=78,
confidence=bandit.HIGH,
text='Starting a process with a partial executable path'
)
1 change: 1 addition & 0 deletions bandit/plugins/injection_sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ def hardcoded_sql_expressions(context):
if _check_string(val[1]):
return bandit.Issue(
severity=bandit.MEDIUM,
cwe=89,
confidence=bandit.MEDIUM if val[0] else bandit.LOW,
text="Possible SQL injection vector through string-based "
"query construction."
Expand Down
1 change: 1 addition & 0 deletions bandit/plugins/injection_wildcard.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ def linux_commands_wildcard_injection(context, config):
):
return bandit.Issue(
severity=bandit.HIGH,
cwe=155,
confidence=bandit.MEDIUM,
text="Possible wildcard injection in call: %s" %
context.call_function_name_qual,
Expand Down
5 changes: 5 additions & 0 deletions bandit/plugins/insecure_ssl_tls.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ def ssl_with_bad_version(context, config):
if context.check_call_arg_value('ssl_version', bad_ssl_versions):
return bandit.Issue(
severity=bandit.HIGH,
cwe=326,
confidence=bandit.HIGH,
text="ssl.wrap_socket call with insecure SSL/TLS protocol "
"version identified, security issue.",
Expand All @@ -114,6 +115,7 @@ def ssl_with_bad_version(context, config):
if context.check_call_arg_value('method', bad_ssl_versions):
return bandit.Issue(
severity=bandit.HIGH,
cwe=326,
confidence=bandit.HIGH,
text="SSL.Context call with insecure SSL/TLS protocol "
"version identified, security issue.",
Expand All @@ -128,6 +130,7 @@ def ssl_with_bad_version(context, config):
context.get_lineno_for_call_arg('ssl_version'))
return bandit.Issue(
severity=bandit.MEDIUM,
cwe=326,
confidence=bandit.MEDIUM,
text="Function call with insecure SSL/TLS protocol "
"identified, possible security issue.",
Expand Down Expand Up @@ -186,6 +189,7 @@ def ssl_with_bad_defaults(context, config):
if val in bad_ssl_versions:
return bandit.Issue(
severity=bandit.MEDIUM,
cwe=326,
confidence=bandit.MEDIUM,
text="Function definition identified with insecure SSL/TLS "
"protocol version by default, possible security "
Expand Down Expand Up @@ -245,6 +249,7 @@ def ssl_with_no_version(context):
# tests for that (ssl_version is not specified).
return bandit.Issue(
severity=bandit.LOW,
cwe=326,
confidence=bandit.MEDIUM,
text="ssl.wrap_socket call with no SSL/TLS protocol version "
"specified, the default SSLv23 could be insecure, "
Expand Down
Loading

0 comments on commit e812ae3

Please sign in to comment.