In una ricerca per avere un'interfaccia in grado di eseguire codice javascript arbitrario all'interno del browser, senza avere un buco di sicurezza delle dimensioni di un tipico scherzo yo-mama, Esailija proposto utilizzando Web Workers. Funzionano in un ambiente semi-sandbox (nessun accesso DOM e già all'interno del browser) e possono essere uccisi in modo che l'utente non possa inserirli in un ciclo infinito.Rendere un WebWorkers un ambiente sicuro
Ecco l'esempio ha portato fino: http://tuohiniemi.fi/~runeli/petka/workertest.html (aprire la console)
jsfiddle (Google Chrome solo)
Ora, questa sembra una buona soluzione; tuttavia, è completo (o si avvicina completo)? C'è qualcosa di evidente mancante?
L'intera cosa (come è collegato a un bot) si possono trovare su github: worker, evaluator
principale:
workercode = "worker.js";
function makeWorkerExecuteSomeCode(code, callback) {
var timeout;
code = code + "";
var worker = new Worker(workercode);
worker.addEventListener("message", function(event) {
clearTimeout(timeout);
callback(event.data);
});
worker.postMessage({
code: code
});
timeout = window.setTimeout(function() {
callback("Maximum execution time exceeded");
worker.terminate();
}, 1000);
}
makeWorkerExecuteSomeCode('5 + 5', function(answer){
console.log(answer);
});
makeWorkerExecuteSomeCode('while(true);', function(answer){
console.log(answer);
});
var kertoma = 'function kertoma(n){return n === 1 ? 1 : n * kertoma(n-1)}; kertoma(15);';
makeWorkerExecuteSomeCode(kertoma, function(answer){
console.log(answer);
});
lavoratore:
var global = this;
/* Could possibly create some helper functions here so they are always available when executing code in chat?*/
/* Most extra functions could be possibly unsafe */
var wl = {
"self": 1,
"onmessage": 1,
"postMessage": 1,
"global": 1,
"wl": 1,
"eval": 1,
"Array": 1,
"Boolean": 1,
"Date": 1,
"Function": 1,
"Number" : 1,
"Object": 1,
"RegExp": 1,
"String": 1,
"Error": 1,
"EvalError": 1,
"RangeError": 1,
"ReferenceError": 1,
"SyntaxError": 1,
"TypeError": 1,
"URIError": 1,
"decodeURI": 1,
"decodeURIComponent": 1,
"encodeURI": 1,
"encodeURIComponent": 1,
"isFinite": 1,
"isNaN": 1,
"parseFloat": 1,
"parseInt": 1,
"Infinity": 1,
"JSON": 1,
"Math": 1,
"NaN": 1,
"undefined": 1
};
Object.getOwnPropertyNames(global).forEach(function(prop) {
if(!wl.hasOwnProperty(prop)) {
Object.defineProperty(global, prop, {
get : function() {
throw new Error("Security Exception: cannot access "+prop);
return 1;
},
configurable : false
});
}
});
Object.getOwnPropertyNames(global.__proto__).forEach(function(prop) {
if(!wl.hasOwnProperty(prop)) {
Object.defineProperty(global.__proto__, prop, {
get : function() {
throw new Error("Security Exception: cannot access "+prop);
return 1;
},
configurable : false
});
}
});
onmessage = function(event) {
"use strict";
var code = event.data.code;
var result;
try {
result = eval('"use strict";\n'+code);
}
catch(e){
result = e.toString();
}
postMessage("(" + typeof result + ")" + " " + result);
};
Non sarebbero ancora in grado di inviare richieste AJAX? – SLaks
@SLaks L'operatore ha XHR impostato su 'null' – Esailija
@SLaks È possibile rimuovere manualmente un gruppo di proprietà non protette, come mostrato nell'esempio. – Zirak