python.flask.security.dangerous-template-string.dangerous-template-string

Verifed by r2c
Community Favorite
profile photo of semgrepsemgrep
Author
99,257
Download Count*

Found a template created with string formatting. This is susceptible to server-side template injection and cross-site scripting attacks.

Run Locally

Run in CI

Defintion

rules:
  - id: dangerous-template-string
    message: Found a template created with string formatting. This is susceptible to
      server-side template injection and cross-site scripting attacks.
    metadata:
      cwe:
        - "CWE-96: Improper Neutralization of Directives in Statically Saved
          Code ('Static Code Injection')"
      owasp:
        - A03:2021 - Injection
      references:
        - https://nvisium.com/blog/2016/03/09/exploring-ssti-in-flask-jinja2.html
        - https://pequalsnp-team.github.io/cheatsheet/flask-jinja2-ssti
      category: security
      technology:
        - flask
      subcategory:
        - audit
      likelihood: LOW
      impact: MEDIUM
      confidence: LOW
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      vulnerability_class:
        - Code Injection
    languages:
      - python
    severity: ERROR
    pattern-either:
      - pattern: |
          $V = "...".format(...)
          ...
          flask.render_template_string($V, ...)
      - pattern: |
          $V = "...".format(...)
          ...
          return flask.render_template_string($V, ...), $MORE
      - pattern: |
          $V = "..." % $S
          ...
          flask.render_template_string($V, ...)
      - pattern: |
          $V = "..." % $S
          ...
          return flask.render_template_string($V, ...), $MORE
      - pattern: |
          $V = "..."
          ...
          $V += $O
          ...
          flask.render_template_string($V, ...)
      - pattern: |
          $V = "..."
          ...
          $V += $O
          ...
          return flask.render_template_string($V, ...), $MORE
      - pattern: |
          $V = f"...{$X}..."
          ...
          flask.render_template_string($V, ...)
      - pattern: |
          $V = f"...{$X}..."
          ...
          return flask.render_template_string($V, ...), $CODE

Examples

dangerous-template-string.py

import flask

app = flask.Flask(__name__)

@app.route("/error")
def error(e):
    # ruleid: dangerous-template-string
    template = '''{  extends "layout.html"  }
{  block body  }
    <div class="center-content error">
        <h1>Oops! That page doesn't exist.</h1>
        <h3>%s</h3>
    </div>
{  endblock  }
'''.format(request.url)
    return flask.render_template_string(template), 404

@app.route("/error2")
def error2(e):
    # ruleid: dangerous-template-string
    template = '''{  extends "layout.html"  }
{  block body  }
    <div class="center-content error">
        <h1>Oops! That page doesn't exist.</h1>
        <h3>%s</h3>
    </div>
{  endblock  }
''' % (request.url)
    return flask.render_template_string(template), 404

## Doesn't work yet
#@app.route("/error3")
#def error3(e):
#    template = f'''{  extends "layout.html"  }
#{  block body  }
#    <div class="center-content error">
#        <h1>Oops! That page doesn't exist.</h1>
#        <h3>{request.url}</h3>
#    </div>
#{  endblock  }
#'''
#    return flask.render_template_string(template)

@app.route("/error4")
def error4(e):
    # ruleid: dangerous-template-string
    template = """
{  extends "layout.html"  }
{  block body  }
    <div class="center-content error">
        <h1>Oops! That page doesn't exist.</h1>
        <h3>
"""
    template += request.url
    template += """
</h3>
</div>
{  endblock  }
"""
    rendered = flask.render_template_string(template)