diff --git a/django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js b/django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js
index 0f02051e6b..d2dda892b1 100644
--- a/django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js
+++ b/django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js
@@ -104,7 +104,7 @@
var selects = $(selectsSelector);
selects.find('option').each(function() {
if (this.value === objId) {
- this.innerHTML = newRepr;
+ this.textContent = newRepr;
this.value = newId;
}
});
diff --git a/django/views/debug.py b/django/views/debug.py
index 56329325d3..eac0a77605 100644
--- a/django/views/debug.py
+++ b/django/views/debug.py
@@ -636,13 +636,13 @@ TECHNICAL_500_TEMPLATE = ("""
var s = link.getElementsByTagName('span')[0];
var uarr = String.fromCharCode(0x25b6);
var darr = String.fromCharCode(0x25bc);
- s.innerHTML = s.innerHTML == uarr ? darr : uarr;
+ s.textContent = s.textContent == uarr ? darr : uarr;
return false;
}
function switchPastebinFriendly(link) {
s1 = "Switch to copy-and-paste view";
s2 = "Switch back to interactive view";
- link.innerHTML = link.innerHTML.trim() == s1 ? s2: s1;
+ link.textContent = link.textContent.trim() == s1 ? s2: s1;
toggle('browserTraceback', 'pastebinTraceback');
return false;
}
diff --git a/docs/releases/1.8.14.txt b/docs/releases/1.8.14.txt
index 6311172abc..31a304f7c0 100644
--- a/docs/releases/1.8.14.txt
+++ b/docs/releases/1.8.14.txt
@@ -2,9 +2,20 @@
Django 1.8.14 release notes
===========================
-*Under development*
+*July 18, 2016*
-Django 1.8.14 fixes several bugs in 1.8.13.
+Django 1.8.14 fixes a security issue and a bug in 1.8.13.
+
+XSS in admin's add/change related popup
+=======================================
+
+Unsafe usage of JavaScript's ``Element.innerHTML`` could result in XSS in the
+admin's add/change related popup. ``Element.textContent`` is now used to
+prevent execution of the data.
+
+The debug view also used ``innerHTML``. Although a security issue wasn't
+identified there, out of an abundance of caution it's also updated to use
+``textContent``.
Bugfixes
========
diff --git a/docs/releases/1.9.8.txt b/docs/releases/1.9.8.txt
index 8db5c3d01f..08ba5ae08f 100644
--- a/docs/releases/1.9.8.txt
+++ b/docs/releases/1.9.8.txt
@@ -2,9 +2,20 @@
Django 1.9.8 release notes
==========================
-*Under development*
+*July 18, 2016*
-Django 1.9.8 fixes several bugs in 1.9.7.
+Django 1.9.8 fixes a security issue and several bugs in 1.9.7.
+
+XSS in admin's add/change related popup
+=======================================
+
+Unsafe usage of JavaScript's ``Element.innerHTML`` could result in XSS in the
+admin's add/change related popup. ``Element.textContent`` is now used to
+prevent execution of the data.
+
+The debug view also used ``innerHTML``. Although a security issue wasn't
+identified there, out of an abundance of caution it's also updated to use
+``textContent``.
Bugfixes
========
diff --git a/tests/admin_views/tests.py b/tests/admin_views/tests.py
index 2886c94bd5..8f12fcd068 100644
--- a/tests/admin_views/tests.py
+++ b/tests/admin_views/tests.py
@@ -4475,11 +4475,11 @@ class SeleniumTests(AdminSeleniumTestCase):
self.wait_for_text('#content h1', 'Change section')
name_input = self.selenium.find_element_by_id('id_name')
name_input.clear()
- name_input.send_keys('edited section')
+ name_input.send_keys('edited section')
self.selenium.find_element_by_xpath('//input[@value="Save"]').click()
self.selenium.switch_to.window(self.selenium.window_handles[0])
select = Select(self.selenium.find_element_by_id('id_form-0-section'))
- self.assertEqual(select.first_selected_option.text, 'edited section')
+ self.assertEqual(select.first_selected_option.text, 'edited section')
# Add popup
self.selenium.find_element_by_id('add_id_form-0-section').click()