Documentación
/
Ofuscación VM
/

Comportamiento de eval directo

El eval() directo desactiva la ofuscación VM

Si una función contiene una llamada directa eval(code) en cualquier parte de su cuerpo (también en funciones anidadas), la ofuscación VM omite esa función y el ofuscador emite una advertencia VMDynamicCodeSkipped (que nombra la función cuando tiene nombre). En el modo root (el predeterminado) se omiten toda la función y todas sus funciones anidadas; en el modo comment, una función anidada que marques por separado se sigue virtualizando, salvo que contenga ella misma el eval. Un eval directo con un argumento no estático también emite una advertencia DynamicCodeRenameRisk. Esto se debe a que el eval directo tiene acceso a las variables locales de la función que lo contiene, y esas variables no están disponibles cuando la función se compila a bytecode de la VM.

Importante para el código envuelto en una IIFE. Si una IIFE de nivel superior contiene un eval directo en cualquier punto de su interior, toda la IIFE (incluido todo tu código) no se ofuscará con VM.

JavaScript

Desenvolver la IIFE tiene una contrapartida: una vez que tus funciones están en el nivel superior, solo se omite la función problemática, pero las funciones restantes pasan a estar en el nivel raíz, así que la ofuscación VM conserva sus nombres. Consulta Ocultar los nombres de las funciones al análisis con LLM para saber cómo mantener esos nombres fuera de la salida.

Las formas indirectas como (0, eval)(code) y window.eval(code) no bloquean la ofuscación VM. eval?.(code) es una excepción: JavaScript lo ejecuta como eval indirecto, pero el ofuscador lo trata de forma conservadora como eval directo y omite la función.

El constructor Function (new Function(body) / Function(body)) se trata igual cuando el argumento del cuerpo es dinámico. Una función que contiene una llamada dinámica a new Function(...) también se omite, con una advertencia VMDynamicCodeSkipped. Igual que con un eval directo dinámico, el ofuscador añade una advertencia DynamicCodeRenameRisk, porque el cuerpo construido en tiempo de ejecución puede hacer referencia a identificadores renombrados. Las llamadas totalmente estáticas como new Function('a', 'b', 'return a + b') no se omiten.

El eval indirecto y el constructor Function se ejecutan en el ámbito global. No pueden leer las variables locales de quien los llama, pero aun así pueden fallar si hacen referencia a variables globales que se renombraron o eliminaron. Un cuerpo estático que solo usa sus propios parámetros, como new Function('a', 'b', 'return a + b'), evita esa dependencia. Revisa las advertencias y prueba el bundle final; cambiar solo la sintaxis del eval no hace que un código dinámico arbitrario sea seguro.

Vía de escape (v6.14.0+): establece vmForceCompileDynamicCode: true (o activa el interruptor Force Compile Dynamic Code en el grupo Anulaciones de la sección VM) para convertir a bytecode la función que lo rodea de todos modos y suprimir VMDynamicCodeSkipped. No puede reparar el ámbito: dentro de una función compilada a la fuerza, el eval directo no puede leer ni escribir las variables locales de la función, sus parámetros ni las variables de una función envolvente virtualizada, aunque el código sea un literal de cadena. Úsalo solo cuando el código evaluado no haga referencia más que a variables globales. DynamicCodeRenameRisk se sigue emitiendo con esta opción activada, porque el riesgo de renombrado que describe es independiente de la omisión de la VM.

Consulta Ofuscación VM con eval y new Function para ver la matriz completa, la forma de las advertencias y las soluciones alternativas.