summaryrefslogtreecommitdiff
path: root/odoo/tools/json/scriptsafe.py
diff options
context:
space:
mode:
authorXavier Morel <xmo@odoo.com>2019-05-27 10:59:43 +0000
committerXavier Morel <xmo@odoo.com>2019-06-19 13:47:35 +0000
commit05746b7068827247fce84b8fa0f19b3f254d20d2 (patch)
tree0c1b460045f5d45573737fd0607ff2e02f053aab /odoo/tools/json/scriptsafe.py
parent411abff3880c8b3945e2f3afe963894a2380202d (diff)
[IMP] *: script-safe JSON serialisation
* add a json_scriptsafe module, which re-exports the stdlib's json but provides a script-safe `dumps` function, because of the way it works the script-safe version is fine / safe to use outside script contexts, so there's no need to provide different functions to qweb contexts * make the json.dumps in qweb contexts <script>-safe (should be rendered using t-raw) * update callsites to properly dump json: - dump in template, not in the python code - dump the entire structure at once, not bits and bobs inside a JSON literal Task 1999158 closes odoo/odoo#33682 Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
Diffstat (limited to 'odoo/tools/json/scriptsafe.py')
-rw-r--r--odoo/tools/json/scriptsafe.py50
1 files changed, 50 insertions, 0 deletions
diff --git a/odoo/tools/json/scriptsafe.py b/odoo/tools/json/scriptsafe.py
new file mode 100644
index 00000000000..f1147b02883
--- /dev/null
+++ b/odoo/tools/json/scriptsafe.py
@@ -0,0 +1,50 @@
+# -*- coding: utf-8 -*-
+import json as json_
+import re
+from json import *
+
+__all__ = ['dumps', 'loads']
+
+JSON_SCRIPTSAFE_MAPPER = {
+ '&': r'\u0026',
+ '<': r'\u003c',
+ '>': r'\u003e',
+ '\u2028': r'\u2028',
+ '\u2029': r'\u2029'
+}
+
+def dumps(*args, **kwargs):
+ """ JSON used as JS in HTML (script tags) is problematic: <script>
+ tags are a special context which only waits for </script> but doesn't
+ interpret anything else, this means standard htmlescaping does not
+ work (it breaks double quotes, and e.g. `<` will become `&lt;` *in
+ the resulting JSON/JS* not just inside the page).
+
+ However, failing to escape embedded json means the json strings could
+ contains `</script>` and thus become XSS vector.
+
+ The solution turns out to be very simple: use JSON-level unicode
+ escapes for HTML-unsafe characters (e.g. "<" -> "\u003C". This removes
+ the XSS issue without breaking the json, and there is no difference to
+ the end result once it's been parsed back from JSON. So it will work
+ properly even for HTML attributes or raw text.
+
+ Also handle U+2028 and U+2029 the same way just in case as these are
+ interpreted as newlines in javascript but not in JSON, which could
+ lead to oddities and issues.
+
+ .. warning::
+
+ except inside <script> elements, this should be escaped following
+ the normal rules of the containing format
+
+ Cf https://code.djangoproject.com/ticket/17419#comment:27
+ """
+ # replacement can be done straight in the serialised JSON as the
+ # problematic characters are not JSON metacharacters (and can thus
+ # only occur in strings)
+ return re.sub(
+ r'[<>&\u2028\u2029]',
+ lambda m: JSON_SCRIPTSAFE_MAPPER[m[0]],
+ json_.dumps(*args, **kwargs),
+ )