Skip to content

Commit 0d48e50

Browse files
thibaudcolasgasman
authored andcommitted
Change ModelAdmin InspectView to escape any HTML from document titles
1 parent c906281 commit 0d48e50

2 files changed

Lines changed: 23 additions & 9 deletions

File tree

‎wagtail/contrib/modeladmin/tests/test_simple_modeladmin.py‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
from wagtail.admin.admin_url_finder import AdminURLFinder
1414
from wagtail.admin.panels import FieldPanel, TabbedInterface
1515
from wagtail.contrib.modeladmin.helpers.search import DjangoORMSearchHandler
16+
from wagtail.documents.models import Document
17+
from wagtail.documents.tests.utils import get_test_document_file
1618
from wagtail.images.models import Image
1719
from wagtail.images.tests.utils import get_test_image_file
1820
from wagtail.models import Locale, ModelLogEntry, Page
@@ -591,6 +593,20 @@ def test_book_author_present(self):
591593
response = self.get_for_book(1)
592594
self.assertContains(response, "J. R. R. Tolkien", 1)
593595

596+
def test_book_extract_document_html_escaping(self):
597+
doc = Document.objects.create(
598+
title="Title with <script>alert('XSS')</script>",
599+
file=get_test_document_file(),
600+
)
601+
book = Book.objects.get(title="The Lord of the Rings")
602+
book.extract_document = doc
603+
book.save()
604+
response = self.get_for_book(1)
605+
self.assertNotContains(response, "Title with <script>alert('XSS')</script>")
606+
self.assertContains(
607+
response, "Title with &lt;script&gt;alert(&#x27;XSS&#x27;)&lt;/script&gt;"
608+
)
609+
594610
def test_non_existent(self):
595611
response = self.get_for_book(100)
596612
self.assertEqual(response.status_code, 404)

‎wagtail/contrib/modeladmin/views.py‎

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@
2929
from django.utils.decorators import method_decorator
3030
from django.utils.encoding import force_str
3131
from django.utils.functional import cached_property
32+
from django.utils.html import format_html
3233
from django.utils.http import urlencode
33-
from django.utils.safestring import mark_safe
3434
from django.utils.text import capfirst
3535
from django.utils.translation import gettext as _
3636
from django.utils.translation import gettext_lazy
@@ -1132,14 +1132,12 @@ def get_document_field_display(self, field_name, field):
11321132
"""Render a link to a document"""
11331133
document = getattr(self.instance, field_name)
11341134
if document:
1135-
return mark_safe(
1136-
'<a href="%s">%s <span class="meta">(%s, %s)</span></a>'
1137-
% (
1138-
document.url,
1139-
document.title,
1140-
document.file_extension.upper(),
1141-
filesizeformat(document.file.size),
1142-
)
1135+
return format_html(
1136+
'<a href="{}">{} <span class="meta">({}, {})</span></a>',
1137+
document.url,
1138+
document.title,
1139+
document.file_extension.upper(),
1140+
filesizeformat(document.file.size),
11431141
)
11441142
return self.model_admin.get_empty_value_display(field_name)
11451143

0 commit comments

Comments
 (0)