-
-
Notifications
You must be signed in to change notification settings - Fork 628
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into missing-metric-in-report
- Loading branch information
Showing
27 changed files
with
356 additions
and
157 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
# Copyright (c) 2025 David Salvisberg | ||
# | ||
# SPDX-License-Identifier: Apache-2.0 | ||
r""" | ||
============================================ | ||
B704: Potential XSS on markupsafe.Markup use | ||
============================================ | ||
``markupsafe.Markup`` does not perform any escaping, so passing dynamic | ||
content, like f-strings, variables or interpolated strings will potentially | ||
lead to XSS vulnerabilities, especially if that data was submitted by users. | ||
Instead you should interpolate the resulting ``markupsafe.Markup`` object, | ||
which will perform escaping, or use ``markupsafe.escape``. | ||
**Config Options:** | ||
This plugin allows you to specify additional callable that should be treated | ||
like ``markupsafe.Markup``. By default we recognize ``flask.Markup`` as | ||
an alias, but there are other subclasses or similar classes in the wild | ||
that you may wish to treat the same. | ||
Additionally there is a whitelist for callable names, whose result may | ||
be safely passed into ``markupsafe.Markup``. This is useful for escape | ||
functions like e.g. ``bleach.clean`` which don't themselves return | ||
``markupsafe.Markup``, so they need to be wrapped. Take care when using | ||
this setting, since incorrect use may introduce false negatives. | ||
These two options can be set in a shared configuration section | ||
`markupsafe_xss`. | ||
.. code-block:: yaml | ||
markupsafe_xss: | ||
# Recognize additional aliases | ||
extend_markup_names: | ||
- webhelpers.html.literal | ||
- my_package.Markup | ||
# Allow the output of these functions to pass into Markup | ||
allowed_calls: | ||
- bleach.clean | ||
- my_package.sanitize | ||
:Example: | ||
.. code-block:: none | ||
>> Issue: [B704:markupsafe_markup_xss] Potential XSS with | ||
``markupsafe.Markup`` detected. Do not use ``Markup`` | ||
on untrusted data. | ||
Severity: Medium Confidence: High | ||
CWE: CWE-79 (https://cwe.mitre.org/data/definitions/79.html) | ||
Location: ./examples/markupsafe_markup_xss.py:5:0 | ||
4 content = "<script>alert('Hello, world!')</script>" | ||
5 Markup(f"unsafe {content}") | ||
6 flask.Markup("unsafe {}".format(content)) | ||
.. seealso:: | ||
- https://pypi.org/project/MarkupSafe/ | ||
- https://markupsafe.palletsprojects.com/en/stable/escaping/#markupsafe.Markup | ||
- https://cwe.mitre.org/data/definitions/79.html | ||
.. versionadded:: 1.8.3 | ||
""" | ||
import ast | ||
|
||
import bandit | ||
from bandit.core import issue | ||
from bandit.core import test_properties as test | ||
from bandit.core.utils import get_call_name | ||
|
||
|
||
def gen_config(name): | ||
if name == "markupsafe_xss": | ||
return { | ||
"extend_markup_names": [], | ||
"allowed_calls": [], | ||
} | ||
|
||
|
||
@test.takes_config("markupsafe_xss") | ||
@test.checks("Call") | ||
@test.test_id("B704") | ||
def markupsafe_markup_xss(context, config): | ||
|
||
qualname = context.call_function_name_qual | ||
if qualname not in ("markupsafe.Markup", "flask.Markup"): | ||
if qualname not in config.get("extend_markup_names", []): | ||
# not a Markup call | ||
return None | ||
|
||
args = context.node.args | ||
if not args or isinstance(args[0], ast.Constant): | ||
# both no arguments and a constant are fine | ||
return None | ||
|
||
allowed_calls = config.get("allowed_calls", []) | ||
if ( | ||
allowed_calls | ||
and isinstance(args[0], ast.Call) | ||
and get_call_name(args[0], context.import_aliases) in allowed_calls | ||
): | ||
# the argument contains a whitelisted call | ||
return None | ||
|
||
return bandit.Issue( | ||
severity=bandit.MEDIUM, | ||
confidence=bandit.HIGH, | ||
cwe=issue.Cwe.XSS, | ||
text=f"Potential XSS with ``{qualname}`` detected. Do " | ||
f"not use ``{context.call_function_name}`` on untrusted data.", | ||
) |
Oops, something went wrong.