CVE-2011-0697
Description
Cross-site scripting (XSS) vulnerability in Django 1.1.x before 1.1.4 and 1.2.x before 1.2.5 might allow remote attackers to inject arbitrary web script or HTML via a filename associated with a file upload.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
DjangoPyPI | >= 1.1, < 1.1.4 | 1.1.4 |
DjangoPyPI | >= 1.2, < 1.2.5 | 1.2.5 |
Affected products
9cpe:2.3:a:djangoproject:django:1.1:*:*:*:*:*:*:*+ 8 more
- cpe:2.3:a:djangoproject:django:1.1:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.1.0:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.1.2:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.1.3:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.2:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.2.1:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.2.2:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.2.3:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.2.4:*:*:*:*:*:*:*
Patches
41966786d2dde[1.1.X] Fixed security issue in AdminFileWidget. Release and disclosure forthcoming.
2 files changed · +17 −1
django/contrib/admin/widgets.py+1 −1 modified@@ -93,7 +93,7 @@ def render(self, name, value, attrs=None): output = [] if value and hasattr(value, "url"): output.append('%s <a target="_blank" href="%s">%s</a> <br />%s ' % \ - (_('Currently:'), value.url, value, _('Change:'))) + (_('Currently:'), escape(value.url), escape(value), _('Change:'))) output.append(super(AdminFileWidget, self).render(name, value, attrs)) return mark_safe(u''.join(output))
tests/regressiontests/admin_widgets/tests.py+16 −0 modified@@ -154,3 +154,19 @@ def test_nonexistent_target_id(self): post_data) self.assertContains(response, 'Select a valid choice. That choice is not one of the available choices.') + +class AdminFileWidgetTest(DjangoTestCase): + def test_render_escapes_html(self): + class StrangeFieldFile(object): + url = "something?chapter=1§=2©=3&lang=en" + + def __unicode__(self): + return u'''something<div onclick="alert('oops')">.jpg''' + + widget = widgets.AdminFileWidget() + field = StrangeFieldFile() + output = widget.render('myfile', field) + self.assertFalse(field.url in output) + self.assertTrue(u'href="something?chapter=1&sect=2&copy=3&lang=en"' in output) + self.assertFalse(unicode(field) in output) + self.assertTrue(u'something<div onclick="alert('oops')">.jpg' in output)
1f814a954784[1.2.X] Fixed security issue in AdminFileWidget. Disclosure and release forthcoming.
2 files changed · +17 −1
django/contrib/admin/widgets.py+1 −1 modified@@ -96,7 +96,7 @@ def render(self, name, value, attrs=None): output = [] if value and hasattr(value, "url"): output.append('%s <a target="_blank" href="%s">%s</a> <br />%s ' % \ - (_('Currently:'), value.url, value, _('Change:'))) + (_('Currently:'), escape(value.url), escape(value), _('Change:'))) output.append(super(AdminFileWidget, self).render(name, value, attrs)) return mark_safe(u''.join(output))
tests/regressiontests/admin_widgets/tests.py+16 −0 modified@@ -239,6 +239,22 @@ def test_render(self): '<input type="file" name="test" />', ) + def test_render_escapes_html(self): + class StrangeFieldFile(object): + url = "something?chapter=1§=2©=3&lang=en" + + def __unicode__(self): + return u'''something<div onclick="alert('oops')">.jpg''' + + widget = AdminFileWidget() + field = StrangeFieldFile() + output = widget.render('myfile', field) + self.assertFalse(field.url in output) + self.assertTrue(u'href="something?chapter=1&sect=2&copy=3&lang=en"' in output) + self.assertFalse(unicode(field) in output) + self.assertTrue(u'something<div onclick="alert('oops')">.jpg' in output) + + class ForeignKeyRawIdWidgetTest(DjangoTestCase): def test_render(self):
a9cf3d23724f[1.2.X] Fixed #14982 -- Ensure that EMPTY_CHANGELIST_VALUE is honored for nullable foreign keys. Thanks to marcob for the report and fix, and to sontek for the test case.
3 files changed · +27 −3
django/contrib/admin/templatetags/admin_list.py+5 −1 modified@@ -157,7 +157,11 @@ def items_for_result(cl, result, form): if value is None: result_repr = EMPTY_CHANGELIST_VALUE if isinstance(f.rel, models.ManyToOneRel): - result_repr = escape(getattr(result, f.name)) + field_val = getattr(result, f.name) + if field_val is None: + result_repr = EMPTY_CHANGELIST_VALUE + else: + result_repr = escape(field_val) else: result_repr = display_for_field(value, f) if isinstance(f, models.DateField) or isinstance(f, models.TimeField):
tests/regressiontests/admin_changelist/models.py+2 −2 modified@@ -5,5 +5,5 @@ class Parent(models.Model): name = models.CharField(max_length=128) class Child(models.Model): - parent = models.ForeignKey(Parent, editable=False) - name = models.CharField(max_length=30, blank=True) \ No newline at end of file + parent = models.ForeignKey(Parent, editable=False, null=True) + name = models.CharField(max_length=30, blank=True)
tests/regressiontests/admin_changelist/tests.py+20 −0 modified@@ -17,6 +17,26 @@ def test_select_related_preserved(self): m.list_select_related, m.list_per_page, m.list_editable, m) self.assertEqual(cl.query_set.query.select_related, {'parent': {'name': {}}}) + def test_result_list_empty_changelist_value(self): + """ + Regression test for #14982: EMPTY_CHANGELIST_VALUE should be honored + for relationship fields + """ + new_child = Child.objects.create(name='name', parent=None) + request = MockRequest() + m = ChildAdmin(Child, admin.site) + cl = ChangeList(request, Child, m.list_display, m.list_display_links, + m.list_filter, m.date_hierarchy, m.search_fields, + m.list_select_related, m.list_per_page, m.list_editable, m) + cl.formset = None + template = Template('{% load admin_list %}{% spaceless %}{% result_list cl %}{% endspaceless %}') + context = Context({'cl': cl}) + table_output = template.render(context) + row_html = '<tbody><tr class="row1"><td><input type="checkbox" class="action-select" value="1" name="_selected_action" /></td><th><a href="1/">name</a></th><td>(None)</td></tr></tbody>' + self.assertFalse(table_output.find(row_html) == -1, + 'Failed to find expected row element: %s' % table_output) + + def test_result_list_html(self): """ Verifies that inclusion tag result_list generates a table when with
90be6ca20d60[1.2.X] Fixed #15032 -- Replaced 1.2.X implementation of admin changelist filtering security fix (r15031/r15033) with the one from trunk so another valid filter usage scenario (using model inheritance) is still possible. Thanks rene for reporting this.
3 files changed · +38 −3
django/contrib/admin/options.py+15 −2 modified@@ -195,8 +195,21 @@ def lookup_allowed(self, lookup): # Special case -- foo__id__exact and foo__id queries are implied # if foo has been specificially included in the lookup list; so - # drop __id if it is the last part. - if len(parts) > 1 and parts[-1] == self.model._meta.pk.name: + # drop __id if it is the last part. However, first we need to find + # the pk attribute name. + model = self.model + pk_attr_name = None + for part in parts[:-1]: + field, _, _, _ = model._meta.get_field_by_name(part) + if hasattr(field, 'rel'): + model = field.rel.to + pk_attr_name = model._meta.pk.name + elif isinstance(field, RelatedObject): + model = field.model + pk_attr_name = model._meta.pk.name + else: + pk_attr_name = None + if pk_attr_name and len(parts) > 1 and parts[-1] == pk_attr_name: parts.pop() try:
tests/regressiontests/admin_views/models.py+12 −0 modified@@ -588,6 +588,17 @@ class Album(models.Model): class AlbumAdmin(admin.ModelAdmin): list_filter = ['title'] +class Employee(Person): + code = models.CharField(max_length=20) + +class WorkHour(models.Model): + datum = models.DateField() + employee = models.ForeignKey(Employee) + +class WorkHourAdmin(admin.ModelAdmin): + list_display = ('datum', 'employee') + list_filter = ('employee',) + admin.site.register(Article, ArticleAdmin) admin.site.register(CustomArticle, CustomArticleAdmin) admin.site.register(Section, save_as=True, inlines=[ArticleInline]) @@ -619,6 +630,7 @@ class AlbumAdmin(admin.ModelAdmin): admin.site.register(PlotDetails) admin.site.register(CyclicOne) admin.site.register(CyclicTwo) +admin.site.register(WorkHour, WorkHourAdmin) # We intentionally register Promo and ChapterXtra1 but not Chapter nor ChapterXtra2. # That way we cover all four cases:
tests/regressiontests/admin_views/tests.py+11 −1 modified@@ -28,7 +28,7 @@ FooAccount, Gallery, ModelWithStringPrimaryKey, \ Person, Persona, Picture, Podcast, Section, Subscriber, Vodcast, \ Language, Collector, Widget, Grommet, DooHickey, FancyDoodad, Whatsit, \ - Category, Post, Plot, FunkyTag + Category, Post, Plot, FunkyTag, WorkHour, Employee class AdminViewBasicTest(TestCase): @@ -311,6 +311,16 @@ def test_disallowed_filtering(self): except SuspiciousOperation: self.fail("Filters should be allowed if they involve a local field without the need to whitelist them in list_filter or date_hierarchy.") + e1 = Employee.objects.create(name='Anonymous', gender=1, age=22, alive=True, code='123') + e2 = Employee.objects.create(name='Visitor', gender=2, age=19, alive=True, code='124') + WorkHour.objects.create(datum=datetime.datetime.now(), employee=e1) + WorkHour.objects.create(datum=datetime.datetime.now(), employee=e2) + response = self.client.get("/test_admin/admin/admin_views/workhour/") + self.assertEqual(response.status_code, 200) + self.assertContains(response, 'employee__person_ptr__exact') + response = self.client.get("/test_admin/admin/admin_views/workhour/?employee__person_ptr__exact=%d" % e1.pk) + self.assertEqual(response.status_code, 200) + class SaveAsTests(TestCase): fixtures = ['admin-views-users.xml','admin-views-person.xml']
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
31- openwall.com/lists/oss-security/2011/02/09/6nvdPatchWEB
- www.djangoproject.com/weblog/2011/feb/08/security/nvdPatchVendor Advisory
- bugzilla.redhat.com/show_bug.cginvdPatchWEB
- github.com/advisories/GHSA-8m3r-rv5g-fcpqghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2011-0697ghsaADVISORY
- lists.fedoraproject.org/pipermail/package-announce/2011-February/054207.htmlnvdWEB
- lists.fedoraproject.org/pipermail/package-announce/2011-February/054208.htmlnvdWEB
- www.debian.org/security/2011/dsa-2163nvdWEB
- www.djangoproject.com/weblog/2011/feb/08/securityghsaWEB
- www.mandriva.com/security/advisoriesnvdWEB
- www.ubuntu.com/usn/USN-1066-1nvdWEB
- github.com/django/django/commit/1966786d2dde73e17f39cf340eb33fcb5d73904eghsaWEB
- github.com/django/django/commit/1f814a9547842dcfabdae09573055984af9d3fabghsaWEB
- github.com/django/django/commit/90be6ca20d607977dec234ec972b77b83955749bghsaWEB
- github.com/django/django/commit/a9cf3d23724ff6918103e86aa863eadd1fab811dghsaWEB
- github.com/pypa/advisory-database/tree/main/vulns/django/PYSEC-2011-11.yamlghsaWEB
- web.archive.org/web/20110521033259/http://secunia.com/advisories/43230ghsaWEB
- web.archive.org/web/20110521033304/http://secunia.com/advisories/43297ghsaWEB
- web.archive.org/web/20110521033309/http://secunia.com/advisories/43382ghsaWEB
- web.archive.org/web/20110521033314/http://secunia.com/advisories/43426ghsaWEB
- web.archive.org/web/20130616104703/http://www.securityfocus.com/bid/46296ghsaWEB
- secunia.com/advisories/43230nvd
- secunia.com/advisories/43297nvd
- secunia.com/advisories/43382nvd
- secunia.com/advisories/43426nvd
- www.securityfocus.com/bid/46296nvd
- www.vupen.com/english/advisories/2011/0372nvd
- www.vupen.com/english/advisories/2011/0388nvd
- www.vupen.com/english/advisories/2011/0429nvd
- www.vupen.com/english/advisories/2011/0439nvd
- www.vupen.com/english/advisories/2011/0441nvd
News mentions
0No linked articles in our index yet.