-
-
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.