python.flask.security.xss.audit.explicit-unescape-with-markup.explicit-unescape-with-markup

profile photo of semgrepsemgrep
Author
7,347
Download Count*

Detected explicitly unescaped content using 'Markup()'. This permits the unescaped data to include unescaped HTML which could result in cross-site scripting. Ensure this data is not externally controlled, or consider rewriting to not use 'Markup()'.

Run Locally

Run in CI

Defintion

rules:
  - id: explicit-unescape-with-markup
    message: Detected explicitly unescaped content using 'Markup()'. This permits
      the unescaped data to include unescaped HTML which could result in
      cross-site scripting. Ensure this data is not externally controlled, or
      consider rewriting to not use 'Markup()'.
    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://tedboy.github.io/flask/generated/generated/flask.Markup.html
      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: flask.Markup(...)
      - pattern: flask.Markup.unescape(...)
      - pattern: markupsafe.Markup(...)
      - pattern: $MARKUPOBJ.unescape()

Examples

explicit-unescape-with-markup.py

from flask import render_template, Markup, request
from markupsafe import Markup as mkup

from application import app

@app.route('/markup')
def markup_test():
    search_query = request.args.get('q')
    if search_query:
        search_query = '"{0}"'.format(
            search_query.replace('\"', '\\\"').strip())
    else:
        search_query = '""'

    playlist = request.args.get('p')
    if playlist:
        playlist = '"{0}"'.format(playlist.replace('\"', '\\\"').strip())
    else:
        playlist = '""'
    # ruleid: explicit-unescape-with-markup
    return render_template('/markup.html', query=Markup(search_query), playlist=Markup(playlist))

@app.route('/markup_unescape')
def markup_unescape_test():
    search_query = request.args.get('q')
    # ruleid: explicit-unescape-with-markup
    return render_template('/markup-unescape.html', query=Markup.unescape(search_query))

@app.route('/markupsafe')
def markupsafe_test():
    search_query = request.args.get('q')
    # ruleid: explicit-unescape-with-markup
    return render_template('/markup-unescape.html', query=mkup(search_query))

@app.route('/good')
def good_test():
    search_query = request.args.get('q')
    # ok: explicit-unescape-with-markup
    return render_template('/markup-unescape.html', query=Markup.escape(search_query))