Domanda

Voglio creare un ambiente HTML + JS in cui l'utente può entrare ed eseguire il codice JavaScript arbitrario che verrà eseguito nel contesto dell'oggetto di prigione specificato. Ho impostato un Playground per illustrare ciò che ho finora .

Questo fa un lavoro un po 'decente:

    .
  • Lavori di valutazione di base:
      .
    • Input: 2 + 2
    • Uscita: 4
  • this restituisce l'oggetto prigione
      .
    • Input: this
    • Uscita: [object Object]
  • this.hello() esegue il metodo previsto
      .
    • Input: this.hello()
    • Uscita: hello world!
  • L'utente può impostare le proprie funzioni ed eseguirli in seguito:
      .
    • Input: this.foo = function() { return 42; }
    • Uscita: function () { return 42; }
    • Input: this.foo()
    • ouput: 42
  • Cercando di accedere ad alcuni oggetti che voglio rimanere "nascosto" dal contesto di prigione fallisce:
      .
    • Input: hidden
    • Uscita: ReferenceError: hidden is not defined

Tuttavia, non riesce completamente a nascondere le proprietà accessibili a livello globale, ad esempio window o document per l'utente:

    .
  • Input: window
  • Uscita corrente: [object Window]
  • Uscita desiderata: ReferenceError: window is not defined

La soluzione migliore che ho trovato finora è semplicemente riempire tutta la variabile globale che posso pensare con undefined o null direttamente nella dichiarazione dell'oggetto della prigione, come illustrato in versione aggiornata . In questo modo sembrano essere persi per sempre all'interno della portata della prigione e dell'utente non saranno in grado di accedervi. Le mie domande:

    .
  • sono giusto? È abbastanza sicuro?
  • C'è un modo migliore, cioè a veramente undefine roba globale in determinati ambito invece di riscriverle con alcuni valori segnapunti?
È stato utile?

Soluzione

Se è lato client e puoi garantire un browser moderno, utilizzare I lavoratori Web invece; Sono molto più sicuri, e puoi anche interrompere infiniti loop di legare il thread principale e implementare timeout chiamando Worker#terminate.

Avvia un nuovo lavoratore per ogni esecuzione:

var worker = new Worker('path/to/evaluator.js');
.

Ricevi messaggi dal lavoratore:

worker.onmessage = function (e) {
    console.log(e.data);
};
.

Invia il codice da eseguire:

worker.postMessage(someCode);
.

Nel lavoratore, ascolta:

onmessage = function (e) {
    postMessage(eval(e.data));
};
.

e assicurati di chiamare terminate dopo aver ricevuto il messaggio, perché il lavoratore può chiamare postMessage stesso. (Puoi impedirlo, ma non c'è davvero alcun punto.)

I lavoratori Web non hanno accesso a nulla nel contesto di esecuzione principale, funzionano su un altro thread, e sono implementati dal browser, quindi sono molto più sicuri della tipica sandbox eliminata-pericolosa-cose. < / P >.

loro fanno , tuttavia, hanno accesso a XMLHttpRequest; Vedi È possibile sandbox javascript Nel browser? per altri approcci se questo è un problema.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top