📖 Scenario: You are building a simple Flask web app that shows user comments on a page. Users can submit comments, and you want to make sure the comments are safe to display without allowing harmful scripts to run.
🎯 Goal: Build a Flask app that safely displays user comments by preventing cross-site scripting (XSS) attacks using Flask's template autoescaping features.
📋 What You'll Learn
Create a list of user comments with some containing HTML tags
Add a variable to hold a new user comment
Render the comments safely in a Flask template using autoescaping
Add a final route to display the comments page
💡 Why This Matters
🌍 Real World
Web applications often display user-generated content. Preventing XSS attacks is critical to keep users safe and maintain trust.
💼 Career
Understanding how to safely render user input in templates is a key skill for web developers working with Flask or similar frameworks.
Progress0 / 4 steps
1
Create the initial comments list
Create a list called comments with these exact string entries: 'Hello, world!', 'Nice to meet you.', and ''.
Flask
Hint
Use square brackets to create a list and include the exact strings with quotes.
2
Add a new user comment variable
Create a variable called new_comment and set it to the string 'Welcome to the site!'.
Flask
Hint
Assign the exact string to the variable new_comment using an equals sign.
3
Render comments safely in a Flask template
Write a Flask route function called show_comments that returns the rendered template 'comments.html' passing the comments list and new_comment variable. Use Flask's render_template function.
Flask
Hint
Use the @app.route('/') decorator and define the function with the exact name show_comments. Return render_template with the template name and variables.
4
Complete the comments.html template with autoescaping
Create a Jinja2 template named comments.html that loops over the comments list and displays each comment inside a <li> tag. Also display the new_comment in a separate <p> tag. Use Jinja2's default autoescaping to prevent XSS.
Flask
Hint
Use Jinja2 template syntax with {% for %} to loop and {{ }} to display variables safely.
Practice
(1/5)
1. What does Flask's template engine do by default to prevent XSS attacks when rendering variables inside {{ }}?
easy
A. It converts all text to uppercase.
B. It disables rendering of any user input.
C. It automatically escapes special HTML characters in the variable content.
D. It removes all spaces from the variable content.
Flask templates use Jinja2, which escapes HTML special characters by default inside {{ }} to prevent scripts from running.
Step 2: Recognize the purpose of escaping
Escaping converts characters like <, >, & into safe HTML entities, stopping malicious scripts from executing.
Final Answer:
It automatically escapes special HTML characters in the variable content. -> Option C
Quick Check:
Default escaping = safe output [OK]
Hint: Flask auto-escapes variables in {{ }} to block scripts [OK]
Common Mistakes:
Thinking Flask disables all user input rendering
Believing Flask changes text case automatically
Assuming Flask removes spaces from variables
2. Which of the following is the correct way to safely display a user input variable named user_input in a Flask template to prevent XSS?
easy
A. {{ user_input|safe }}
B. {% raw user_input %}
C. {% safe user_input %}
D. {{ user_input }}
Solution
Step 1: Identify safe default rendering
Using {{ user_input }} automatically escapes content, preventing XSS.
Step 2: Understand the risk of |safe filter
The |safe filter disables escaping and should be used only with trusted content.
Final Answer:
{{ user_input }} -> Option D
Quick Check:
Use {{ variable }} without |safe for safety [OK]
Hint: Use {{ variable }} without |safe to keep escaping [OK]
Common Mistakes:
Using |safe on untrusted user input
Trying to use {% raw %} incorrectly
Assuming {% safe %} is a valid Jinja2 tag
3. Given this Flask template snippet:
<p>User comment: {{ comment }}</p>
If the variable comment contains <script>alert('XSS')</script>, what will be the rendered HTML output?
medium
A.
User comment: <script>alert('XSS')</script>
B.
User comment:
C.
User comment: <script>alert('XSS')</script>
D.
User comment: alert('XSS')
Solution
Step 1: Recognize Flask autoescaping behavior
Flask escapes HTML special characters like < and > in variables inside {{ }}.
Step 2: Convert script tags to safe HTML entities
The <script> tags become <script> in raw HTML, but browsers render them as <script> text, not executable code.
Final Answer:
<p>User comment: <script>alert('XSS')</script></p> -> Option A
Quick Check:
Escaped tags show as text, not scripts [OK]
Hint: Escaped script tags show as text, not run scripts [OK]
Common Mistakes:
Thinking scripts run when escaped
Confusing < with <
Assuming output removes tags completely
4. You see this Flask template code:
<p>Message: {{ message|safe }}</p>
What is the main problem with this code if message contains user input?
medium
A. It will cause a syntax error in the template.
B. It disables escaping, allowing XSS attacks if input is malicious.
C. It will remove all HTML tags from the message.
D. It automatically sanitizes the input, so no problem.
Solution
Step 1: Understand the effect of |safe filter
The |safe filter tells Flask not to escape the content, rendering raw HTML.
Step 2: Recognize security risk with user input
If message is user input, malicious scripts can run, causing XSS attacks.
Final Answer:
It disables escaping, allowing XSS attacks if input is malicious. -> Option B
Quick Check:
Using |safe on user input = security risk [OK]
Hint: Avoid |safe on user input to prevent XSS [OK]
Common Mistakes:
Thinking |safe sanitizes input
Believing it causes syntax errors
Assuming it strips HTML tags
5. You want to display a user-submitted comment that may contain some safe HTML tags like <b> and <i>, but prevent any scripts or dangerous tags from running. Which Flask approach best achieves this?
hard
A. Sanitize the comment in Python code to allow only safe tags, then mark safe with |safe in template.
B. Use {{ comment|safe }} directly to allow all HTML.
C. Use {{ comment }} to escape everything, disallowing all HTML tags.
D. Use {% raw %}{{ comment }}{% endraw %} to render raw input.
Solution
Step 1: Understand the need for selective HTML allowance
Allowing only safe tags requires cleaning input to remove scripts but keep tags like <b> and <i>.
Step 2: Use Python sanitization before rendering
Sanitize the comment in backend code (e.g., with bleach library) to whitelist safe tags, then mark safe in template.
Step 3: Avoid unsafe direct |safe usage
Directly using |safe without sanitization risks XSS.
Final Answer:
Sanitize the comment in Python code to allow only safe tags, then mark safe with |safe in template. -> Option A
Quick Check:
Sanitize first, then use |safe safely [OK]
Hint: Sanitize input in Python, then use |safe to allow safe HTML [OK]
Common Mistakes:
Using |safe without sanitizing user input
Escaping everything and losing desired formatting
Using {% raw %} which disables escaping completely
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.