Bezpośrednie wywołanie eval() wyłącza obfuskację VM
Jeśli funkcja zawiera bezpośrednie wywołanie eval(code) w dowolnym miejscu swojego ciała (również w funkcjach zagnieżdżonych), ta funkcja jest pomijana przez obfuskację VM, a obfuskator zgłasza ostrzeżenie VMDynamicCodeSkipped (wskazujące tę funkcję, jeśli ma ona nazwę). W trybie root (domyślnym) pomijana jest cała funkcja wraz ze wszystkimi zagnieżdżonymi funkcjami; w trybie komentarzy zagnieżdżona funkcja, którą oznaczysz osobno, nadal jest wirtualizowana, chyba że sama zawiera eval. Bezpośredni eval z niestatycznym argumentem zgłasza także ostrzeżenie DynamicCodeRenameRisk. Dzieje się tak, ponieważ bezpośredni eval ma dostęp do zmiennych lokalnych otaczającej funkcji, które nie są dostępne, gdy funkcja zostanie skompilowana do kodu bajtowego VM.
Ważne dla kodu opakowanego w IIFE. Jeśli IIFE najwyższego poziomu zawiera gdziekolwiek w głębi bezpośredni eval, całe IIFE (wraz z całym Twoim kodem) nie zostanie objęte obfuskacją VM.
Rozpakowanie IIFE ma swoją cenę: gdy funkcje znajdą się na najwyższym poziomie, pomijana jest tylko problematyczna funkcja, ale pozostałe funkcje stają się funkcjami poziomu głównego, więc obfuskacja VM zachowuje ich nazwy. Jak usunąć te nazwy z wyniku, opisuje przewodnik Ukrywanie nazw funkcji przed analizą LLM.
Formy pośrednie, takie jak (0, eval)(code) i window.eval(code), nie blokują obfuskacji VM. Wyjątkiem jest eval?.(code): JavaScript wykonuje je jako pośredni eval, ale obfuskator zachowawczo traktuje je jak bezpośredni eval i pomija funkcję.
Konstruktor Function (new Function(body) / Function(body)) jest traktowany tak samo, gdy argument z ciałem funkcji jest dynamiczny. Funkcja zawierająca dynamiczne wywołanie new Function(...) również jest pomijana, z ostrzeżeniem VMDynamicCodeSkipped. Tak jak przy dynamicznym bezpośrednim eval, obfuskator dodaje ostrzeżenie DynamicCodeRenameRisk, ponieważ ciało budowane w czasie wykonania może odwoływać się do identyfikatorów o zmienionych nazwach. W pełni statyczne wywołania, takie jak new Function('a', 'b', 'return a + b'), nie są pomijane.
Pośredni eval i konstruktor Function wykonują się w zakresie globalnym. Nie mogą odczytać zmiennych lokalnych wywołującego, ale nadal mogą zawieść, jeśli odwołują się do zmiennych globalnych, których nazwy zmieniono lub które usunięto. Statyczne ciało korzystające wyłącznie z własnych parametrów, np. new Function('a', 'b', 'return a + b'), unika tej zależności. Sprawdzaj ostrzeżenia i testuj końcowy bundle; sama zmiana składni eval nie sprawia, że dowolny dynamiczny kod staje się bezpieczny.
Furtka awaryjna (v6.14.0+): ustaw vmForceCompileDynamicCode: true (lub włącz przełącznik Force Compile Dynamic Code w grupie Nadpisania sekcji VM), aby mimo to skompilować otaczającą funkcję do kodu bajtowego i wyciszyć VMDynamicCodeSkipped. Nie naprawia to zakresu: wewnątrz funkcji skompilowanej w ten sposób bezpośredni eval nie może odczytywać ani zapisywać zmiennych lokalnych funkcji, jej parametrów ani zmiennych zwirtualizowanej funkcji otaczającej, nawet gdy kod jest literałem tekstowym. Używaj tej opcji tylko wtedy, gdy wykonywany kod odwołuje się wyłącznie do zmiennych globalnych. Ostrzeżenie DynamicCodeRenameRisk jest zgłaszane nadal, także przy włączonej tej opcji, ponieważ opisywane przez nie ryzyko związane ze zmianą nazw nie zależy od pominięcia przez VM.
Pełną macierz przypadków, postać ostrzeżeń i obejścia opisuje strona Obfuskacja VM a eval i new Function.
