Vm2: Algum motivo pelo qual a maioria dos módulos integrados é proxy em vez de ser necessária na sandbox?

Criado em 17 out. 2017  ·  5Comentários  ·  Fonte: patriksimek/vm2

Oi,
Estou tentando descobrir por que os módulos internos são proxy do host e não são necessários no vm.

esta é a minha configuração atualmente:

const vm = new NodeVM({
        require: {
            external: true,
            context: 'sandbox',
            builtin: ['*'],
        },
    });

vm.run(...);

dentro da VM eu exijo um módulo externo ( axios se isso importa) e na cadeia de dependências requer outro módulo ( follow-redirects ) que faz isso (mais ou menos):

var Writable = require('stream').Writable;

function RedirectableRequest(options, responseCallback) {
// .....
}

RedirectableRequest.prototype = Object.create(Writable.prototype);

RedirectableRequest.prototype._performRequest = function () {  // <-------- this line breaks
// ..........
}

executar este código dentro do vm lança: TypeError: 'set' on proxy: trap retornou false para a propriedade '_performRequest'.
O objeto de fluxo está sendo proxy para o vm.

executar este código quando stream está sendo realmente necessário dentro da vm (removendo a instrução if aqui: https://github.com/patriksimek/vm2/blob/master/lib/sandbox.js#L133) é trabalhando.

executando o nó 6.10.3 no osx.

Obrigado

stale

Comentários muito úteis

Também encontrei uma solução alternativa (uma que acho que se encaixa melhor no paradigma).

Basicamente o que eu encontrei foi que o código contextualizado estava tentando escrever em um protótipo de um objeto que ele criou em seu contexto, mas que estendeu um objeto trazido de outro contexto.

De acordo com a documentação do manipulador de proxy set, se a propriedade não existir no objeto que você está tentando definir, o manipulador de conjunto de protótipo será chamado.

Assim;
Objeto
protótipo
a <-Definindo isso (que na verdade não existe no protótipo)
__proto__ (proxy)
set: (){} <- Na verdade chama isso

E quando o manipulador set for chamado, o argumento receiver será definido para o objeto original que estávamos tentando definir. Minha solução foi essa:

--- a/node_modules/vm2/lib/contextify.js
+++ b/node_modules/vm2/lib/contextify.js
@@ -17,7 +17,23 @@ const DEBUG = false;
 const OPNA = 'Operation not allowed on contextified object.';
 const ERROR_CST = Error.captureStackTrace;
 const FROZEN_TRAPS = {
-   set: (target, key) => false,
+   set: (target, key, value, receiver) => {
+       if( target !== receiver ){
+
+           Object.defineProperty(receiver, key, {
+               value: value,
+               writable: true,
+               enumerable: true,
+               configurable: true
+           })
+
+           return true;
+
+       }
+
+       return false;
+
+   },

Todos 5 comentários

relacionado a #127

Eu fui em frente e mudei a instrução if para:

if( vm.options.require.context === 'sandbox' && modulename !== 'async_hooks' ){

Descobri que no nó 8.x tive problemas com async_hooks

Também encontrei uma solução alternativa (uma que acho que se encaixa melhor no paradigma).

Basicamente o que eu encontrei foi que o código contextualizado estava tentando escrever em um protótipo de um objeto que ele criou em seu contexto, mas que estendeu um objeto trazido de outro contexto.

De acordo com a documentação do manipulador de proxy set, se a propriedade não existir no objeto que você está tentando definir, o manipulador de conjunto de protótipo será chamado.

Assim;
Objeto
protótipo
a <-Definindo isso (que na verdade não existe no protótipo)
__proto__ (proxy)
set: (){} <- Na verdade chama isso

E quando o manipulador set for chamado, o argumento receiver será definido para o objeto original que estávamos tentando definir. Minha solução foi essa:

--- a/node_modules/vm2/lib/contextify.js
+++ b/node_modules/vm2/lib/contextify.js
@@ -17,7 +17,23 @@ const DEBUG = false;
 const OPNA = 'Operation not allowed on contextified object.';
 const ERROR_CST = Error.captureStackTrace;
 const FROZEN_TRAPS = {
-   set: (target, key) => false,
+   set: (target, key, value, receiver) => {
+       if( target !== receiver ){
+
+           Object.defineProperty(receiver, key, {
+               value: value,
+               writable: true,
+               enumerable: true,
+               configurable: true
+           })
+
+           return true;
+
+       }
+
+       return false;
+
+   },

Qual é o estado? Projeto morto?

Este problema foi marcado automaticamente como obsoleto porque não teve atividade recente. Será fechado se não ocorrer mais nenhuma atividade. Obrigado por suas contribuições.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

XmiliaH picture XmiliaH  ·  19Comentários

keyosk picture keyosk  ·  64Comentários

vshymanskyy picture vshymanskyy  ·  8Comentários

unxcepted picture unxcepted  ·  11Comentários

CapacitorSet picture CapacitorSet  ·  13Comentários