직접 eval()은 VM 난독화를 비활성화합니다
함수 본문 어디에든(중첩 함수 포함) 직접 eval(code) 호출이 있으면, 그 함수는 VM 난독화에서 제외되고 난독화 도구는 VMDynamicCodeSkipped 경고를 보고합니다(함수에 이름이 있으면 그 이름을 지목합니다). root 모드(기본값)에서는 그 함수 전체와 모든 중첩 함수가 제외됩니다. comment 모드에서는 별도로 표시한 중첩 함수가 eval을 직접 포함하지 않는 한 여전히 가상화됩니다. 인수가 정적이지 않은 직접 eval은 DynamicCodeRenameRisk 경고도 내보냅니다. 직접 eval은 자신을 둘러싼 함수의 지역 변수에 접근할 수 있는데, 함수가 VM 바이트코드로 컴파일되면 그 지역 변수를 사용할 수 없기 때문입니다.
IIFE로 감싼 코드에서 중요합니다. 최상위 IIFE 안 깊은 곳에 직접 eval이 하나라도 있으면, IIFE 전체(여러분의 모든 코드 포함)가 VM 난독화되지 않습니다.
IIFE를 풀어내는 데에는 트레이드오프가 있습니다. 함수들이 최상위에 놓이면 문제가 되는 함수만 제외되지만, 남은 함수들은 이제 루트 수준 함수가 되므로 VM 난독화가 그 이름을 보존합니다. 그 이름을 출력에서 숨기는 방법은 LLM 분석으로부터 함수 이름 숨기기를 참고하세요.
(0, eval)(code)나 window.eval(code) 같은 간접 형태는 VM 난독화를 막지 않습니다. 단, eval?.(code)는 예외입니다. JavaScript는 이를 간접 eval로 실행하지만, 난독화 도구는 보수적으로 직접 eval로 취급해 해당 함수를 제외합니다.
Function 생성자(new Function(body) / Function(body))도 본문 인수가 동적이면 같은 방식으로 처리됩니다. 동적인 new Function(...) 호출을 포함한 함수도 VMDynamicCodeSkipped 경고와 함께 제외됩니다. 동적 직접 eval과 마찬가지로, 런타임에 만들어지는 본문이 이름이 바뀐 식별자를 참조할 수 있으므로 난독화 도구는 DynamicCodeRenameRisk 경고를 추가합니다. new Function('a', 'b', 'return a + b')처럼 완전히 정적인 호출은 제외되지 않습니다.
간접 eval과 Function 생성자는 전역 스코프에서 실행됩니다. 호출한 쪽의 지역 변수를 읽을 수는 없지만, 이름이 바뀌었거나 제거된 전역을 참조하면 여전히 실패할 수 있습니다. new Function('a', 'b', 'return a + b')처럼 자신의 매개변수만 사용하는 정적 본문은 이런 의존성을 피합니다. 경고를 검토하고 최종 번들을 테스트하세요. eval 구문만 바꾼다고 임의의 동적 코드가 안전해지지는 않습니다.
비상 탈출구 (v6.14.0+): vmForceCompileDynamicCode: true를 설정하면(또는 VM 섹션의 재정의 그룹에서 Force Compile Dynamic Code 스위치를 켜면) 둘러싼 함수를 그래도 바이트코드로 변환하고 VMDynamicCodeSkipped를 표시하지 않습니다. 이 옵션은 스코프 문제를 고쳐 주지 못합니다. 강제로 컴파일된 함수 안에서 직접 eval은 코드가 문자열 리터럴이더라도 그 함수의 지역 변수, 매개변수, 가상화된 바깥 함수의 변수를 읽거나 쓸 수 없습니다. 평가되는 코드가 전역만 참조할 때만 사용하세요. 이 옵션을 켜도 DynamicCodeRenameRisk는 계속 발생합니다. 이 경고가 설명하는 이름 변경 위험은 VM 제외와 무관하기 때문입니다.
전체 매트릭스, 경고 형태, 해결 방법은 eval 및 new Function과 함께 VM 난독화 사용하기 문서를 참고하세요.
