Skip to content

Commit ff806ab

Browse files
thibaudcolasgasman
authored andcommitted
Change ModelAdmin InspectView to escape any HTML from document titles
1 parent f6eae49 commit ff806ab

File tree

2 files changed

+23
-9
lines changed

2 files changed

+23
-9
lines changed

Diff for: wagtail/contrib/modeladmin/tests/test_simple_modeladmin.py

+16
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)

Diff for: wagtail/contrib/modeladmin/views.py

+7-9
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
@@ -1131,14 +1131,12 @@ def get_document_field_display(self, field_name, field):
11311131
"""Render a link to a document"""
11321132
document = getattr(self.instance, field_name)
11331133
if document:
1134-
return mark_safe(
1135-
'<a href="%s">%s <span class="meta">(%s, %s)</span></a>'
1136-
% (
1137-
document.url,
1138-
document.title,
1139-
document.file_extension.upper(),
1140-
filesizeformat(document.file.size),
1141-
)
1134+
return format_html(
1135+
'<a href="{}">{} <span class="meta">({}, {})</span></a>',
1136+
document.url,
1137+
document.title,
1138+
document.file_extension.upper(),
1139+
filesizeformat(document.file.size),
11421140
)
11431141
return self.model_admin.get_empty_value_display(field_name)
11441142

0 commit comments

Comments
 (0)