Documentação
/
Ofuscação VM
/

Comportamento do eval direto

O eval() direto desativa a ofuscação VM

Se uma função contém uma chamada direta eval(code) em qualquer ponto do seu corpo (inclusive em funções aninhadas), essa função é ignorada pela ofuscação VM, e o ofuscador emite um aviso VMDynamicCodeSkipped (que identifica a função quando ela tem nome). No modo root (o padrão), a função inteira e todas as suas funções aninhadas são ignoradas; no modo comment, uma função aninhada que você marca separadamente ainda é virtualizada, a menos que ela mesma contenha o eval. Um eval direto com argumento não estático também emite um aviso DynamicCodeRenameRisk. Isso acontece porque o eval direto tem acesso às variáveis locais da função que o envolve, que não estão disponíveis quando a função é compilada em bytecode da VM.

Importante para código envolvido em IIFE. Se uma IIFE de nível superior contém qualquer eval direto em algum ponto interno, a IIFE inteira (incluindo todo o seu código) não recebe a ofuscação VM.

JavaScript

Desembrulhar a IIFE tem um custo: quando suas funções ficam no nível superior, só a função problemática é ignorada, mas as funções restantes passam a ser de nível raiz, então a ofuscação VM preserva os nomes delas. Veja em Escondendo nomes de funções da análise por LLM como manter esses nomes fora da saída.

Formas indiretas como (0, eval)(code) e window.eval(code) não bloqueiam a ofuscação VM. eval?.(code) é uma exceção: o JavaScript o executa como eval indireto, mas o ofuscador, de forma conservadora, o trata como eval direto e ignora a função.

O construtor Function (new Function(body) / Function(body)) é tratado da mesma forma quando o argumento do corpo é dinâmico. Uma função que contém uma chamada dinâmica a new Function(...) também é ignorada, com um aviso VMDynamicCodeSkipped. Assim como em um eval direto dinâmico, o ofuscador adiciona um aviso DynamicCodeRenameRisk, porque o corpo montado em tempo de execução pode referenciar identificadores renomeados. Chamadas totalmente estáticas, como new Function('a', 'b', 'return a + b'), não são ignoradas.

O eval indireto e o construtor Function executam no escopo global. Eles não conseguem ler as variáveis locais de quem os chama, mas ainda podem falhar se referenciarem globais que foram renomeados ou removidos. Um corpo estático que usa apenas os próprios parâmetros, como new Function('a', 'b', 'return a + b'), evita essa dependência. Revise os avisos e teste o bundle final; mudar apenas a sintaxe do eval não torna seguro um código dinâmico arbitrário.

Válvula de escape (v6.14.0+): defina vmForceCompileDynamicCode: true (ou ative a chave Force Compile Dynamic Code no grupo Sobrescritas da seção VM) para compilar em bytecode a função ao redor mesmo assim e suprimir VMDynamicCodeSkipped. Isso não corrige o escopo: dentro de uma função compilada à força, o eval direto não consegue ler nem escrever as variáveis locais da função, os parâmetros dela ou as variáveis de uma função externa virtualizada, mesmo quando o código é uma string literal. Use-a apenas quando o código avaliado não referenciar nada além de globais. DynamicCodeRenameRisk continua sendo emitido com essa opção ativada, porque o risco de renomeação que ele descreve independe de a VM ignorar a função.

Veja Ofuscação VM com eval e new Function para a matriz completa, o formato dos avisos e as soluções alternativas.