-
-
Save aemkei/3847852 to your computer and use it in GitHub Desktop.
function sandbox(script, context){ | |
context.window = {}; | |
for (var key in context){ | |
context.window[key] = context[key]; | |
} | |
context.global = context.window; | |
eval("with (context){~function(){'use strict';" + script + "}()}"); | |
} | |
// ~115 bytes: | |
// function(e,t,n,r){r={};for(n in t)r[n]=t[n];t.window=t.global=r,eval("with(t)~function(){'use strict';"+e+"}()")} | |
var NOT_ALLOWED = function(name){ | |
return function(){ | |
console.warn(name + "(); is not allowed."); | |
return function(){}; | |
}; | |
}; | |
var scope = { | |
"alert": function(message){ console.log(message); }, | |
"Function": NOT_ALLOWED("Function"), | |
"eval": NOT_ALLOWED("eval") | |
}; | |
function test(script){ | |
try { | |
sandbox(script, scope); | |
} catch (e) { | |
console.error(e); | |
} | |
} | |
var samples = [ | |
"alert('good try');", | |
"global.alert('1');", | |
"window.alert('2');", | |
"eval('alert(3)');", | |
"~new Function('alert(4)')();", | |
"~function(){this.alert(5)}()", | |
"(function(){this.eval('good try');}).apply(null)", | |
"(function(){return this;})().alert(6)" | |
]; | |
samples.forEach(test); |
// This will fail:
sandbox("(function(){this.eval('good try');}).apply(null)", scope);
Okay, 'use strict'
might fix that.
"console.log(this, window, self, top, frames, document, parent, document.defaultView);" // should also be protected.
// could be done in line 8: context.global = context.self = context.top = context.frames = context.parent = context.window;
"setTimeout(function () { console.log(this, window); }, 100);" // "this" will be the global object.
// this might work (to be set in the scope object): "setTimeout": function (fn, time) { setTimeout(~function () { fn(); }.call(scope), time); }
"onclick=function () { console.log(this, window); };" // same here.
// how could we protect these cases? Not allowing event handlers and timeouts at all seems a little too strict.
This one break your jail:
'new (function(){}).constructor('alert("good try")')()'
test('(function*(){}).constructor("eval('alert(1337)')")().next()');
test('}}eval("alert(1337)");{+function(){');
This should work in the browser and Node.js.