Sanitize RichtText fields content
issue9405 review327451002
This commit is contained in:
1 parent
8d1fe05de0
commit
7cb4222199
6 files changed
+131
-3
No files matched your search
@@ -1,3 +1,4 @@
|
||||
* Sanitize RichtText fields content (issue9405)
|
||||
* Escape external string (issue9394)
|
||||
* Keep context in sessionStorage
|
||||
* Use existing context for get_preferences
|
||||
|
||||
@@ -2,6 +2,7 @@ Copyright (C) 2012-2020 Nicolas Évrard.
|
||||
Copyright (C) 2012-2020 Cédric Krier.
|
||||
Copyright (C) 2012-2014 Bertrand Chenal.
|
||||
Copyright (C) 2012-2020 B2CK SPRL.
|
||||
Copyright (C) 2019 Jitbit.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
+2
-1
@@ -23,7 +23,8 @@ module.exports = function(grunt) {
|
||||
'src/wizard.js',
|
||||
'src/board.js',
|
||||
'src/bus.js',
|
||||
'src/plugins.js'
|
||||
'src/plugins.js',
|
||||
'src/html_sanitizer.js'
|
||||
];
|
||||
|
||||
// Project configuration.
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var tag_whitelist = {
|
||||
B: true,
|
||||
BODY: true,
|
||||
BR: true,
|
||||
DIV: true,
|
||||
FONT: true,
|
||||
I: true,
|
||||
U: true,
|
||||
};
|
||||
|
||||
var attribute_whitelist = {
|
||||
align: true,
|
||||
color: true,
|
||||
face: true,
|
||||
size: true,
|
||||
};
|
||||
|
||||
Sao.HtmlSanitizer = {};
|
||||
Sao.HtmlSanitizer.sanitize = function(input) {
|
||||
input = input.trim();
|
||||
// to save performance and not create iframe
|
||||
if (input == "") return "";
|
||||
|
||||
// firefox "bogus node" workaround
|
||||
if (input == "<br>") return "";
|
||||
|
||||
var iframe = document.createElement('iframe');
|
||||
if (iframe.sandbox === undefined) {
|
||||
// Browser does not support sandboxed iframes
|
||||
console.warn("Your browser do not support sandboxed iframes," +
|
||||
" unable to sanitize HTML.");
|
||||
return input;
|
||||
}
|
||||
iframe.sandbox = 'allow-same-origin';
|
||||
iframe.style.display = 'none';
|
||||
// necessary so the iframe contains a document
|
||||
document.body.appendChild(iframe);
|
||||
var iframedoc = (iframe.contentDocument ||
|
||||
iframe.contentWindow.document);
|
||||
// null in IE
|
||||
if (iframedoc.body == null) {
|
||||
iframedoc.write("<body></body>");
|
||||
}
|
||||
iframedoc.body.innerHTML = input;
|
||||
|
||||
function make_sanitized_copy(node) {
|
||||
var new_node;
|
||||
if (node.nodeType == Node.TEXT_NODE) {
|
||||
new_node = node.cloneNode(true);
|
||||
} else if (node.nodeType == Node.ELEMENT_NODE &&
|
||||
tag_whitelist[node.tagName]) {
|
||||
//remove useless empty tags
|
||||
if ((node.tagName != "BR") && node.innerHTML.trim() == "") {
|
||||
return document.createDocumentFragment();
|
||||
}
|
||||
|
||||
new_node = iframedoc.createElement(node.tagName);
|
||||
|
||||
for (var i = 0; i < node.attributes.length; i++) {
|
||||
var attr = node.attributes[i];
|
||||
if (attribute_whitelist[attr.name]) {
|
||||
new_node.setAttribute(attr.name, attr.value);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < node.childNodes.length; i++) {
|
||||
var sub_copy = make_sanitized_copy(node.childNodes[i]);
|
||||
new_node.appendChild(sub_copy, false);
|
||||
}
|
||||
} else {
|
||||
new_node = document.createDocumentFragment();
|
||||
}
|
||||
return new_node;
|
||||
}
|
||||
|
||||
var result_element = make_sanitized_copy(iframedoc.body);
|
||||
document.body.removeChild(iframe);
|
||||
// replace is just for cleaner code
|
||||
return result_element.innerHTML
|
||||
.replace(/<br[^>]*>(\S)/g, "<br>\n$1")
|
||||
.replace(/div><div/g, "div>\n<div");
|
||||
};
|
||||
})();
|
||||
+3
-2
@@ -2261,7 +2261,7 @@ function eval_pyson(value){
|
||||
this.input.attr('spellcheck', 'true');
|
||||
}
|
||||
}
|
||||
this.input.html(value);
|
||||
this.input.html(Sao.HtmlSanitizer.sanitize(value || ''));
|
||||
},
|
||||
focus: function() {
|
||||
this.input.focus();
|
||||
@@ -2279,7 +2279,8 @@ function eval_pyson(value){
|
||||
this.field.set_client(this.record, value);
|
||||
},
|
||||
_normalize_markup: function(content) {
|
||||
var el = jQuery('<div/>').html(content || '');
|
||||
var el = jQuery('<div/>').html(
|
||||
Sao.HtmlSanitizer.sanitize(content || ''));
|
||||
this._normalize(el);
|
||||
return el.html();
|
||||
},
|
||||
|
||||
@@ -2800,6 +2800,25 @@
|
||||
["Active: False", "Active: True"]));
|
||||
});
|
||||
|
||||
QUnit.test('HTML Sanitization', function() {
|
||||
var examples = [
|
||||
["Test", "Test"],
|
||||
["<b>Test</b>", "<b>Test</b>"],
|
||||
["<div><b>Test</b></div>", "<div><b>Test</b></div>"],
|
||||
["<script>window.alert('insecure')</script>", ""],
|
||||
["<b><script>window.alert('insecure')</script>Test</b>",
|
||||
"<b>Test</b>"],
|
||||
['<div align="left">Test</div>', '<div align="left">Test</div>'],
|
||||
['<font href="test" size="1">Test</font>',
|
||||
'<font size="1">Test</font>'],
|
||||
];
|
||||
for (var i = 0; i < examples.length; i++) {
|
||||
var input = examples[i][0], output = examples[i][1];
|
||||
QUnit.strictEqual(Sao.HtmlSanitizer.sanitize(input), output,
|
||||
'Sao.HtmlSanitizer.sanitize(' + input + ')');
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
QUnit.test('CRUD', function() {
|
||||
var run_tests = function() {
|
||||
|
||||
Reference in new issue
Block a user