python.django.security.audit.xss.html-safe.html-safe

profile photo of semgrepsemgrep
Author
8,409
Download Count*

html_safe() add the __html__ magic method to the provided class. The __html__ method indicates to the Django template engine that the value is 'safe' for rendering. This means that normal HTML escaping will not be applied to the return value. This exposes your application to cross-site scripting (XSS) vulnerabilities. If you need to render raw HTML, consider instead using mark_safe() which more clearly marks the intent to render raw HTML than a class with a magic method.

Run Locally

Run in CI

Defintion

rules:
  - id: html-safe
    message: "`html_safe()` add the `__html__` magic method to the provided class.
      The `__html__` method indicates to the Django template engine that the
      value is 'safe' for rendering. This means that normal HTML escaping will
      not be applied to the return value. This exposes your application to
      cross-site scripting (XSS) vulnerabilities. If you need to render raw
      HTML, consider instead using `mark_safe()` which more clearly marks the
      intent to render raw HTML than a class with a magic method."
    metadata:
      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/_modules/django/utils/html/#html_safe
        - https://gist.github.com/minusworld/7885d8a81dba3ea2d1e4b8fd3c218ef5
      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
    pattern-either:
      - pattern: django.utils.html.html_safe(...)
      - pattern: |
          @django.utils.html.html_safe
          class $CLASS(...):
            ...

Examples

html-safe.py

from django.utils.html import (
    conditional_escape, escape, escapejs, format_html, html_safe, json_script,
    linebreaks, smart_urlquote, strip_spaces_between_tags, strip_tags, urlize,
)
from django.utils.safestring import mark_safe

# cf.https://github.com/django/django/blob/76ed1c49f804d409cfc2911a890c78584db3c76e/tests/utils_tests/test_html.py#L204
# ruleid: html-safe
@html_safe
class HtmlClass:
    def __str__(self):
        return "<h1>I'm a html class!</h1>"

# ok: html-safe
class Boring:
    def __str__(self):
        return "<h1>I will become an html class!</h1>"

# ruleid: html-safe
HtmlBoring = html_safe(Boring)