python.flask.security.xss.audit.direct-use-of-jinja2.direct-use-of-jinja2

profile photo of semgrepsemgrep
Author
7,347
Download Count*

Detected direct use of jinja2. If not done properly, this may bypass HTML escaping which opens up the application to cross-site scripting (XSS) vulnerabilities. Prefer using the Flask method 'render_template()' and templates with a '.html' extension in order to prevent XSS.

Run Locally

Run in CI

Defintion

rules:
  - id: direct-use-of-jinja2
    message: Detected direct use of jinja2. If not done properly, this may bypass
      HTML escaping which opens up the application to cross-site scripting (XSS)
      vulnerabilities. Prefer using the Flask method 'render_template()' and
      templates with a '.html' extension in order to prevent XSS.
    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://jinja.palletsprojects.com/en/2.11.x/api/#basics
      category: security
      technology:
        - flask
      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: jinja2.Environment(...)
      - pattern: jinja2.Template.render(...)
      - patterns:
          - pattern-inside: |
              $TEMPLATE = $ENV.get_template(...)
              ...
          - pattern: $TEMPLATE.render(...)
      - patterns:
          - pattern-inside: |
              $TEMPLATE = jinja2.Template(...)
              ...
          - pattern: $TEMPLATE.render(...)

Examples

direct-use-of-jinja2.py

import jinja2

template = jinja2.Template("""
<html>
<body>
{{ body }}
</body>
</html>
""")

# ruleid: direct-use-of-jinja2
rendered = template.render(body=input())

from jinja2 import Environment, PackageLoader, select_autoescape
# ruleid: direct-use-of-jinja2
env = Environment(
    loader=PackageLoader('yourapplication', 'templates'),
    autoescape=select_autoescape(['html', 'xml'])
)

t = env.get_template('mytemplate.html')

# ruleid: direct-use-of-jinja2
rendered2 = t.render(body=input())