- Security fix/Breaking change (Imagelib): Require allowedImageLibOrigins
config array be set with safe origins or otherwise reject `postMessage` messages in case from untrusted sources - Security fix/Breaking change (xdomain): Namespace xdomain file to avoid it being used to modify non-xdomain storage - Security fix (Imagelib): Expose `dropXMLInternalSubset` to extensions for preventing billion laughs attack (and use in Imagelib)
This commit is contained in:
@@ -32,7 +32,7 @@ export default {
|
||||
// Must match the icon ID in helloworld-icon.xml
|
||||
id: 'hello_world',
|
||||
|
||||
// Fallback, e.g., for `file://` access
|
||||
// Fallback, e.g., for `file:///` access
|
||||
icon: svgEditor.curConfig.extIconsPath + 'helloworld.png',
|
||||
|
||||
// This indicates that the button will be added to the "mode"
|
||||
|
||||
@@ -9,12 +9,12 @@
|
||||
*/
|
||||
export default {
|
||||
name: 'imagelib',
|
||||
async init ({decode64, importLocale}) {
|
||||
async init ({decode64, importLocale, dropXMLInteralSubset}) {
|
||||
const imagelibStrings = await importLocale();
|
||||
const svgEditor = this;
|
||||
|
||||
const $ = jQuery;
|
||||
const {uiStrings, canvas: svgCanvas} = svgEditor;
|
||||
const {uiStrings, canvas: svgCanvas, curConfig: {allowedImageLibOrigins}} = svgEditor;
|
||||
|
||||
function closeBrowser () {
|
||||
$('#imgbrowse_holder').hide();
|
||||
@@ -44,10 +44,8 @@ export default {
|
||||
let transferStopped = false;
|
||||
let preview, submit;
|
||||
|
||||
window.addEventListener('message', function (evt) {
|
||||
// Receive `postMessage` data
|
||||
let response = evt.data;
|
||||
|
||||
// Receive `postMessage` data
|
||||
window.addEventListener('message', function ({origin, data: response}) {
|
||||
if (!response || typeof response !== 'string') {
|
||||
// Do nothing
|
||||
return;
|
||||
@@ -60,6 +58,10 @@ export default {
|
||||
if (response.namespace !== 'imagelib') {
|
||||
return;
|
||||
}
|
||||
if (!allowedImageLibOrigins.includes('*') && !allowedImageLibOrigins.includes(origin)) {
|
||||
console.log(`Origin ${origin} not whitelisted for posting to ${window.origin}`);
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
@@ -90,7 +92,8 @@ export default {
|
||||
transferStopped = false;
|
||||
curMeta = response;
|
||||
|
||||
pending[curMeta.id] = curMeta;
|
||||
// Should be safe to add dynamic property as passed metadata
|
||||
pending[curMeta.id] = curMeta; // lgtm [js/remote-property-injection]
|
||||
|
||||
const name = (curMeta.name || 'file');
|
||||
|
||||
@@ -170,7 +173,8 @@ export default {
|
||||
title = curMeta.name;
|
||||
} else {
|
||||
// Try to find a title
|
||||
const xml = new DOMParser().parseFromString(response, 'text/xml').documentElement;
|
||||
// `dropXMLInteralSubset` is to help prevent the billion laughs attack
|
||||
const xml = new DOMParser().parseFromString(dropXMLInteralSubset(response), 'text/xml').documentElement; // lgtm [js/xml-bomb]
|
||||
title = $(xml).children('title').first().text() || '(SVG #' + response.length + ')';
|
||||
}
|
||||
if (curMeta) {
|
||||
|
||||
@@ -19,7 +19,7 @@ export default {
|
||||
return;
|
||||
}
|
||||
// The default is not to allow any origins, including even the same domain or
|
||||
// if run on a file:// URL See svgedit-config-es.js for an example of how
|
||||
// if run on a `file:///` URL. See `svgedit-config-es.js` for an example of how
|
||||
// to configure
|
||||
const {allowedOrigins} = svgEditor.curConfig;
|
||||
if (!allowedOrigins.includes('*') && !allowedOrigins.includes(e.origin)) {
|
||||
|
||||
@@ -31,7 +31,7 @@ $('a').click(function () {
|
||||
try {
|
||||
data = canvas.toDataURL();
|
||||
} catch (err) {
|
||||
// This fails in Firefox with file:// URLs :(
|
||||
// This fails in Firefox with `file:///` URLs :(
|
||||
alert('Data URL conversion failed: ' + err);
|
||||
data = '';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user