- Security fix (minor): For embedded API, avoid chance for arbitrary property

setting (though this was only for trusted origins anyways)
- Security fix (minor): For embedded API example, copy params to iframe
    source without XSS risk (though params should already be XML-safe
    given `encodeURIComponent` and lack of a single quote attribute context)
- Linting (LGTM): Flag origin-checked item as safe
- Refactoring: Destructuring, ellipsis
- Docs (JSDoc): Missing return value
This commit is contained in:
Brett Zamir
2018-09-22 10:06:25 +08:00
parent dab1ff81af
commit fbffc86503
4 changed files with 27 additions and 12 deletions

View File

@@ -7,6 +7,16 @@ var svgEditorExtension_xdomain_messaging = (function () {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
}; };
var toConsumableArray = function (arr) {
if (Array.isArray(arr)) {
for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
return arr2;
} else {
return Array.from(arr);
}
};
/** /**
* Should not be needed for same domain control (just call via child frame), * Should not be needed for same domain control (just call via child frame),
* but an API common for cross-domain and same domain use can be found * but an API common for cross-domain and same domain use can be found
@@ -45,7 +55,9 @@ var svgEditorExtension_xdomain_messaging = (function () {
id: cbid id: cbid
}; };
try { try {
message.result = svgCanvas[name].apply(svgCanvas, args); // Now that we know the origin is trusted, we perform otherwise
// unsafe arbitrary canvas method execution
message.result = svgCanvas[name].apply(svgCanvas, toConsumableArray(args)); // lgtm [js/remote-property-injection]
} catch (err) { } catch (err) {
message.error = err.message; message.error = err.message;
} }

View File

@@ -68,12 +68,12 @@ $('#exportPDF').click(exportPDF);
const frameBase = 'https://raw.githack.com/SVG-Edit/svgedit/master'; const frameBase = 'https://raw.githack.com/SVG-Edit/svgedit/master';
// const frameBase = 'http://localhost:8001'; // const frameBase = 'http://localhost:8001';
const framePath = '/editor/xdomain-svg-editor-es.html?extensions=ext-xdomain-messaging.js'; const framePath = '/editor/xdomain-svg-editor-es.html?extensions=ext-xdomain-messaging.js';
const iframe = $(`<iframe src="${frameBase}${framePath}` + const iframe = $('<iframe width="900px" height="600px" id="svgedit"></iframe>');
iframe[0].src = frameBase + framePath +
(location.href.includes('?') (location.href.includes('?')
? location.href.replace(/\?(.*)$/, '&$1') ? location.href.replace(/\?(.*)$/, '&$1')
: '') + // Append arguments to this file onto the iframe : ''); // Append arguments to this file onto the iframe
'" width="900px" height="600px" id="svgedit""></iframe>'
);
iframe[0].addEventListener('load', function () { iframe[0].addEventListener('load', function () {
svgCanvas = new EmbeddedSVGEdit(frame, [new URL(frameBase).origin]); svgCanvas = new EmbeddedSVGEdit(frame, [new URL(frameBase).origin]);
// Hide main button, as we will be controlling new, load, save, etc. from the host document // Hide main button, as we will be controlling new, load, save, etc. from the host document

View File

@@ -44,14 +44,14 @@ function getCallbackSetter (funcName) {
* @param {JSON} data * @param {JSON} data
* @returns {undefined} * @returns {undefined}
*/ */
function addCallback (t, data) { function addCallback (t, {result, error, id: cbid}) {
const result = data.result || data.error, if (typeof cbid === 'number' && t.callbacks[cbid]) {
cbid = data.id; // These should be safe both because we check `cbid` is numeric and
if (t.callbacks[cbid]) { // because the calls are from trusted origins
if (data.result) { if (result) {
t.callbacks[cbid](result); t.callbacks[cbid](result);
} else { } else {
t.callbacks[cbid](result, 'error'); t.callbacks[cbid](error, 'error');
} }
} }
} }
@@ -340,6 +340,7 @@ class EmbeddedSVGEdit {
* @param {string} name * @param {string} name
* @param {ArgumentsArray} args Signature dependent on function * @param {ArgumentsArray} args Signature dependent on function
* @param {module:EmbeddedSVGEdit.GenericCallback} callback * @param {module:EmbeddedSVGEdit.GenericCallback} callback
* @returns {Integer}
*/ */
send (name, args, callback) { send (name, args, callback) {
const t = this; const t = this;

View File

@@ -33,7 +33,9 @@ export default {
id: cbid id: cbid
}; };
try { try {
message.result = svgCanvas[name].apply(svgCanvas, args); // Now that we know the origin is trusted, we perform otherwise
// unsafe arbitrary canvas method execution
message.result = svgCanvas[name](...args); // lgtm [js/remote-property-injection]
} catch (err) { } catch (err) {
message.error = err.message; message.error = err.message;
} }