Fixed #33461 -- Escaped template errors in the technical 500 debug page.

This commit is contained in:
Keryn Knight 2022-01-26 15:09:08 +00:00 committed by Mariusz Felisiak
parent 3a9b8b25d4
commit c5c7a15b09
4 changed files with 42 additions and 4 deletions

View File

@ -190,7 +190,7 @@
<div id="template"> <div id="template">
<h2>Error during template rendering</h2> <h2>Error during template rendering</h2>
<p>In template <code>{{ template_info.name }}</code>, error at line <strong>{{ template_info.line }}</strong></p> <p>In template <code>{{ template_info.name }}</code>, error at line <strong>{{ template_info.line }}</strong></p>
<h3>{{ template_info.message }}</h3> <h3>{{ template_info.message|force_escape }}</h3>
<table class="source{% if template_info.top %} cut-top{% endif %} <table class="source{% if template_info.top %} cut-top{% endif %}
{% if template_info.bottom != template_info.total %} cut-bottom{% endif %}"> {% if template_info.bottom != template_info.total %} cut-bottom{% endif %}">
{% for source_line in template_info.source_lines %} {% for source_line in template_info.source_lines %}
@ -316,7 +316,7 @@ Using engine {{ entry.backend.name }}:
{% endif %}{% endif %}{% if template_info %} {% endif %}{% endif %}{% if template_info %}
Template error: Template error:
In template {{ template_info.name }}, error at line {{ template_info.line }} In template {{ template_info.name }}, error at line {{ template_info.line }}
{{ template_info.message }} {{ template_info.message|force_escape }}
{% for source_line in template_info.source_lines %}{% if source_line.0 == template_info.line %} {{ source_line.0 }} : {{ template_info.before }} {{ template_info.during }} {{ template_info.after }}{% else %} {{ source_line.0 }} : {{ source_line.1 }}{% endif %}{% endfor %}{% endif %} {% for source_line in template_info.source_lines %}{% if source_line.0 == template_info.line %} {{ source_line.0 }} : {{ template_info.before }} {{ template_info.during }} {{ template_info.after }}{% else %} {{ source_line.0 }} : {{ source_line.1 }}{% endif %}{% endfor %}{% endif %}
Traceback (most recent call last):{% for frame in frames %} Traceback (most recent call last):{% for frame in frames %}

View File

@ -7,7 +7,7 @@ import tempfile
import threading import threading
from io import StringIO from io import StringIO
from pathlib import Path from pathlib import Path
from unittest import mock from unittest import mock, skipIf
from django.core import mail from django.core import mail
from django.core.files.uploadedfile import SimpleUploadedFile from django.core.files.uploadedfile import SimpleUploadedFile
@ -263,6 +263,27 @@ class DebugViewTests(SimpleTestCase):
"traceback, instead found: %s" % raising_loc "traceback, instead found: %s" % raising_loc
) )
@skipIf(
sys.platform == 'win32',
'Raises OSError instead of TemplateDoesNotExist on Windows.',
)
def test_safestring_in_exception(self):
with self.assertLogs('django.request', 'ERROR'):
response = self.client.get('/safestring_exception/')
self.assertNotContains(
response,
'<script>alert(1);</script>',
status_code=500,
html=True,
)
self.assertContains(
response,
'&lt;script&gt;alert(1);&lt;/script&gt;',
count=3,
status_code=500,
html=True,
)
def test_template_loader_postmortem(self): def test_template_loader_postmortem(self):
"""Tests for not existing file""" """Tests for not existing file"""
template_name = "notfound.html" template_name = "notfound.html"

View File

@ -59,6 +59,11 @@ urlpatterns += i18n_patterns(
) )
urlpatterns += [ urlpatterns += [
path(
'safestring_exception/',
views.safestring_in_template_exception,
name='safestring_exception',
),
path('template_exception/', views.template_exception, name='template_exception'), path('template_exception/', views.template_exception, name='template_exception'),
path( path(
'raises_template_does_not_exist/<path:path>', 'raises_template_does_not_exist/<path:path>',

View File

@ -9,7 +9,7 @@ from django.core.exceptions import (
) )
from django.http import Http404, HttpResponse, JsonResponse from django.http import Http404, HttpResponse, JsonResponse
from django.shortcuts import render from django.shortcuts import render
from django.template import TemplateDoesNotExist from django.template import Context, Template, TemplateDoesNotExist
from django.urls import get_resolver from django.urls import get_resolver
from django.views import View from django.views import View
from django.views.debug import ( from django.views.debug import (
@ -89,6 +89,18 @@ def template_exception(request):
return render(request, 'debug/template_exception.html') return render(request, 'debug/template_exception.html')
def safestring_in_template_exception(request):
"""
Trigger an exception in the template machinery which causes a SafeString
to be inserted as args[0] of the Exception.
"""
template = Template('{% extends "<script>alert(1);</script>" %}')
try:
template.render(Context())
except Exception:
return technical_500_response(request, *sys.exc_info())
def jsi18n(request): def jsi18n(request):
return render(request, 'jsi18n.html') return render(request, 'jsi18n.html')