+34
-4
lines changedFilter options
+34
-4
lines changed Original file line number Diff line number Diff line change
@@ -193,7 +193,7 @@ def contents(self):
193
193
if getattr(attr, "allow_tags", False):
194
194
result_repr = mark_safe(result_repr)
195
195
else:
196
-
result_repr = linebreaksbr(result_repr)
196
+
result_repr = linebreaksbr(result_repr, autoescape=True)
197
197
else:
198
198
if isinstance(f.rel, ManyToManyRel) and value is not None:
199
199
result_repr = ", ".join(map(six.text_type, value.all()))
Original file line number Diff line number Diff line change
@@ -2,9 +2,23 @@
2
2
Django 1.7.6 release notes
3
3
==========================
4
4
5
-
*Under Development*
5
+
*March 9, 2015*
6
6
7
-
Django 1.7.6 fixes several bugs in 1.7.5.
7
+
Django 1.7.6 fixes a security issue and several bugs in 1.7.5.
8
+
9
+
Mitigated an XSS attack via properties in ``ModelAdmin.readonly_fields``
10
+
========================================================================
11
+
12
+
The :attr:`ModelAdmin.readonly_fields
13
+
<django.contrib.admin.ModelAdmin.readonly_fields>` attribute in the Django
14
+
admin allows displaying model fields and model attributes. While the former
15
+
were correctly escaped, the latter were not. Thus untrusted content could be
16
+
injected into the admin, presenting an exploitation vector for XSS attacks.
17
+
18
+
In this vulnerability, every model attribute used in ``readonly_fields`` that
19
+
is not an actual model field (e.g. a :class:`property`) will **fail to be
20
+
escaped** even if that attribute is not marked as safe. In this release,
21
+
autoescaping is now correctly applied.
8
22
9
23
Bugfixes
10
24
========
Original file line number Diff line number Diff line change
@@ -860,7 +860,7 @@ def get_formsets_with_inlines(self, request, obj=None):
860
860
site = admin.AdminSite(name="admin")
861
861
site.register(Article, ArticleAdmin)
862
862
site.register(CustomArticle, CustomArticleAdmin)
863
-
site.register(Section, save_as=True, inlines=[ArticleInline])
863
+
site.register(Section, save_as=True, inlines=[ArticleInline], readonly_fields=['name_property'])
864
864
site.register(ModelWithStringPrimaryKey)
865
865
site.register(Color)
866
866
site.register(Thing, ThingAdmin)
Original file line number Diff line number Diff line change
@@ -22,6 +22,13 @@ class Section(models.Model):
22
22
"""
23
23
name = models.CharField(max_length=100)
24
24
25
+
@property
26
+
def name_property(self):
27
+
"""
28
+
A property that simply returns the name. Used to test #24461
29
+
"""
30
+
return self.name
31
+
25
32
26
33
@python_2_unicode_compatible
27
34
class Article(models.Model):
Original file line number Diff line number Diff line change
@@ -3862,6 +3862,15 @@ def test_readonly_field_overrides(self):
3862
3862
self.assertContains(response, '<label for="id_public">Overridden public label:</label>', html=True)
3863
3863
self.assertNotContains(response, "Some help text for the date (with unicode ŠĐĆŽćžšđ)")
3864
3864
3865
+
def test_correct_autoescaping(self):
3866
+
"""
3867
+
Make sure that non-field readonly elements are properly autoescaped (#24461)
3868
+
"""
3869
+
section = Section.objects.create(name='<a>evil</a>')
3870
+
response = self.client.get(reverse('admin:admin_views_section_change', args=(section.pk,)))
3871
+
self.assertNotContains(response, "<a>evil</a>", status_code=200)
3872
+
self.assertContains(response, "<a>evil</a>", status_code=200)
3873
+
3865
3874
3866
3875
@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
3867
3876
class LimitChoicesToInAdminTest(TestCase):
You can’t perform that action at this time.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4