Closes #22657: escape exception message in render_widget before mark_safe (#22658)

This commit is contained in:
bctiemann 2026-07-10 11:26:40 -04:00 committed by GitHub
parent 817b35de49
commit 6ec79402cc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 33 additions and 2 deletions

View File

@ -1,4 +1,5 @@
from django import template
from django.utils.html import escape
from django.utils.safestring import mark_safe
from django.utils.translation import gettext as _
@ -19,6 +20,6 @@ def render_widget(context, widget):
<span class="text-danger"><i class="mdi mdi-alert"></i></span>
{message1}
</p>
<p class="font-monospace ps-3">{e}</p>
<p class="font-monospace ps-3">{escape(e)}</p>
<p>{message2}</p>
""")

View File

@ -1,6 +1,7 @@
from django.test import TestCase, tag
from django.test import RequestFactory, TestCase, tag
from extras.dashboard.widgets import ObjectListWidget
from extras.templatetags.dashboard import render_widget
class ObjectListWidgetTestCase(TestCase):
@ -46,3 +47,32 @@ class ObjectListWidgetTestCase(TestCase):
widget = ObjectListWidget(id='2829fd9b-5dee-4c9a-81f2-5bd84c350a27', **config)
rendered = widget.render(mock_request)
self.assertTrue('Unable to load content. Could not resolve list URL for:' in rendered)
class RenderWidgetTemplateTagTestCase(TestCase):
def _make_context(self):
request = RequestFactory().get('/')
return {'request': request}
def test_render_widget_escapes_exception_html(self):
"""Exception text with HTML special chars must be escaped, not rendered as markup."""
class BrokenWidget:
def render(self, request):
raise Exception('<script>alert(1)</script>')
output = render_widget(self._make_context(), BrokenWidget())
self.assertIn('&lt;script&gt;', output)
self.assertNotIn('<script>', output)
def test_render_widget_escapes_exception_angle_brackets(self):
"""Angle brackets in exception messages are escaped."""
class BrokenWidget:
def render(self, request):
raise ValueError('invalid value: <bad>')
output = render_widget(self._make_context(), BrokenWidget())
self.assertIn('&lt;bad&gt;', output)
self.assertNotIn('<bad>', output)