Flask-User icon indicating copy to clipboard operation
Flask-User copied to clipboard

Raw HTML in email confirmation flash message

Open wolfgang42 opened this issue 5 years ago • 2 comments

I just got a flash message that looked like this:

Your email address has not yet been confirmed. Check your email Inbox and Spam folders for the confirmation email or <a href="http://localhost:5000/user/resend-email-confirmation">Re-send confirmation email</a>.

According to StackOverflow, this line should be wrapped in a call to Markup() to tell Flask that it is HTML which is safe to output directly:

https://github.com/lingthio/Flask-User/blob/a379fa0a281789618c484b459cb41236779b95b1/flask_user/user_manager__views.py#L679

I have done this in my project and it fixed the problem. This should be safe to do because the entire message is controlled by the server; there's no user-supplied content in it that could be used for injection.

While I'm at it, can the ‘R’ in “Re-send” be made lowercase? It looks strange in the middle of the sentence.

I can submit a PR for this, but the fact that this has been like this since the link was added 5 years ago makes me wonder if there's something I've missed here.

wolfgang42 avatar Dec 30 '18 22:12 wolfgang42

@wolfgang42, using {{ message|safe }} solves this. Check out the flask docs explanation

example

{% with messages = get_flashed_messages() %}
      {% if messages %}
      <ul>

        {% for message in messages %}
        <li>{{ message|safe }}</li>
        {% endfor %}
      </ul>
      {% endif %}
{% endwith %}

dann254 avatar Jan 03 '19 10:01 dann254

@dann254 Using {{markup|safe}} is a bad idea. I understand that the |safe filter can be used to turn off HTML escaping in the template. However, this opens a possible security hole. What happens when I (or another plugin) does something like the following (possibly by mistake)?

flash('Your friend '"+post.user.name+"' has written a new post "'+post.title+'"!')

If the post title contains a <script> tag, anyone who is following this person would get cross-site scripted, allowing a self-retweeting tweet or worse.

In fact, your link to the Flask docs specifically says:

In the Python code, wrap the HTML string in a Markup object before passing it to the template. This is in general the recommended way.

(Also, the example templates in the docs on flashing just use {{msg}} - there is no mention anywhere of unescaping it. If this was an acceptable practice I imagine it would be mentioned somewhere.)

wolfgang42 avatar Jan 03 '19 17:01 wolfgang42