Template Security & Auto-Escaping
Django templates auto-escape HTML by default, protecting against XSS (Cross-Site Scripting) attacks. Understanding when and how to control escaping is critical for security. Never mark user input as safe.
15 min•By Priygop Team•Updated 2026
Auto-Escaping
- Django escapes < > & ' " in template variables by default
- {{ user_input }} is SAFE — HTML is escaped automatically
- {{ user_input|safe }} is DANGEROUS — disables escaping
- {% autoescape off %} disables escaping for a block
- Only use |safe or autoescape off for TRUSTED content
- mark_safe() in Python marks a string as safe
- XSS attack: user submits <script>alert('hacked')</script>
- With auto-escape: displays as text. Without: executes the script!
Escaping Examples
Escaping Examples
# Auto-escaping in action
# If user_input = '<script>alert("XSS")</script>'
# SAFE — auto-escaped (default)
# {{ user_input }}
# Output: <script>alert("XSS")</script>
# Displays as text, does NOT execute
# DANGEROUS — escaping disabled
# {{ user_input|safe }}
# Output: <script>alert("XSS")</script>
# Executes the JavaScript! XSS attack!
# Block-level control
# {% autoescape off %}
# {{ trusted_html }} <- Not escaped
# {% endautoescape %}
# In Python — mark trusted content as safe
# from django.utils.safestring import mark_safe
# def get_badge(self):
# return mark_safe('<span class="badge">Admin</span>')
# RULE: Never use |safe on user input!
# Only use it for content YOU generate (icons, badges, etc.)Tip
Tip
Django auto-escapes all template variables. Only use |safe when you're 100% sure the content is sanitized.
Diagram
Loading diagram…
QuerySets are LAZY — no DB hit until evaluated.
Common Mistake
Warning
Disabling auto-escaping globally. Keep it on and selectively use |safe only where needed.
Practice Task
Note
(1) Try XSS with {{ user_input }} and verify Django escapes it. (2) Compare with |safe. (3) Use mark_safe() in views.
Quick Quiz
Key Takeaways
- Django templates auto-escape HTML by default, protecting against XSS (Cross-Site Scripting) attacks.
- Django escapes < > & ' " in template variables by default
- {{ user_input }} is SAFE — HTML is escaped automatically
- {{ user_input|safe }} is DANGEROUS — disables escaping