python.django.security.audit.avoid-mark-safe.avoid-mark-safe
Community Favorite
semgrep
Author
49,023
Download Count*
License
'mark_safe()' is used to mark a string as "safe" for HTML output. This disables escaping and could therefore subject the content to XSS attacks. Use 'django.utils.html.format_html()' to build HTML for rendering instead.
Run Locally
Run in CI
Defintion
rules:
- id: avoid-mark-safe
patterns:
- pattern-not-inside: django.utils.html.format_html(...)
- pattern-not: django.utils.safestring.mark_safe("...")
- pattern: django.utils.safestring.mark_safe(...)
message: "'mark_safe()' is used to mark a string as \"safe\" for HTML output.
This disables escaping and could therefore subject the content to XSS
attacks. Use 'django.utils.html.format_html()' to build HTML for rendering
instead."
metadata:
source-rule-url: https://bandit.readthedocs.io/en/latest/plugins/b703_django_mark_safe.html
cwe:
- "CWE-79: Improper Neutralization of Input During Web Page Generation
('Cross-site Scripting')"
owasp:
- A07:2017 - Cross-Site Scripting (XSS)
- A03:2021 - Injection
references:
- https://docs.djangoproject.com/en/3.0/ref/utils/#django.utils.safestring.mark_safe
- https://docs.djangoproject.com/en/3.0/ref/utils/#django.utils.html.format_html
category: security
technology:
- django
cwe2022-top25: true
cwe2021-top25: true
subcategory:
- audit
likelihood: LOW
impact: MEDIUM
confidence: LOW
license: Commons Clause License Condition v1.0[LGPL-2.1-only]
vulnerability_class:
- Cross-Site-Scripting (XSS)
languages:
- python
severity: WARNING
Examples
avoid-mark-safe.py
from django.utils.safestring import mark_safe
from django.utils.html import format_html
from django.http import HttpResponse
from django.template import loader
def not_really_safe(request):
template = loader.get_template('contents.html')
# ruleid:avoid-mark-safe
not_actually_safe = mark_safe(
"""
<div>
<p>Contents! %s</p>
</div>
""" % request.POST.get("contents")
)
return HttpResponse(template.render({"html_example": not_actually_safe}, request))
def fine(request):
template = loader.get_template('contents.html')
# ok:avoid-mark-safe
fine = mark_safe(
"""
<div>
<p>Contents!</p>
</div>
"""
)
return HttpResponse(template.render({"html_example": fine}, request))
def not_really_safe(request):
template = loader.get_template('contents.html')
# ok:avoid-mark-safe
this_is_ok = format_html(
"""
<div>
<p>Contents! {}</p>
</div>
""",
request.POST.get("contents")
)
return HttpResponse(template.render({"html_example": this_is_ok}, request))
Short Link: https://sg.run/yd0P