[ajax] use a custom tag to handle dynamically loaded js
Using <pre class="script"> makes it trivial for a malicious user to
inject arbitrary javascript into a html or rest text element (because it
looks innocent to the html sanitizer). Using a custom tag we can be
sure that it actually comes from our code and not from untrusted user
data. IE ignores custom tags, though, so we put it in its own namespace.
https://extranet.logilab.fr/1530578
--- a/utils.py Mon Feb 03 19:07:58 2014 +0100
+++ b/utils.py Wed Feb 05 16:34:21 2014 +0100
@@ -375,9 +375,9 @@
if skiphead:
# Don't insert <script> tags directly as they would be
# interpreted directly by some browsers (e.g. IE).
- # Use <pre class="script"> tags instead and let
+ # Use <cubicweb:script> tags instead and let
# `loadAjaxHtmlHead` handle the script insertion / execution.
- w(u'<pre class="script" src="%s"></pre>\n' %
+ w(u'<cubicweb:script src="%s"></cubicweb:script>\n' %
xml_escape(jsfile))
# FIXME: a probably better implementation might be to add
# JS or CSS urls in a JS list that loadAjaxHtmlHead
@@ -392,9 +392,9 @@
if self.post_inlined_scripts:
if skiphead:
for script in self.post_inlined_scripts:
- w(u'<pre class="script">')
+ w(u'<cubicweb:script>')
w(xml_escape(script))
- w(u'</pre>')
+ w(u'</cubicweb:script>')
else:
w(self.script_opening)
w(u'\n\n'.join(self.post_inlined_scripts))
@@ -455,8 +455,8 @@
attrs = ' '.join('%s="%s"' % (attr, xml_escape(value))
for attr, value in self._htmlattrs)
if attrs:
- return '<html %s>' % attrs
- return '<html>'
+ return '<html xmlns:cubicweb="http://www.cubicweb.org" %s>' % attrs
+ return '<html xmlns:cubicweb="http://www.cubicweb.org">'
def getvalue(self):
"""writes HTML headers, closes </head> tag and writes HTML body"""
--- a/web/data/cubicweb.ajax.js Mon Feb 03 19:07:58 2014 +0100
+++ b/web/data/cubicweb.ajax.js Wed Feb 05 16:34:21 2014 +0100
@@ -200,7 +200,7 @@
},
_loadAjaxScripts: function($responseHead, $head) {
- $responseHead.find('pre.script').each(function(i) {
+ $responseHead.find('cubicweb\\:script').each(function(i) {
var $srcnode = $(this);
var url = $srcnode.attr('src');
if (url) {
@@ -222,7 +222,7 @@
jQuery.globalEval($srcnode.text());
}
});
- $responseHead.find('pre.script').remove();
+ $responseHead.find('cubicweb\\:script').remove();
}
});
--- a/web/test/unittest_views_baseviews.py Mon Feb 03 19:07:58 2014 +0100
+++ b/web/test/unittest_views_baseviews.py Wed Feb 05 16:34:21 2014 +0100
@@ -133,7 +133,7 @@
html_source = self.view('my-view').source
source_lines = [line.strip() for line in html_source.splitlines(False)
if line.strip()]
- self.assertListEqual(['<!DOCTYPE html>', '<html lang="en">'], source_lines[:2])
+ self.assertListEqual(['<!DOCTYPE html>', '<html xmlns:cubicweb="http://www.cubicweb.org" lang="en">'], source_lines[:2])
def test_set_doctype_no_reset_xmldecl(self):
"""
@@ -151,7 +151,7 @@
html_source = self.view('my-view').source
source_lines = [line.strip() for line in html_source.splitlines(False)
if line.strip()]
- self.assertListEqual([html_doctype, '<html lang="cz">', '<head>'],
+ self.assertListEqual([html_doctype, '<html xmlns:cubicweb="http://www.cubicweb.org" lang="cz">', '<head>'],
source_lines[:3])
if __name__ == '__main__':