Skip to content

Instantly share code, notes, and snippets.

@ZauberNerd
Created March 8, 2012 11:08
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ZauberNerd/2000479 to your computer and use it in GitHub Desktop.
Save ZauberNerd/2000479 to your computer and use it in GitHub Desktop.
Run JavaScript code sandboxed by an iframe
var runInSandbox = (function () {
function extend(dest, src, arr) {
var property = null,
ext = '',
isArray = false,
key;
for (property in src) {
key = arr ? '[' + property + ']' : '["' + property + '"]';
ext += dest + key + ' = ';
if (typeof src[property] === 'object' && src[property] !== null) {
isArray = Object.prototype.toString.call(src[property]) === '[object Array]';
ext += dest + key + (isArray ? ' || [];' : ' || {};');
ext += extend(dest + key, src[property], isArray);
} else if (typeof src[property] === 'function') {
ext += src[property].toString() + ';';
} else if (typeof src[property] === 'string') {
ext += '"' + src[property] + '";';
} else {
ext += src[property] + ';';
}
}
return ext;
}
return function runInSandbox(code, globals, base64) {
var iframe = document.createElement('iframe'),
callbackFn = null;
iframe.style.cssText = 'position: absolute; display: none; top: -9999em; left: -9999em; z-index: -1; width: 0px; height: 0px;';
code = ',<script>(function () {' + extend('window', globals) + code + '}());</script>';
base64 && (code = ';base64,' + window.btoa(code));
iframe.src = 'data:text/html' + code;
return {
execute: function (callback) {
callbackFn = function (e) { callback && callback(e.data); };
window.addEventListener('message', callbackFn);
document.body.appendChild(iframe);
},
destroy: function () {
window.removeEventListener('message', callbackFn);
document.body.removeChild(iframe);
iframe = callbackFn = null;
}
};
}
}());
(function () {
var sandBoxGlobals = {
num: 1,
string: 'foo',
arr: [1, 2, 3],
arr2: ['1', '2', '3'],
arr3: [{ pos: 1 }, { foo: 'bar' }, { pos: 'third' }],
obj: { foo: 'bar', num: 2, bar: 'baz', obj2: { foo: 'foofoo' } },
alert: function() {
parent.postMessage({ type: 'log', func: 'alert', data: Array.prototype.slice.call(arguments).join(', ') }, '*');
},
eval: function () {
parent.postMessage({ type: 'error', func: 'eval', data: Array.prototype.slice.call(arguments).join(', ') }, '*');
},
document: {
write: function () {
parent.postMessage({ type: 'error', func: 'document.write', data: Array.prototype.slice.call(arguments).join(', ') }, '*');
}
}
},
sandBoxed = runInSandbox('alert("hi!"); eval("badcode"); document.write("booh!");', sandBoxGlobals);
sandBoxed.execute(function (data) {
console[data.type](data, data.func, data.data);
});
}());
@mghayour
Copy link

hi, thank you for this grate work.
i suggest to use "sandbox" attr of iframe to havo more security
just add iframe.setAttribute("sandbox", "allow-scripts"); in line 29

refrences:
https://medium.com/looker-engineering/iframe-sandbox-security-3cb246eacb0d
https://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment