Referencia de opciones
Contenido
compact
config
controlFlowFlattening
controlFlowFlatteningThreshold
deadCodeInjection
deadCodeInjectionThreshold
debugProtection
debugProtectionInterval
disableConsoleOutput
domainLock
Varios dominios y subdominios
domainLockRedirectUrl
exclude
forceTransformStrings
identifierNamesCache
API de Node.js
CLI
identifierNamesGenerator
identifiersDictionary
identifiersPrefix
randomIdentifiersPrefix
ignoreImports
inputFileName
log
numbersToExpressions
optionsPreset
parseHtml
renameGlobals
renameProperties
renamePropertiesMode
reservedNames
reservedStrings
seed
selfDefending
simplify
sourceMap
sourceMapBaseUrl
sourceMapFileName
sourceMapMode
sourceMapSourcesMode
splitStrings
splitStringsChunkLength
stringArray
stringArrayCallsTransform
stringArrayCallsTransformThreshold
stringArrayEncoding
stringArrayIndexesType
stringArrayIndexShift
stringArrayRotate
stringArrayShuffle
stringArrayWrappersCount
stringArrayWrappersChainedCalls
stringArrayWrappersParametersMaxCount
stringArrayWrappersType
stringArrayThreshold
strictMode
target
transformObjectKeys
warnings
vmObfuscation
vmTargetFunctions
vmExcludeFunctions
vmTargetFunctionsMode
vmForceCompileDynamicCode
vmWrapTopLevelInitializers
vmDynamicOpcodes
vmBytecodeEncoding
vmBytecodeArrayEncoding
vmBytecodeArrayEncodingKey
vmBytecodeArrayEncodingKeyGetter
vmAsyncExecutor
vmJumpsEncoding
vmMacroOps
vmDebugProtection
vmSelfDefending
vmDefenseHook
vmDefenseReaction
vmStatefulOpcodes
vmCallContextOpcodes
vmStackEncoding
vmCompactDispatcher
vmStringArrayBytecodeOnly
vmDomainLock
Varios dominios y subdominios
vmDomainLockRedirectUrl
Preset Options
Ofuscación alta, rendimiento bajo
Ofuscación media, rendimiento óptimo
Ofuscación baja, rendimiento alto
Preajuste predeterminado, rendimiento alto
Ofuscación VM Ultra High (seguridad máxima)
VM Anti-LLM (protección contra agentes de IA)
Ofuscación VM High (seguridad más alta)
Ofuscación VM Medium (seguridad equilibrada)
Ofuscación VM Low (seguridad básica, mejor rendimiento)
VM Default (VM + protección con String Array)
compact
Type: boolean Default: true
Compacta el código de salida en una sola línea.
config
Type: string Default: ``
Nombre del archivo de configuración JS/JSON que contiene las opciones del ofuscador. Estas serán anuladas por las opciones pasadas directamente a la CLI
controlFlowFlattening
Type: boolean Default: false
⚠️ Esta opción afecta enormemente al rendimiento, con una velocidad de ejecución hasta 1,5 veces más lenta. Usa controlFlowFlatteningThreshold para establecer el porcentaje de nodos que se verán afectados por el aplanamiento del flujo de control.
Activa el aplanamiento del flujo de control del código. El aplanamiento del flujo de control es una transformación de la estructura del código fuente que dificulta la comprensión del programa.
Ejemplo:
// input
(function(){
function foo () {
return function () {
var sum = 1 + 2;
console.log(1);
console.log(2);
console.log(3);
console.log(4);
console.log(5);
console.log(6);
}
}
foo()();
})();
// output
(function () {
function _0x3bfc5c() {
return function () {
var _0x3260a5 = {
'WtABe': '4|0|6|5|3|2|1',
'GokKo': function _0xf87260(_0x427a8e, _0x43354c) {
return _0x427a8e + _0x43354c;
}
};
var _0x1ad4d6 = _0x3260a5['WtABe']['split']('|'), _0x1a7b12 = 0x0;
while (!![]) {
switch (_0x1ad4d6[_0x1a7b12++]) {
case '0':
console['log'](0x1);
continue;
case '1':
console['log'](0x6);
continue;
case '2':
console['log'](0x5);
continue;
case '3':
console['log'](0x4);
continue;
case '4':
var _0x1f2f2f = _0x3260a5['GokKo'](0x1, 0x2);
continue;
case '5':
console['log'](0x3);
continue;
case '6':
console['log'](0x2);
continue;
}
break;
}
};
}
_0x3bfc5c()();
}());
controlFlowFlatteningThreshold
Type: number Default: 0.75 Min: 0 Max: 1
La probabilidad de que la transformación controlFlowFlattening se aplique a un nodo concreto.
Este ajuste resulta especialmente útil con bases de código grandes, ya que una gran cantidad de transformaciones del flujo de control puede ralentizar tu código y aumentar su tamaño.
controlFlowFlatteningThreshold: 0 equivale a controlFlowFlattening: false.
deadCodeInjection
Type: boolean Default: false
⚠️ Aumenta drásticamente el tamaño del código ofuscado (hasta un 200%); úsala solo si el tamaño del código ofuscado no importa. Usa deadCodeInjectionThreshold para establecer el porcentaje de nodos que se verán afectados por la inyección de código muerto.
⚠️ Esta opción activa de forma forzada la opción stringArray.
⚠️ Esta opción se desactiva silenciosamente cuando vmObfuscation está activada.
Con esta opción, se añadirán bloques aleatorios de código muerto al código ofuscado.
Ejemplo:
// input
(function(){
if (true) {
var foo = function () {
console.log('abc');
};
var bar = function () {
console.log('def');
};
var baz = function () {
console.log('ghi');
};
var bark = function () {
console.log('jkl');
};
var hawk = function () {
console.log('mno');
};
foo();
bar();
baz();
bark();
hawk();
}
})();
// output
var _0x37b8 = [
'YBCtz',
'GlrkA',
'urPbb',
'abc',
'NMIhC',
'yZgAj',
'zrAId',
'EtyJA',
'log',
'mno',
'jkl',
'def',
'Quzya',
'IWbBa',
'ghi'
];
function _0x43a7(_0x12cf56, _0x587376) {
_0x43a7 = function (_0x2f87a8, _0x47eac2) {
_0x2f87a8 = _0x2f87a8 - (0x16a7 * 0x1 + 0x5 * 0x151 + -0x1c92);
var _0x341e03 = _0x37b8[_0x2f87a8];
return _0x341e03;
};
return _0x43a7(_0x12cf56, _0x587376);
}
(function () {
if (!![]) {
var _0xbbe28f = function () {
var _0x2fc85f = _0x43a7;
if (_0x2fc85f(0xaf) === _0x2fc85f(0xae)) {
_0x1dd94f[_0x2fc85f(0xb2)](_0x2fc85f(0xb5));
} else {
console[_0x2fc85f(0xb2)](_0x2fc85f(0xad));
}
};
var _0x5e46bc = function () {
var _0x15b472 = _0x43a7;
if (_0x15b472(0xb6) !== _0x15b472(0xaa)) {
console[_0x15b472(0xb2)](_0x15b472(0xb5));
} else {
_0x47eac2[_0x15b472(0xb2)](_0x15b472(0xad));
}
};
var _0x3669e8 = function () {
var _0x47a442 = _0x43a7;
if (_0x47a442(0xb7) !== _0x47a442(0xb0)) {
console[_0x47a442(0xb2)](_0x47a442(0xb8));
} else {
_0x24e0bf[_0x47a442(0xb2)](_0x47a442(0xb3));
}
};
var _0x28b05a = function () {
var _0x497902 = _0x43a7;
if (_0x497902(0xb1) === _0x497902(0xb1)) {
console[_0x497902(0xb2)](_0x497902(0xb4));
} else {
_0x59c9c6[_0x497902(0xb2)](_0x497902(0xb4));
}
};
var _0x402a54 = function () {
var _0x1906b7 = _0x43a7;
if (_0x1906b7(0xab) === _0x1906b7(0xac)) {
_0xb89cd0[_0x1906b7(0xb2)](_0x1906b7(0xb8));
} else {
console[_0x1906b7(0xb2)](_0x1906b7(0xb3));
}
};
_0xbbe28f();
_0x5e46bc();
_0x3669e8();
_0x28b05a();
_0x402a54();
}
}());
deadCodeInjectionThreshold
Type: number Default: 0.4 Min: 0 Max: 1
Permite establecer el porcentaje de nodos que se verán afectados por deadCodeInjection.
debugProtection
Type: boolean Default: false
⚠️ Puede congelar tu navegador si abres las Herramientas de desarrollo.
⚠️ Esta opción se desactiva silenciosamente cuando vmObfuscation está activada. Usa vmDebugProtection en su lugar.
Esta opción hace casi imposible usar la función debugger de las Herramientas de desarrollo (tanto en navegadores basados en WebKit como en Mozilla Firefox).
debugProtectionInterval
Type: number Default: 0
⚠️ ¡Puede congelar tu navegador! Úsala bajo tu propia responsabilidad.
⚠️ Esta opción se desactiva silenciosamente cuando vmObfuscation está activada. Usa vmDebugProtection en su lugar.
Si se establece, se utiliza un intervalo en milisegundos para forzar el modo de depuración en la pestaña Consola, lo que dificulta usar otras funciones de las Herramientas de desarrollo. Funciona si debugProtection está activada. El valor recomendado está entre 2000 y 4000 milisegundos.
disableConsoleOutput
Type: boolean Default: false
⚠️ Esta opción desactiva las llamadas a console de forma global para todos los scripts
Desactiva el uso de console.log, console.info, console.error, console.warn, console.debug, console.exception y console.trace reemplazándolos por funciones vacías. Esto dificulta el uso del depurador.
domainLock
Type: string[] Default: []
⚠️ Esta opción no funciona con target: 'node', target: 'service-worker' o target: 'bytenode'
Permite ejecutar el código fuente ofuscado únicamente en dominios y/o subdominios concretos. Esto hace muy difícil que alguien se limite a copiar y pegar tu código fuente y ejecutarlo en otro sitio.
Si el código fuente no se ejecuta en los dominios especificados por esta opción, el navegador será redirigido a la URL pasada a la opción domainLockRedirectUrl.
Varios dominios y subdominios
Es posible bloquear tu código en más de un dominio o subdominio. Por ejemplo, para bloquearlo de modo que el código solo se ejecute en www.example.com añade www.example.com. Para que funcione en el dominio raíz incluyendo cualquier subdominio (example.com, sub.example.com), usa .example.com.
domainLockRedirectUrl
Type: string Default: about:blank
⚠️ Esta opción no funciona con target: 'node', target: 'service-worker' o target: 'bytenode'
Permite redirigir el navegador a una URL indicada si el código fuente no se ejecuta en los dominios especificados por domainLock
exclude
Type: string[] Default: []
Nombres de archivo o globs que indican qué archivos excluir de la ofuscación.
forceTransformStrings
Type: string[] Default: []
Activa la transformación forzada de los literales de cadena que coinciden con los patrones RegExp indicados.
⚠️ Esta opción solo afecta a las cadenas que no deberían transformarse según stringArrayThreshold (o posibles otros umbrales en el futuro)
La opción tiene prioridad sobre la opción reservedStrings, pero no sobre los comentarios condicionales.
Ejemplo:
{
forceTransformStrings: [
'some-important-value',
'some-string_\d'
]
}
identifierNamesCache
Type: Object | null Default: null
El objetivo principal de esta opción es poder usar los mismos nombres de identificadores durante la ofuscación de varios códigos fuente/archivos.
Actualmente se admiten dos tipos de identificadores:
- Identificadores globales:
- Todos los identificadores globales se escribirán en la caché;
- Todos los identificadores globales no declarados que coincidan se reemplazarán por los valores de la caché.
- Identificadores de propiedades, solo cuando la opción
renamePropertiesestá activada:- Todos los identificadores de propiedades se escribirán en la caché;
- Todos los identificadores de propiedades que coincidan se reemplazarán por los valores de la caché.
API de Node.js
Si se pasa un valor null, se desactiva por completo la caché.
Si se pasa un objeto vacío ({}), se activa la escritura de nombres de identificadores en el objeto de caché (tipo TIdentifierNamesCache). Se accederá a este objeto de caché mediante la llamada al método getIdentifierNamesCache del objeto ObfuscationResult.
El objeto de caché resultante puede usarse a continuación como valor de la opción identifierNamesGenerator para emplear estos nombres durante la ofuscación de todos los nombres de identificadores coincidentes de los códigos fuente siguientes.
Ejemplo:
const source1ObfuscationResult = JavaScriptObfuscator.obfuscate(
`
function foo(arg) {
console.log(arg)
}
function bar() {
var bark = 2;
}
`,
{
compact: false,
identifierNamesCache: {},
renameGlobals: true
}
)
console.log(source1ObfuscationResult.getIdentifierNamesCache());
/*
{
globalIdentifiers: {
foo: '_0x5de86d',
bar: '_0x2a943b'
}
}
*/
const source2ObfuscationResult = JavaScriptObfuscator.obfuscate(
`
// Expecting that these global functions are defined in another obfuscated file
foo(1);
bar();
// Expecting that this global function is defined in third-party package
baz();
`,
{
compact: false,
identifierNamesCache: source1ObfuscationResult.getIdentifierNamesCache(),
renameGlobals: true
}
)
console.log(source2ObfuscationResult.getObfuscatedCode());
/*
_0x5de86d(0x1);
_0x2a943b();
baz();
*/
CLI
La CLI tiene una opción distinta, --identifier-names-cache-path, que permite definir una ruta a un archivo .json existente que se usará para leer y escribir la caché de nombres de identificadores.
Si se pasa una ruta a un archivo vacío, la caché de nombres de identificadores se escribirá en ese archivo.
Este archivo con la caché existente puede volver a usarse como valor de la opción --identifier-names-cache-path para emplear estos nombres durante la ofuscación de todos los nombres de identificadores coincidentes de los archivos siguientes.
identifierNamesGenerator
Type: string Default: hexadecimal
Establece el generador de nombres de identificadores.
Valores disponibles:
dictionary: nombres de identificadores de la listaidentifiersDictionaryhexadecimal: nombres de identificadores como_0xabc123mangled: nombres de identificadores cortos comoa,b,cmangled-shuffled: igual quemangledpero con el alfabeto mezclado
identifiersDictionary
Type: string[] Default: []
Establece el diccionario de identificadores para la opción identifierNamesGenerator: dictionary. Cada identificador del diccionario se usará en varias variantes con distintas combinaciones de mayúsculas y minúsculas de cada carácter. Por tanto, el número de identificadores del diccionario debería depender de la cantidad de identificadores del código fuente original.
identifiersPrefix
Type: string Default: ''
Establece un prefijo para todos los identificadores globales.
Usa esta opción cuando quieras ofuscar varios archivos. Esta opción ayuda a evitar conflictos entre los identificadores globales de dichos archivos. El prefijo debería ser distinto para cada archivo.
randomIdentifiersPrefix
Type: boolean Default: false
Añade un prefijo aleatorio basado en la semilla (6 caracteres alfanuméricos) a todos los identificadores globales. Usa esta opción para evitar colisiones entre bundles ofuscados por separado que se cargan en el mismo ámbito global: elimina la necesidad de elegir manualmente un identifiersPrefix único para cada bundle.
- El valor aleatorio se deriva de la opción
seedy del hash del código fuente, de modo que los builds reproducibles con la misma semilla producen el mismo prefijo. - Cuando se combina con
identifiersPrefix, los caracteres aleatorios se añaden al prefijo indicado por el usuario (p. ej.,myApp+ aleatorioaBc123→myAppaBc123). - Cuando se combina con
vmObfuscation, el valor aleatorio sustituye al prefijovmpredeterminado: la aleatoriedad ya garantiza la unicidad.
ignoreImports
Type: boolean Default: false
Impide la ofuscación de las importaciones require. Puede resultar útil en algunos casos en los que, por alguna razón, el entorno de ejecución exige estas importaciones solo con cadenas estáticas.
inputFileName
Type: string Default: ''
Permite establecer el nombre del archivo de entrada con el código fuente. Este nombre se usará internamente para la generación del source map.
Obligatorio cuando se usa la API de NodeJS y la opción sourceMapSourcesMode tiene el valor sources.
log
Type: boolean Default: false
Activa el registro de la información en la consola.
numbersToExpressions
Type: boolean Default: false
Activa la conversión de números en expresiones
Ejemplo:
// input
const foo = 1234;
// output
const foo=-0xd93+-0x10b4+0x41*0x67+0x84e*0x3+-0xff8;
optionsPreset
Type: string Default: default
Permite establecer un preajuste de opciones.
Valores disponibles:
vm-default;vm-low-obfuscation;vm-medium-obfuscation;vm-high-obfuscation;vm-ultra-high-obfuscation;vm-anti-llm;default;low-obfuscation;medium-obfuscation;high-obfuscation.
Todas las opciones adicionales se combinarán con el preajuste de opciones seleccionado.
parseHtml
Type: boolean Default: false
Activa la ofuscación de JavaScript dentro de las etiquetas <script> de HTML.
Cuando está activada, el ofuscador:
- Detecta automáticamente si la entrada es HTML (comprobando las etiquetas
<!DOCTYPE,<html>,<head>,<body>o<script>) - Extrae el JavaScript de las etiquetas
<script>marcadas con el atributodata-javascript-obfuscator - Ofusca cada script marcado de forma individual conservando la estructura del HTML
- Reinserta el código ofuscado en sus posiciones originales
Importante: solo se ofuscan los scripts que tengan el atributo data-javascript-obfuscator. Cada script marcado se ofusca de forma individual e independiente. Esto significa que:
- El código dentro de las etiquetas de script marcadas debe estar aislado: NO debe hacer referencia a variables, funciones o clases definidas en otras etiquetas de script marcadas
- Los scripts no marcados aún pueden acceder a los globales definidos por los scripts marcados (mediante declaraciones
varo asignaciones explícitas aglobalThis) - Esto te da un control explícito sobre qué scripts proteger
Se ofuscan (deben tener el atributo data-javascript-obfuscator):
<script data-javascript-obfuscator>- scripts normales<script type="text/javascript" data-javascript-obfuscator>- scripts con tipo explícito- Scripts con cualquier atributo adicional (
id,class, otrosdata-*, etc.)
Se omiten (se dejan sin cambios):
- Scripts sin el atributo
data-javascript-obfuscator <script type="module">- módulos ES (aunque tengan el atributo)<script src="...">- scripts externos (aunque tengan el atributo)- Etiquetas de script vacías
Nota: los source maps no se generan cuando parseHtml está activada, ya que no se corresponderían correctamente con la salida HTML.
Ejemplo:
// input
const html = `<!DOCTYPE html>
<html>
<body>
<!-- This script will NOT be obfuscated -->
<script>
var helper = 'utility';
</script>
<!-- This script WILL be obfuscated -->
<script data-javascript-obfuscator>
var greeting = 'Hello World';
console.log(greeting);
</script>
</body>
</html>`;
JavaScriptObfuscator.obfuscate(html, {
parseHtml: true,
stringArray: true
});
// output: HTML with only the marked script obfuscated
renameGlobals
Type: boolean Default: false
⚠️ esta opción puede romper tu código. ¡Actívala solo si sabes lo que hace!
Activa la ofuscación de los nombres de variables y funciones globales con su declaración.
Cuando esta opción está desactivada y el código de entrada declara funciones o clases en el ámbito global (es decir, el código no está envuelto en una IIFE), sus nombres se conservan tal cual en la salida ofuscada: otros scripts pueden referenciarlos por su nombre. Con vmObfuscation se informa de una advertencia VMGlobalFunctionNamesNotRenamed que lista estos nombres, ya que el cuerpo de la función se oculta como bytecode pero el nombre de nivel superior, legible, sigue revelando lo que hace el código (por ejemplo, a un LLM). Para evitar esta exposición, envuelve el código en una IIFE o activa esta opción.
renameProperties
Type: boolean Default: false
⚠️ esta opción PUEDE romper tu código. ¡Actívala solo si sabes lo que hace!
Activa el renombrado de los nombres de propiedades. Se ignorarán todas las propiedades DOM integradas y las propiedades de las clases fundamentales de JavaScript.
Para alternar entre los modos safe y unsafe de esta opción, usa la opción renamePropertiesMode.
Para establecer el formato de los nombres de propiedades renombrados, usa la opción identifierNamesGenerator.
Para controlar qué propiedades se renombrarán, usa la opción reservedNames.
Ejemplo:
// input
(function () {
const foo = {
prop1: 1,
prop2: 2,
calc: function () {
return this.prop1 + this.prop2;
}
};
console.log(foo.calc());
})();
// output
(function () {
const _0x46529b = {
'_0x10cec7': 0x1,
'_0xc1c0ca': 0x2,
'_0x4b961d': function () {
return this['_0x10cec7'] + this['_0xc1c0ca'];
}
};
console['log'](_0x46529b['_0x4b961d']());
}());
renamePropertiesMode
Type: string Default: safe
⚠️ Incluso en el modo safe, la opción renameProperties PUEDE romper tu código.
Especifica el modo de la opción renameProperties:
safe- comportamiento predeterminado a partir de la versión2.11.0. Intenta renombrar las propiedades de una forma más segura para evitar errores en tiempo de ejecución. Con este modo, algunas propiedades quedarán excluidas del renombrado.unsafe- comportamiento predeterminado anterior a la versión2.11.0. Renombra las propiedades de forma no segura, sin ninguna restricción.
Si un archivo usa propiedades de otro archivo, utiliza la opción identifierNamesCache para mantener los mismos nombres de propiedades entre esos archivos.
reservedNames
Type: string[] Default: []
Desactiva la ofuscación y la generación de los identificadores que coinciden con los patrones RegExp indicados.
Ejemplo:
{
reservedNames: [
'^someVariable',
'functionParameter_\d'
]
}
reservedStrings
Type: string[] Default: []
Desactiva la transformación de los literales de cadena que coinciden con los patrones RegExp indicados. Las cadenas coincidentes permanecerán visibles en la salida ofuscada.
Al usar la ofuscación VM, las cadenas reservadas se almacenan en un array independiente sin cifrar para mantenerlas visibles. Esto es útil para cadenas que deben seguir siendo legibles, como endpoints de API para monitorización o identificadores de bibliotecas.
Ejemplo:
{
reservedStrings: [
'react-native',
'\.\/src\/test',
'some-string_\d'
]
}
seed
Type: string|number Default: 0
Esta opción establece la semilla del generador de números aleatorios. Es útil para crear resultados reproducibles.
Si la semilla es 0, el generador de números aleatorios funcionará sin semilla.
selfDefending
Type: boolean Default: false
⚠️ ¡No modifiques de ninguna manera el código ofuscado tras ofuscarlo con esta opción, porque cualquier cambio, como minificar el código, puede activar la autodefensa y el código dejará de funcionar!
⚠️ Esta opción fuerza el valor de compact a true
⚠️ Esta opción se desactiva silenciosamente cuando vmObfuscation está activada. Usa vmSelfDefending en su lugar.
Esta opción hace que el código de salida sea resistente al formateo y al renombrado de variables. Si alguien intenta aplicar un embellecedor (beautifier) de JavaScript al código ofuscado, el código dejará de funcionar, lo que dificulta entenderlo y modificarlo.
simplify
Type: boolean Default: true
Activa una ofuscación adicional del código mediante simplificación.
⚠️ en versiones futuras, la ofuscación de los literales boolean (true => !![]) se trasladará a esta opción.
Ejemplo:
// input
if (condition1) {
const foo = 1;
const bar = 2;
console.log(foo);
return bar;
} else if (condition2) {
console.log(1);
console.log(2);
console.log(3);
return 4;
} else {
return 5;
}
// output
if (condition1) {
const foo = 0x1, bar = 0x2;
return console['log'](foo), bar;
} else
return condition2 ? (console['log'](0x1), console['log'](0x2), console['log'](0x3), 0x4) : 0x5;
sourceMap
Type: boolean Default: false
Activa la generación de source maps para el código ofuscado.
Los source maps pueden resultar útiles para ayudarte a depurar tu código fuente JavaScript ofuscado. Si quieres o necesitas depurar en producción, puedes subir el archivo de source map por separado a una ubicación secreta y luego apuntar tu navegador a ella.
sourceMapBaseUrl
Type: string Default: ``
Establece la URL base para la URL de importación del source map cuando sourceMapMode: 'separate'.
Ejemplo de CLI:
javascript-obfuscator input.js --output out.js --source-map true --source-map-base-url 'http://localhost:9000'
Resultado:
//# sourceMappingURL=http://localhost:9000/out.js.map
sourceMapFileName
Type: string Default: ``
Establece el nombre de archivo del source map de salida cuando sourceMapMode: 'separate'.
Ejemplo de CLI:
javascript-obfuscator input.js --output out.js --source-map true --source-map-base-url 'http://localhost:9000' --source-map-file-name example
Resultado:
//# sourceMappingURL=http://localhost:9000/example.js.map
sourceMapMode
Type: string Default: separate
Especifica el modo de generación del source map:
inline- añade el source map al final de cada archivo .js;separate- genera el archivo '.map' correspondiente con el source map. Si ejecutas el ofuscador mediante la CLI, añade un enlace al archivo de source map al final del archivo con el código ofuscado//# sourceMappingUrl=file.js.map.
sourceMapSourcesMode
Type: string Default: sources-content
Permite controlar los campos sources y sourcesContent del source map:
sources-content- añade un camposourcesficticio y un camposourcesContentcon el código fuente original;sources- añade un camposourcescon una descripción de origen válida y no añade el camposourcesContent. Al usar la API de NodeJS es necesario definir la opcióninputFileName, que se usará como valor del camposources.
splitStrings
Type: boolean Default: false
Divide las cadenas literales en fragmentos con la longitud del valor de la opción splitStringsChunkLength.
Ejemplo:
// input
(function(){
var test = 'abcdefg';
})();
// output
(function(){
var _0x5a21 = 'ab' + 'cd' + 'ef' + 'g';
})();
splitStringsChunkLength
Type: number Default: 10
Establece la longitud de los fragmentos de la opción splitStrings.
stringArray
Type: boolean Default: true
Elimina los literales de cadena y los coloca en un array especial. Por ejemplo, la cadena "Hello World" en var m = "Hello World"; se reemplazará por algo como var m = _0x12c456[0x1];
stringArrayCallsTransform
Type: boolean Default: false
⚠️ la opción stringArray debe estar activada
Activa la transformación de las llamadas al stringArray. Todos los argumentos de estas llamadas pueden extraerse a un objeto distinto en función del valor de stringArrayCallsTransformThreshold.
Así resulta aún más difícil localizar automáticamente las llamadas al string array.
Ejemplo:
function foo() {
var k = {
c: 0x2f2,
d: '0x396',
e: '0x397',
f: '0x39a',
g: '0x39d',
h: 0x398,
l: 0x394,
m: '0x39b',
n: '0x39f',
o: 0x395,
p: 0x395,
q: 0x399,
r: '0x399'
};
var c = i(k.d, k.e);
var d = i(k.f, k.g);
var e = i(k.h, k.l);
var f = i(k.m, k.n);
function i(c, d) {
return b(c - k.c, d);
}
var g = i(k.o, k.p);
var h = i(k.q, k.r);
}
function j(c, d) {
var l = { c: 0x14b };
return b(c - -l.c, d);
}
console[j(-'0xa6', -'0xa6')](foo());
function b(c, d) {
var e = a();
b = function (f, g) {
f = f - 0xa3;
var h = e[f];
return h;
};
return b(c, d);
}
function a() {
var m = [
'string5',
'string1',
'log',
'string3',
'string6',
'string2',
'string4'
];
a = function () {
return m;
};
return a();
}
stringArrayCallsTransformThreshold
Type: number Default: 0.5
⚠️ las opciones stringArray y stringArrayCallsTransformThreshold deben estar activadas
Puedes usar este ajuste para regular la probabilidad (de 0 a 1) de que se transformen las llamadas al string array.
stringArrayEncoding
Type: string[] Default: []
⚠️ la opción stringArray debe estar activada
Esta opción puede ralentizar tu script.
Codifica todos los literales de cadena del stringArray usando base64 o rc4 e inserta un código especial que se emplea para decodificarlos de nuevo en tiempo de ejecución.
Cada valor del stringArray se codificará con la codificación elegida al azar de la lista indicada. Esto permite usar varias codificaciones.
Valores disponibles:
'none'(boolean): no codifica el valor delstringArray'base64'(string): codifica el valor delstringArrayusandobase64'rc4'(string): codifica el valor delstringArrayusandorc4. Alrededor de un 30-50% más lento quebase64, pero dificulta más obtener los valores iniciales.
Por ejemplo, con los siguientes valores de opción, algún valor del stringArray no se codificará y otros valores se codificarán con las codificaciones base64 y rc4:
stringArrayEncoding: [
'none',
'base64',
'rc4'
]
stringArrayIndexesType
Type: string[] Default: ['hexadecimal-number']
⚠️ la opción stringArray debe estar activada
Permite controlar el tipo de los índices de las llamadas al string array.
Cada índice de llamada al stringArray se transformará con el tipo elegido al azar de la lista indicada. Esto permite usar varios tipos.
Valores disponibles:
'hexadecimal-number'(default): transforma los índices de las llamadas al string array como números hexadecimales'hexadecimal-numeric-string': transforma los índices de las llamadas al string array como cadenas numéricas hexadecimales
Antes de la versión 2.9.0, javascript-obfuscator transformaba todos los índices de las llamadas al string array con el tipo hexadecimal-numeric-string. Esto dificulta ligeramente cierta desofuscación manual, pero permite que los desofuscadores automáticos detecten fácilmente estas llamadas.
El nuevo tipo hexadecimal-number busca dificultar la detección automática de los patrones de llamada al string array en el código.
Se añadirán más tipos en el futuro.
stringArrayIndexShift
Type: boolean Default: true
⚠️ la opción stringArray debe estar activada
Activa un desplazamiento de índice adicional para todas las llamadas al string array
stringArrayRotate
Type: boolean Default: true
⚠️ stringArray debe estar activada
Desplaza el array stringArray un número de posiciones fijo y aleatorio (generado durante la ofuscación del código). Esto dificulta hacer coincidir el orden de las cadenas eliminadas con su lugar original.
stringArrayShuffle
Type: boolean Default: true
⚠️ stringArray debe estar activada
Baraja aleatoriamente los elementos del array stringArray.
stringArrayWrappersCount
Type: number Default: 1
⚠️ la opción stringArray debe estar activada
Establece el número de wrappers del string array dentro de cada ámbito raíz o de función.
El número real de wrappers dentro de cada ámbito está limitado por la cantidad de nodos literal de ese ámbito.
Ejemplo:
// Input
const foo = 'foo';
const bar = 'bar';
function test () {
const baz = 'baz';
const bark = 'bark';
const hawk = 'hawk';
}
const eagle = 'eagle';
// Output, stringArrayWrappersCount: 5
const _0x3f6c = [
'bark',
'bar',
'foo',
'eagle',
'hawk',
'baz'
];
const _0x48f96e = _0x2e13;
const _0x4dfed8 = _0x2e13;
const _0x55e970 = _0x2e13;
function _0x2e13(_0x33c4f5, _0x3f6c62) {
_0x2e13 = function (_0x2e1388, _0x60b1e) {
_0x2e1388 = _0x2e1388 - 0xe2;
let _0x53d475 = _0x3f6c[_0x2e1388];
return _0x53d475;
};
return _0x2e13(_0x33c4f5, _0x3f6c62);
}
const foo = _0x48f96e(0xe4);
const bar = _0x4dfed8(0xe3);
function test() {
const _0x1c262f = _0x2e13;
const _0x54d7a4 = _0x2e13;
const _0x5142fe = _0x2e13;
const _0x1392b0 = _0x1c262f(0xe7);
const _0x201a58 = _0x1c262f(0xe2);
const _0xd3a7fb = _0x1c262f(0xe6);
}
const eagle = _0x48f96e(0xe5);
stringArrayWrappersChainedCalls
Type: boolean Default: true
⚠️ las opciones stringArray y stringArrayWrappersCount deben estar activadas
Activa las llamadas encadenadas entre los wrappers del string array.
Ejemplo:
// Input
const foo = 'foo';
const bar = 'bar';
function test () {
const baz = 'baz';
const bark = 'bark';
function test1() {
const hawk = 'hawk';
const eagle = 'eagle';
}
}
// Output, stringArrayWrappersCount: 5, stringArrayWrappersChainedCalls: true
const _0x40c2 = [
'bar',
'bark',
'hawk',
'eagle',
'foo',
'baz'
];
const _0x31c087 = _0x3280;
const _0x31759a = _0x3280;
function _0x3280(_0x1f52ee, _0x40c2a2) {
_0x3280 = function (_0x3280a4, _0xf07b02) {
_0x3280a4 = _0x3280a4 - 0x1c4;
let _0x57a182 = _0x40c2[_0x3280a4];
return _0x57a182;
};
return _0x3280(_0x1f52ee, _0x40c2a2);
}
const foo = _0x31c087(0x1c8);
const bar = _0x31c087(0x1c4);
function test() {
const _0x848719 = _0x31759a;
const _0x2693bf = _0x31c087;
const _0x2c08e8 = _0x848719(0x1c9);
const _0x359365 = _0x2693bf(0x1c5);
function _0x175e90() {
const _0x310023 = _0x848719;
const _0x2302ef = _0x2693bf;
const _0x237437 = _0x310023(0x1c6);
const _0x56145c = _0x310023(0x1c7);
}
}
stringArrayWrappersParametersMaxCount
Type: number Default: 2
⚠️ la opción stringArray debe estar activada
⚠️ Actualmente esta opción solo afecta a los wrappers añadidos por el valor function de la opción stringArrayWrappersType
Permite controlar el número máximo de parámetros de los wrappers del string array.
El valor predeterminado y mínimo es 2. El valor recomendado está entre 2 y 5.
stringArrayWrappersType
Type: string Default: variable
⚠️ las opciones stringArray y stringArrayWrappersCount deben estar activadas
Permite seleccionar el tipo de los wrappers que añade la opción stringArrayWrappersCount.
Valores disponibles:
'variable': añade wrappers de variable al principio de cada ámbito. Rendimiento rápido.'function': añade wrappers de función en posiciones aleatorias dentro de cada ámbito. Rendimiento más lento que convariable, pero ofrece una ofuscación más estricta.
Muy recomendable usar los wrappers function para una mayor ofuscación cuando la pérdida de rendimiento no tenga un gran impacto en la aplicación ofuscada.
Ejemplo del valor de opción 'function':
// input
const foo = 'foo';
function test () {
const bar = 'bar';
console.log(foo, bar);
}
test();
// output
const a = [
'log',
'bar',
'foo'
];
const foo = d(0x567, 0x568);
function b(c, d) {
b = function (e, f) {
e = e - 0x185;
let g = a[e];
return g;
};
return b(c, d);
}
function test() {
const c = e(0x51c, 0x51b);
function e (c, g) {
return b(c - 0x396, g);
}
console[f(0x51b, 0x51d)](foo, c);
function f (c, g) {
return b(c - 0x396, g);
}
}
function d (c, g) {
return b(g - 0x3e1, c);
}
test();
stringArrayThreshold
Type: number Default: 0.8 Min: 0 Max: 1
⚠️ la opción stringArray debe estar activada
Puedes usar este ajuste para regular la probabilidad (de 0 a 1) de que un literal de cadena se inserte en el stringArray.
Este ajuste resulta especialmente útil con bases de código grandes, ya que realiza llamadas repetidas al string array y puede ralentizar tu código.
stringArrayThreshold: 0 equivale a stringArray: false.
strictMode
Type: boolean | null Default: null
Permite especificar cómo debe tratar el ofuscador el código en relación con el modo estricto de JavaScript.
Valores disponibles:
null(predeterminado) - detecta automáticamente el modo estricto a partir del código. Si el código tiene una directiva'use strict'explícita, sintaxis de módulo ES o métodos de clase, se trata como modo estricto. En caso contrario, se asume el modo permisivo (sloppy).true- fuerza el tratamiento en modo estricto para todo el código, incluso sin una directiva'use strict'explícita. Úsalo cuando tu código vaya a ejecutarse en un contexto de modo estricto (por ejemplo, en módulos ES, bundlers o frameworks modernos).false- solo se tratan como estrictos los indicadores explícitos de modo estricto ('use strict', módulos ES, métodos de clase). La herencia del ámbito padre sigue aplicándose según la especificación de JS.
target
Type: string Default: browser
Permite establecer el entorno de destino del código ofuscado.
Valores disponibles:
browser(predeterminado) — entorno estándar de página web. El código de salida es idéntico al denode, pero algunas opciones específicas del navegador no pueden usarse con el targetnodebrowser-no-eval— igual quebrowser, pero la salida no usaeval(). Úsalo cuando la página de destino tenga una Content Security Policy que prohíbaeval/unsafe-eval.node— entorno Node.js. Las opciones específicas del navegador se desactivan (requierenwindow/documenty serían inoperantes o lanzarían errores en Node). Algunas defensas devmSelfDefendingque dependen de APIs exclusivas del navegador —detección de navegadores headless, recuperación de realm limpio basada en iframe, comprobaciones anti-inspector/DOM— no se emiten para este target.service-worker— contexto de Service Worker. Sinwindow, sindocument, con un globalselfdistinto.userscript— sandbox de un gestor de userscripts (p. ej., Tampermonkey). Las defensas devmSelfDefendingse ajustan en consecuencia.bytenode— código de Node.js que se compilará con el cargador bytenode (bytecode en caché de V8.jsc) tras la ofuscación. El propio ofuscador no invocabytenode; emite JavaScript ofuscado con VM cuyo runtime está estructurado para sobrevivir al paso de compilación de bytenode, y las defensas devmSelfDefendingse ajustan en consecuencia. Ejecuta tú mismobytenodesobre la salida ofuscada para producir el.jscfinal.
transformObjectKeys
Type: boolean Default: false
Activa la transformación de las claves de objeto.
Ejemplo:
// input
(function(){
var object = {
foo: 'test1',
bar: {
baz: 'test2'
}
};
})();
// output
var _0x4735 = [
'foo',
'baz',
'bar',
'test1',
'test2'
];
function _0x390c(_0x33d6b6, _0x4735f4) {
_0x390c = function (_0x390c37, _0x1eed85) {
_0x390c37 = _0x390c37 - 0x198;
var _0x2275f8 = _0x4735[_0x390c37];
return _0x2275f8;
};
return _0x390c(_0x33d6b6, _0x4735f4);
}
(function () {
var _0x17d1b7 = _0x390c;
var _0xc9b6bb = {};
_0xc9b6bb[_0x17d1b7(0x199)] = _0x17d1b7(0x19c);
var _0x3d959a = {};
_0x3d959a[_0x17d1b7(0x198)] = _0x17d1b7(0x19b);
_0x3d959a[_0x17d1b7(0x19a)] = _0xc9b6bb;
var _0x41fd86 = _0x3d959a;
}());
warnings
Type: string | object Default: all
Controla qué advertencias de ofuscación no fatales se emiten a través del método ObfuscationResult.getWarnings().
Valores disponibles:
'all'(predeterminado) — se emite cada advertencia.'none'— se suprimen todas las advertencias.- un objeto que asocia tipos de advertencia a booleanos — un tipo asociado a
falsese suprime; cada tipo no presente (o asociado atrue) permanece activado. Por ejemplo,{ "VMGlobalFunctionNamesNotRenamed": false }mantiene todas las advertencias salvo esa.
Tipos de advertencia:
VMGlobalFunctionNamesNotRenamed— convmObfuscation, los nombres de las declaraciones de funciones de nivel superior, las declaraciones de clase y las variables a las que se asigna una expresión de función/flecha/clase se conservaron tal cual (la opciónrenameGlobalsestá desactivada y el código no está envuelto en una IIFE), por lo que siguen siendo legibles en la salida aunque los cuerpos se oculten como bytecode. Los nombres exportados no se informan.VMTopLevelInitializerNotVirtualized— los inicializadores de variables de nivel superior permanecieron en JavaScript plano bajo la ofuscación VM porquevmWrapTopLevelInitializersestá desactivada o no pudo virtualizarlos.DynamicCodeRenameRisk— el código construye una función a partir de una cadena en tiempo de ejecución (evaldirecto, el constructorFunctionofn.toString()inyectado en un<script>/Worker), lo que puede hacer referencia a identificadores que el ofuscador ha renombrado.VMDynamicCodeSkipped— una función se omitió de la conversión a bytecode de la VM porque contieneevaldirecto /new Functiondinámico /Function(consultavmForceCompileDynamicCode).VMSyncFunctionSkippedInAsyncMode— convmAsyncExecutoractivada, una función que marcaste explícitamente en el modocommentresultó ser síncrona y se omitió (en ese modo solo se virtualizan las funciones asíncronas).VMAsyncGeneratorSkippedInAsyncMode— convmAsyncExecutory un getter de clave asíncrono activo, no se pudo virtualizar un generador asíncrono marcado (debe devolver su iterador de forma síncrona).BrowserTargetWithNodeStyleCode— el código parece dirigido a Node.js (p. ej.,require('fs'),__dirname,process.argv) mientras la opcióntargetestá establecida en un entorno de tipo navegador.
vmObfuscation
Type: boolean Default: false
Activa la ofuscación basada en bytecode de VM. Cuando está activada, las funciones de JavaScript se compilan a un bytecode personalizado que se ejecuta en una máquina virtual embebida. Esto proporciona el máximo nivel de protección, ya que la lógica original del código se transforma por completo.
Ejemplo:
Tu código legible, como return qty * price, se convierte en una lista de números como [0x15,0x03,0x17,...] que solo el intérprete embebido de la VM puede ejecutar. La lógica original deja de ser visible como JavaScript.
vmTargetFunctions
Type: string[] Default: []
Especifica exactamente por su nombre qué funciones de nivel raíz deben recibir protección VM.
Ejemplo:
{
vmObfuscation: true,
vmTargetFunctions: ['someFunctionName']
}
Resultado: Solo estas tres funciones quedan protegidas con VM. Todo lo demás permanece como JavaScript normal (pero aún ofuscado). Perfecto para proteger comprobaciones de licencia sensibles o la lógica de autenticación manteniendo el resto de tu código ligero.
vmExcludeFunctions
Type: string[] Default: []
Especifica funciones de nivel raíz que nunca deben recibir protección VM. Tiene prioridad sobre otros ajustes.
Ejemplo:
{
vmObfuscation: true,
vmExcludeFunctions: ['someFunctionName']
}
Cuándo usarla: Las funciones de nivel raíz críticas para el rendimiento (bucles de animación, procesamiento de datos en tiempo real) pueden excluirse para evitar la sobrecarga de la VM sin dejar de proteger todo lo demás.
vmTargetFunctionsMode
Type: string Default: root
Controla cómo se seleccionan las funciones/métodos para la ofuscación VM.
Ejemplo - Modo comment:
// Source code
function regularFunction() {
return 'not virtualized';
}
/* javascript-obfuscator:vm */
function sensitiveFunction() {
return 'this will be VM-protected';
}
function outer() {
/* javascript-obfuscator:vm */
function nestedSensitive() {
return 'nested but still VM-protected';
}
return nestedSensitive();
}
// Obfuscator options
{
vmObfuscation: true,
vmTargetFunctionsMode: 'comment'
}
Cuándo usarlo: Cuando necesitas un control quirúrgico sobre exactamente qué funciones reciben protección VM, especialmente funciones anidadas que contienen lógica sensible. A diferencia de vmTargetFunctions, que solo funciona con funciones con nombre de nivel raíz, el modo comment te permite proteger cualquier función en cualquier parte de tu código.
vmForceCompileDynamicCode
Type: boolean Default: false
Controla qué hace la ofuscación VM con una función que contiene una llamada a eval directo, new Function(...) o Function(...).
De forma predeterminada, dicha función (y cada función definida dentro de ella) se omite de la conversión a bytecode de la VM y se informa de una advertencia VMDynamicCodeSkipped en result.getWarnings(). Esto se debe a que el código fuente construido en tiempo de ejecución puede hacer referencia a identificadores de la cadena de ámbitos circundante, identificadores que el ofuscador ha renombrado.
Cuando se establece en true, la función se convierte a bytecode de todos modos y la advertencia VMDynamicCodeSkipped deja de emitirse.
La advertencia independiente DynamicCodeRenameRisk se sigue emitiendo con independencia de esta opción, porque el riesgo de renombrado que describe es independiente de la omisión de la VM: activar esta opción no hace que el patrón subyacente sea más seguro.
// Source code
function loadConfig(src) {
return eval(src);
}
loadConfig('1 + 2');
// Options
{
vmObfuscation: true,
vmForceCompileDynamicCode: true
}
Con la opción desactivada (predeterminado), loadConfig se deja como JavaScript plano. Con la opción activada, loadConfig se compila a bytecode de la VM como cualquier otra función. Úsala cuando hayas auditado el sitio de la llamada y sepas que el código construido en tiempo de ejecución no depende de identificadores renombrados del closure.
vmWrapTopLevelInitializers
Type: boolean Default: false
Envuelve algunos inicializadores de variables de nivel superior en IIFE (expresiones de función invocadas inmediatamente) para que puedan ofuscarse con VM.
Qué hace: Sin esta opción, las constantes y variables de nivel superior permanecen visibles en la salida:
// Input
const MY_STRING = "my-string";
// Output (without vmWrapTopLevelInitializers)
const MY_STRING = "my-string"; // String is visible!
Con esta opción activada, el inicializador se envuelve en una IIFE que se ofusca con VM:
// Input
const MY_STRING = "my-string";
// Output (with vmWrapTopLevelInitializers: true)
const MY_STRING = (() => { return /* VM bytecode call */ })(); // String hidden in bytecode
Nota: Esta opción solo funciona cuando vmTargetFunctionsMode es 'root' (el valor predeterminado).
Advertencias: Siempre que un inicializador de nivel superior acabe en JavaScript plano bajo la ofuscación VM, se informa de una advertencia VMTopLevelInitializerNotVirtualized que lista los nombres de las variables afectadas. Esto abarca: que esta opción esté desactivada, los inicializadores que esta opción tuvo que omitir (cada uno con su motivo, p. ej., el inicializador hace referencia a un declarador hermano o contiene un await de nivel superior) y el modo vmAsyncExecutor, donde los wrappers síncronos no pueden virtualizarse en absoluto.
vmDynamicOpcodes
Type: boolean Default: false
Hace que el intérprete de la VM sea más pequeño y único para cada build.
Qué hace:
- Filtra las instrucciones no usadas - Si tu código no usa clases, las instrucciones relacionadas con clases se eliminan por completo
- Aleatoriza la estructura - El orden de los manejadores de instrucciones se baraja en cada build
Como resultado, una salida más pequeña y cada build tiene un aspecto diferente.
vmBytecodeEncoding
Type: boolean Default: false
Codifica cada instrucción del bytecode. Las instrucciones se decodifican una a una durante la ejecución.
vmBytecodeArrayEncoding
Type: boolean Default: false
Codifica todo el array de bytecode como un único bloque. El array se decodifica una sola vez al inicio, antes de que comience la ejecución. Úsala junto con vmBytecodeEncoding para obtener dos capas de protección.
vmBytecodeArrayEncodingKey
Type: string Default: ''
Clave de cifrado personalizada para la codificación del array de bytecode. Cuando se establece, esta clave se usa en lugar de la clave predeterminada derivada del entorno. La clave debe proporcionarse en tiempo de ejecución mediante vmBytecodeArrayEncodingKeyGetter.
Esta opción externaliza la clave de cifrado: no se incrusta en el propio código ofuscado. Aunque la clave sigue siendo accesible en tiempo de ejecución (y, por tanto, no es realmente secreta), esta separación impide que las herramientas de análisis estático encuentren la clave examinando únicamente el código.
Importante: La clave debe estar disponible de forma síncrona cuando se carga el código ofuscado. Usa almacenamiento síncrono como cookies, localStorage, sessionStorage, variables globales o elementos del DOM (p. ej., meta tags inyectados por el servidor). Los métodos asíncronos como fetch() no pueden usarse directamente en la expresión del getter de clave.
vmBytecodeArrayEncodingKeyGetter
Type: string Default: ''
Expresión de JavaScript síncrona que devuelve la clave de cifrado en tiempo de ejecución. Esta expresión se evalúa cuando se carga el código ofuscado y debe devolver la misma clave que se proporcionó en vmBytecodeArrayEncodingKey. Para resolver la clave de forma asíncrona (una Promise), activa vmAsyncExecutor.
Nota: un getter que devuelve una Promise requiere vmAsyncExecutor. Esto no puede comprobarse en tiempo de compilación, por lo que un getter con Promise y vmAsyncExecutor desactivada falla en tiempo de ejecución: el decodificador recibe la Promise en lugar de la clave.
El código ofuscado solo funcionará cuando el getter de clave devuelva exactamente la misma clave que se usó durante la ofuscación. Si las claves no coinciden, el descifrado fallará y el código producirá datos basura o errores. Si el getter de clave devuelve undefined, null o una cadena vacía, el código lanzará un error: "VM decryption key not available".
Importante: Mantén la clave fuera del mismo archivo/script que el código ofuscado; incluirla ahí en línea permite que incluso un análisis puramente estático del bundle la recupere. Almacénala en cambio en una fuente independiente: cookies establecidas por el servidor, localStorage rellenado por otro script, un meta tag HTML inyectado por el servidor, un global establecido por un script distinto o (con vmAsyncExecutor) obtenida de tu backend en tiempo de ejecución.
Cuando la clave se obtiene de tu backend (mediante vmAsyncExecutor), añade comprobaciones basadas en la sesión o en el origen en ese endpoint: devuelve la clave correcta a los usuarios reales (sesión válida, Origin/Referer esperados) y una clave basura a las solicitudes sospechosas (p. ej., un origen localhost/inesperado, sin sesión). Los usuarios reales se ejecutan con normalidad; una copia que se ejecute fuera de tu entorno obtiene una clave que no descifra nada. La lógica exacta depende de tu sitio.
Ejemplos:
// From cookie
vmBytecodeArrayEncodingKeyGetter: "document.cookie.match(/vmKey=([^;]+)/)?.[1]"
// From localStorage
vmBytecodeArrayEncodingKeyGetter: "localStorage.getItem('vmKey')"
// From global variable
vmBytecodeArrayEncodingKeyGetter: "window.__VM_KEY__"
// From meta tag (server-injected)
vmBytecodeArrayEncodingKeyGetter: "document.querySelector('meta[name=\"vm-key\"]').content"
// From nested object
vmBytecodeArrayEncodingKeyGetter: "window.config.encryption.key"
// From backend, async (requires vmAsyncExecutor)
vmBytecodeArrayEncodingKeyGetter: 'fetch("/vm-key").then((res) => res.text())'
Ejemplo de uso:
// Build time
JavaScriptObfuscator.obfuscate(code, {
vmObfuscation: true,
vmBytecodeArrayEncoding: true,
vmBytecodeArrayEncodingKey: 'mySecretKey123',
vmBytecodeArrayEncodingKeyGetter: 'window.__VM_KEY__'
});
// Runtime - key must be set before obfuscated code runs
window.__VM_KEY__ = 'mySecretKey123';
vmAsyncExecutor
Type: boolean Default: false
Activa el ejecutor asíncrono de la VM, que permite que vmBytecodeArrayEncodingKeyGetter devuelva una Promise (un getter de clave asíncrono), de modo que la clave de descifrado puede obtenerse en tiempo de ejecución (petición de red, IndexedDB, etc.) en lugar de tener que estar disponible de forma síncrona cuando se carga el código.
Muy recomendable para bases de código totalmente asíncronas. En este modo solo se virtualizan las funciones async: una función síncrona no puede convertirse en asíncrona sin transformar su valor de retorno en una Promise y romper a quienes la llaman, por lo que el código que es async de principio a fin obtiene la mayor cobertura. Sigue funcionando cuando la raíz es síncrona (p. ej., una IIFE síncrona / wrapper UMD): las funciones async más externas del interior quedan protegidas y las partes síncronas se dejan tal cual.
Qué se transforma: cada función async más externa, dondequiera que aparezca (incluso anidada dentro de wrappers síncronos). La función asíncrona más externa de cada cadena es la unidad protegida: todo lo que hay dentro de ella, síncrono y asíncrono, se compila. Las funciones síncronas y los generadores normales se dejan sin ofuscar.
function foo() { // sync — left as-is
function bar() {} // sync — left as-is
async function baz() { // transformed
// any code here, including calls to other async or sync functions
}
async function bark() { // transformed
// any code here, including calls to other async or sync functions
}
}
Omisiones y advertencias. Los generadores asíncronos también se dejan sin ofuscar cuando hay un getter de clave asíncrono activo (un generador asíncrono debe devolver su iterador de forma síncrona y no puede esperar a la clave). En el modo predeterminado vmTargetFunctionsMode: 'root', las omisiones son silenciosas (la selección es automática); en el modo comment se emite una advertencia a través de ObfuscationResult.getWarnings() siempre que una función que marcaste explícitamente no pueda virtualizarse: resultó ser síncrona o es un generador asíncrono bajo un getter de clave asíncrono.
El getter de clave asíncrono requiere además vmBytecodeArrayEncoding con un vmBytecodeArrayEncodingKeyGetter.
Ejemplo de uso:
JavaScriptObfuscator.obfuscate(code, {
vmObfuscation: true,
vmAsyncExecutor: true,
vmBytecodeArrayEncoding: true,
vmBytecodeArrayEncodingKey: 'mySecretKey123',
// the key getter may now return a Promise
vmBytecodeArrayEncodingKeyGetter: 'fetch("/vm-key").then((res) => res.text())'
});
vmJumpsEncoding
Type: boolean Default: false
Codifica los destinos de salto en el bytecode. Los desplazamientos de salto se calculan en tiempo de ejecución, lo que oculta la estructura del flujo de control (if/else, bucles, etc.) del análisis estático.
vmMacroOps
Type: boolean Default: false
Combina secuencias de instrucciones comunes en opcodes «macro» únicos. Por ejemplo, LOAD + ADD + STORE podría convertirse en una única instrucción MACRO_ADD_TO_VAR. Esto rompe el reconocimiento de patrones y puede mejorar el rendimiento.
vmDebugProtection
Type: boolean Default: false
Añade defensas multicapa antidepuración, antianálisis y anti-LLM al runtime de la VM. Funciona mejor con los targets browser/browser-no-eval.
vmSelfDefending
Type: boolean Default: false
Añade al runtime de la VM protección multicapa de detección de manipulación, anti-hooking y anti-ingeniería inversa.
⚠️ Esta opción fuerza la activación de vmBytecodeArrayEncoding.
⚠️ Detección de entornos sensibles. Esta opción vincula el código ofuscado a su entorno de ejecución de destino y utiliza fingerprinting avanzado del navegador para detectar herramientas de automatización. El código protegido con esta opción se romperá de forma intencionada cuando se ejecute en:
- Navegadores headless (Chrome/Chromium headless, PhantomJS)
- Herramientas de automatización de navegadores (Puppeteer, Playwright, Cypress, Selenium/ChromeDriver, Nightmare)
- Node.js (cuando
targetestá establecido enbrowser) - jsdom o emulaciones de DOM del lado del servidor similares
- Entornos donde los builtins nativos del navegador han sido interceptados (hooked) o reemplazados
El código funcionará correctamente en navegadores normales (Chrome, Firefox, Safari, Edge), incluso cuando se carga dentro de iframes, extensiones de navegador (content scripts) y Web Workers. Si necesitas ejecutar pruebas automatizadas contra código protegido, desactiva vmSelfDefending en los builds de prueba: esta opción está diseñada para impedir el análisis automatizado y no puede usarse de forma segura con ningún framework de automatización.
Muy recomendable usarla junto con vmDebugProtection, vmBytecodeArrayEncodingKey y vmBytecodeArrayEncodingKeyGetter.
vmDefenseHook
Type: { name: string, aliases?: object } Default: ''
vmDefenseHook toma un objeto con dos claves: name (obligatoria) y aliases (opcional).
name es una función global que define tu página anfitriona y que una defensa de la VM (vmDebugProtection / vmSelfDefending) llama con un objeto de señal cuando detecta una señal hostil: un depurador o inspector, un navegador headless / de automatización, un proceso de agente de codificación con IA, un dominio no permitido, etc. Úsala para informar del evento a tu backend (p. ej., navigator.sendBeacon). El hook es un mero sumidero de telemetría: su valor de retorno se ignora, y un hook ausente o que lanza una excepción es una operación nula silenciosa que nunca puede desactivar una defensa. Para cambiar lo que una defensa hace al detectar algo, usa vmDefenseReaction.
aliases renombra opcionalmente los campos de ese objeto de señal, lo que se explica más abajo en Renombrar los campos de señal.
El objeto de señal. El hook recibe una única signal:
source— el detector concreto que se activó (consulta la tabla).category— el grupo bajo el que informa:automation(navegadores no humanos),debugger(hay un depurador/inspector activo),sandbox(host instrumentado/falso),domain(violación del bloqueo de dominio),tamper(builtins parcheados en tiempo de ejecución) ointegrity(se alteró el propio código de la VM).score/threshold— con qué intensidad se activó el detector y el valor que tenía que alcanzar; el hook se dispara solo cuandoscore >= threshold. La mayoría de las comprobaciones son de todo o nada (una única señal decisiva);headlesssuma varias señales sobre la forma del navegador, por lo que suscoresuele ser mayor que suthreshold.
Registrar el hook. Defínelo como un global normal antes de que se cargue el bundle ofuscado: el runtime de la VM y sus defensas se ejecutan antes que tu programa (protegido), por lo que muchas detecciones se disparan durante el arranque:
// in your page, before the obfuscated script:
window.__vmDetection = function (signal) { navigator.sendBeacon('/vm-defense', JSON.stringify(signal)); };
// obfuscation option:
vmDefenseHook: { name: '__vmDetection' }
Un hook definido dentro del código fuente ofuscado se registra demasiado tarde para captar las detecciones del momento de arranque, y si se compila con la VM no puede alcanzarse hasta que tu programa se ejecute. En cualquier caso se mantiene seguro (un hook ausente no hace nada y una protección contra reentrada evita cualquier desbordamiento), pero para una cobertura completa regístralo por adelantado. Para proteger de todos modos tu lógica de notificación, mantén el hook registrado como un búfer de una sola línea ((window.__vmDet = window.__vmDet || []).push(signal)) y lee/envía ese búfer desde tu código ofuscado.
Renombrar los campos de señal (aliases). Los valores predeterminados source/category son nombres descriptivos, de modo que cualquiera que instrumente el callback (o lea la salida) puede reconocer la protección y qué detector se activó. aliases renombra los campos de señal a tokens opacos de tu elección, aplicados dentro de la VM antes de que se emita la señal, por lo que esos nombres nunca aparecen en la salida ni llegan al callback. Tu aplicación conoce su propio mapeo y reenvía los tokens a tu backend.
Los alias son por campo, manteniendo separados los renombrados de clave y de valor: cada campo toma una key (el nombre de propiedad que recibe el callback); los campos de nombre de tipo cadena source y category también toman un mapa values, mientras que score/threshold son números y solo toman una key. Los nombres que puedes mapear (cualquier otro se rechaza en tiempo de compilación):
- claves de campo —
source,category,score,threshold - valores de
source—headless,agent,node,debugger,timing,sandbox,domain,nativeHook,integrity - valores de
category—automation,debugger,sandbox,domain,tamper,integrity
vmDefenseHook: {
name: '__vmDetection',
aliases: {
source: { key: 'a8Qm', values: { headless: 'xP4m9Q' } },
category: { key: 'p3Tx', values: { automation: 'bQ7s1M' } },
score: { key: 's1' },
threshold: { key: 't1' }
}
// the callback now receives e.g. { a8Qm: 'xP4m9Q', p3Tx: 'bQ7s1M', s1: <score>, t1: <threshold> }
}
Esto es evasión de fingerprint, no secretismo: el mapeo aún puede inferirse mediante pruebas repetidas, por lo que su único beneficio es no exponer nombres estables y autoexplicativos. Las entradas sin definir conservan sus nombres predeterminados.
Una cadena simple (vmDefenseHook: '__vmDetection') se acepta como forma abreviada de { name: '__vmDetection' } pero está obsoleta: prefiere la forma de objeto.
vmDefenseReaction
Type: object Default: { automation: 'break', debugger: 'decoy', sandbox: 'decoy', domain: 'break', tamper: 'break', integrity: 'break' }
Configura cómo reacciona cada categoría de detección. No activa nada: las defensas en sí se activan con vmSelfDefending, vmDebugProtection y vmDomainLock; esta opción solo selecciona cómo reacciona una defensa ya activada. La categoría es la unidad de control: cada detector de una categoría aplica la reacción de esa categoría.
Cada categoría agrupa los detectores que vigilan un tipo de condición hostil. Una categoría solo reacciona cuando la opción que emite sus detectores está activada:
Cada categoría se corresponde con una o varias de vmSelfDefending, vmDebugProtection y vmDomainLock; no existe ninguna categoría fuera de esas tres opciones, y una reacción establecida para una categoría cuya opción está desactivada simplemente no tiene efecto.
Las claves son estos seis nombres de categoría, o default (un valor de reserva para las categorías no especificadas). Los valores son:
break— interrumpe inmediatamentedecoy— sigue ejecutándose con un estado envenenado, produciendo resultados incorrectos de forma silenciosanone— no hace nada localmente (solo telemetría)
Los valores predeterminados por categoría se muestran arriba; una categoría que no establezcas (o que establezcas a su valor predeterminado) usa ese valor predeterminado. default alcanza a todas las categorías, incluidas las que son correctas por construcción (integrity, tamper), de modo que { default: 'none' } es un build genuinamente no disruptivo, solo de telemetría:
vmDefenseReaction: { default: 'none' } // never break — pair with vmDefenseHook
vmDefenseReaction: { automation: 'none', domain: 'break' } // tolerate automation FPs, still break on a bad domain
vmStatefulOpcodes
Type: boolean Default: false
Hace que el significado de los opcodes dependa de su posición en el bytecode. Cada posición tiene un mapeo de opcode a manejador distinto derivado de una semilla, de modo que el mismo número de opcode realiza operaciones diferentes en posiciones diferentes.
vmCallContextOpcodes
Type: boolean Default: false
Hace que una función protegida dependa del lugar desde el que se la llama, de modo que no pueda extraerse del código y ejecutarse o analizarse por sí sola: solo se comporta correctamente cuando se la invoca a través de sus sitios de llamada reales dentro del programa. Esta opción afecta al rendimiento en tiempo de ejecución.
Actualmente solo se admiten las siguientes construcciones:
- declaraciones de función (
function f() {}); - expresiones de función y funciones flecha asignadas a una variable (
const f = () => {}); - métodos privados de instancia (
this.#m()).
En todos los casos, la función debe alcanzarse siempre mediante una llamada directa (f(), this.#m()). Si se almacena en otra variable, se pasa como argumento o se usa de cualquier otra forma como valor, se deja sin proteger. Se admiten las funciones asíncronas; los generadores no.
Esta opción es experimental y puede romper tu código, así que prueba la salida a fondo antes de usarla.
vmStackEncoding
Type: boolean Default: false
Cifra los valores de la pila de la VM durante la ejecución. Los valores se codifican al insertarlos (push) y se decodifican al extraerlos (pop), de modo que la inspección de la memoria muestra datos cifrados en lugar de los valores reales.
Esta opción afecta mucho al rendimiento.
vmCompactDispatcher
Type: boolean Default: false
Usa un único ejecutor de VM en lugar de ejecutores duales (síncrono + generador). Reduce el tamaño del código ofuscado, pero añade una sobrecarga de rendimiento de ~20% en código con mucha recursión.
false(predeterminado): ejecutores duales — rendimiento óptimo, salida más grandetrue: ejecutor único — salida más pequeña, ligeramente más lento
vmStringArrayBytecodeOnly
Type: boolean Default: false
Cuando está activada, el string array solo extraerá cadenas de los datos del bytecode; no se transforma ninguna otra cadena del código. Esto activa de forma forzada stringArray aunque no se haya establecido explícitamente.
Por qué usarla: Extraer todas las cadenas del runtime de la VM a un string array es lento. Esta opción apunta únicamente al contenido del bytecode para la extracción del string array, lo que mejora el rendimiento sin dejar de proteger las constantes del bytecode.
- Cuando
vmBytecodeArrayEncoding: false— se extraen las cadenas de los pools de constantes del bytecode (arraysc) - Cuando
vmBytecodeArrayEncoding: true— se extraen las cadenas de bytecode de nivel superior codificadas en base64 stringArrayThresholdsigue controlando qué porcentaje de esas cadenas de bytecode se extraen
vmDomainLock
Type: string[] Default: []
⚠️ Esta opción no funciona con target: 'node', target: 'service-worker' o target: 'bytenode'
Restringe el código ofuscado a dominios y/o subdominios concretos, y es mucho más difícil de localizar y eliminar que domainLock.
Si el código fuente no se ejecuta en los dominios especificados por esta opción, el navegador será redirigido a la URL pasada a vmDomainLockRedirectUrl, y las llamadas protegidas posteriores devolverán resultados incorrectos incluso si se suprime la redirección.
Varios dominios y subdominios
Es posible bloquear tu código en más de un dominio o subdominio. Por ejemplo, para bloquearlo de modo que el código solo se ejecute en www.example.com añade www.example.com. Para que funcione en el dominio raíz incluyendo cualquier subdominio (example.com, sub.example.com), usa .example.com.
vmDomainLockRedirectUrl
Type: string Default: about:blank
⚠️ Esta opción no funciona con target: 'node', target: 'service-worker' o target: 'bytenode'
Permite redirigir el navegador a una URL indicada si el código fuente no se ejecuta en los dominios especificados por vmDomainLock.
Preset Options
Ofuscación alta, rendimiento bajo
El rendimiento será mucho más lento que sin ofuscación
{
compact: true,
controlFlowFlattening: true,
controlFlowFlatteningThreshold: 1,
deadCodeInjection: true,
deadCodeInjectionThreshold: 1,
debugProtection: true,
debugProtectionInterval: 4000,
disableConsoleOutput: true,
identifierNamesGenerator: 'hexadecimal',
log: false,
numbersToExpressions: true,
renameGlobals: false,
selfDefending: true,
simplify: true,
splitStrings: true,
splitStringsChunkLength: 5,
strictMode: null,
stringArray: true,
stringArrayCallsTransform: true,
stringArrayEncoding: ['rc4'],
stringArrayIndexShift: true,
stringArrayRotate: true,
stringArrayShuffle: true,
stringArrayWrappersCount: 5,
stringArrayWrappersChainedCalls: true,
stringArrayWrappersParametersMaxCount: 5,
stringArrayWrappersType: 'function',
stringArrayThreshold: 1,
transformObjectKeys: true
}
Ofuscación media, rendimiento óptimo
El rendimiento será más lento que sin ofuscación
{
compact: true,
controlFlowFlattening: true,
controlFlowFlatteningThreshold: 0.75,
deadCodeInjection: true,
deadCodeInjectionThreshold: 0.4,
debugProtection: false,
debugProtectionInterval: 0,
disableConsoleOutput: true,
identifierNamesGenerator: 'hexadecimal',
log: false,
numbersToExpressions: true,
renameGlobals: false,
selfDefending: true,
simplify: true,
splitStrings: true,
splitStringsChunkLength: 10,
strictMode: null,
stringArray: true,
stringArrayCallsTransform: true,
stringArrayCallsTransformThreshold: 0.75,
stringArrayEncoding: ['base64'],
stringArrayIndexShift: true,
stringArrayRotate: true,
stringArrayShuffle: true,
stringArrayWrappersCount: 2,
stringArrayWrappersChainedCalls: true,
stringArrayWrappersParametersMaxCount: 4,
stringArrayWrappersType: 'function',
stringArrayThreshold: 0.75,
transformObjectKeys: true
}
Ofuscación baja, rendimiento alto
El rendimiento se mantendrá en un nivel relativamente normal
{
compact: true,
controlFlowFlattening: false,
deadCodeInjection: false,
debugProtection: false,
debugProtectionInterval: 0,
disableConsoleOutput: true,
identifierNamesGenerator: 'hexadecimal',
log: false,
numbersToExpressions: false,
renameGlobals: false,
selfDefending: true,
simplify: true,
splitStrings: false,
strictMode: null,
stringArray: true,
stringArrayCallsTransform: false,
stringArrayEncoding: [],
stringArrayIndexShift: true,
stringArrayRotate: true,
stringArrayShuffle: true,
stringArrayWrappersCount: 1,
stringArrayWrappersChainedCalls: true,
stringArrayWrappersParametersMaxCount: 2,
stringArrayWrappersType: 'variable',
stringArrayThreshold: 0.75
}
Preajuste predeterminado, rendimiento alto
{
compact: true,
controlFlowFlattening: false,
deadCodeInjection: false,
debugProtection: false,
debugProtectionInterval: 0,
disableConsoleOutput: false,
identifierNamesGenerator: 'hexadecimal',
log: false,
numbersToExpressions: false,
renameGlobals: false,
selfDefending: false,
simplify: true,
splitStrings: false,
strictMode: null,
stringArray: true,
stringArrayCallsTransform: false,
stringArrayCallsTransformThreshold: 0.5,
stringArrayEncoding: [],
stringArrayIndexShift: true,
stringArrayRotate: true,
stringArrayShuffle: true,
stringArrayWrappersCount: 1,
stringArrayWrappersChainedCalls: true,
stringArrayWrappersParametersMaxCount: 2,
stringArrayWrappersType: 'variable',
stringArrayThreshold: 0.75
}
Ofuscación VM Ultra High (seguridad máxima)
Este preajuste activa la ofuscación basada en bytecode de VM con todas las funciones de refuerzo, incluido el despacho indirecto. Ofrece la protección más fuerte, pero con un mayor tamaño de salida y una ejecución mucho más lenta.
{
optionsPreset: 'vm-ultra-high-obfuscation'
}
O configúralo individualmente:
{
compact: true,
simplify: true,
identifierNamesGenerator: 'mangled-shuffled',
vmObfuscation: true,
vmForceCompileDynamicCode: false,
vmWrapTopLevelInitializers: true,
vmDynamicOpcodes: true,
vmBytecodeEncoding: true,
vmBytecodeArrayEncoding: true,
vmBytecodeArrayEncodingKey: '',
vmBytecodeArrayEncodingKeyGetter: '',
vmAsyncExecutor: false,
vmJumpsEncoding: true,
vmMacroOps: true,
vmDebugProtection: true,
vmSelfDefending: true,
vmDefenseHook: '',
vmDefenseReaction: {
automation: 'break',
debugger: 'decoy',
sandbox: 'decoy',
domain: 'break',
tamper: 'break',
integrity: 'break'
},
vmStatefulOpcodes: true,
vmCallContextOpcodes: false,
vmStackEncoding: true,
vmCompactDispatcher: true,
controlFlowFlattening: true,
controlFlowFlatteningThreshold: 0.5,
deadCodeInjection: true,
deadCodeInjectionThreshold: 0.5,
debugProtection: true,
debugProtectionInterval: 4000,
disableConsoleOutput: true,
identifierNamesGenerator: 'hexadecimal',
log: false,
numbersToExpressions: true,
renameGlobals: false,
selfDefending: true,
simplify: true,
splitStrings: true,
splitStringsChunkLength: 5,
strictMode: null,
stringArray: true,
stringArrayCallsTransform: true,
stringArrayEncoding: ['rc4'],
stringArrayIndexShift: true,
stringArrayRotate: true,
stringArrayShuffle: true,
stringArrayWrappersCount: 5,
stringArrayWrappersChainedCalls: true,
stringArrayWrappersParametersMaxCount: 5,
stringArrayWrappersType: 'function',
stringArrayThreshold: 0.5,
transformObjectKeys: true
}
VM Anti-LLM (protección contra agentes de IA)
Este preajuste está diseñado específicamente para impedir que los agentes de IA y los LLM apliquen ingeniería inversa al código convertido a bytecode de VM. Se basa en vm-default con la autodefensa y la protección de depuración activadas. Es más ligero que vm-high-obfuscation, pero está reforzado específicamente contra el análisis automatizado.
{
optionsPreset: 'vm-anti-llm'
}
Incluye:
- Ofuscación con bytecode de VM con string array (de
vm-default) vmSelfDefending— detección anti-hook, hash de integridad, fingerprint del código fuente, verificación de realm limpio con iframe, derivación de clave con cifrado ARXvmDebugProtection— comprobaciones antidepuración en el bucle de despacho de la VMdebugProtection: false— sin protección de depuración heredada (la protección de depuración de la VM es superior)
Ofuscación VM High (seguridad más alta)
Este preajuste activa la ofuscación basada en bytecode de VM con la mayoría de las funciones de refuerzo. Ofrece una protección fuerte con mejor rendimiento que el preajuste ultra-high.
{
optionsPreset: 'vm-high-obfuscation'
}
O configúralo individualmente:
{
compact: true,
simplify: true,
identifierNamesGenerator: 'mangled-shuffled',
vmObfuscation: true,
vmForceCompileDynamicCode: false,
vmWrapTopLevelInitializers: true,
vmDynamicOpcodes: true,
vmBytecodeEncoding: true,
vmBytecodeArrayEncoding: true,
vmBytecodeArrayEncodingKey: '',
vmBytecodeArrayEncodingKeyGetter: '',
vmAsyncExecutor: false,
vmJumpsEncoding: true,
vmMacroOps: true,
vmDebugProtection: true,
vmSelfDefending: true,
vmDefenseHook: '',
vmDefenseReaction: {
automation: 'break',
debugger: 'decoy',
sandbox: 'decoy',
domain: 'break',
tamper: 'break',
integrity: 'break'
},
vmStatefulOpcodes: true,
vmCallContextOpcodes: false,
vmStackEncoding: true,
vmCompactDispatcher: false
}
Ofuscación VM Medium (seguridad equilibrada)
Este preajuste activa la ofuscación basada en bytecode de VM con un conjunto equilibrado de funciones de refuerzo. Buen compromiso entre seguridad y rendimiento.
{
optionsPreset: 'vm-medium-obfuscation'
}
O configúralo individualmente:
{
compact: true,
simplify: true,
identifierNamesGenerator: 'mangled-shuffled',
vmObfuscation: true,
vmForceCompileDynamicCode: false,
vmWrapTopLevelInitializers: true,
vmDynamicOpcodes: true,
vmBytecodeEncoding: true,
vmBytecodeArrayEncoding: false,
vmBytecodeArrayEncodingKey: '',
vmBytecodeArrayEncodingKeyGetter: '',
vmAsyncExecutor: false,
vmJumpsEncoding: true,
vmMacroOps: true,
vmDebugProtection: true,
vmSelfDefending: false,
vmDefenseHook: '',
vmDefenseReaction: {
automation: 'break',
debugger: 'decoy',
sandbox: 'decoy',
domain: 'break',
tamper: 'break',
integrity: 'break'
},
vmStatefulOpcodes: false,
vmCallContextOpcodes: false,
vmStackEncoding: false,
vmCompactDispatcher: false
}
Ofuscación VM Low (seguridad básica, mejor rendimiento)
Este preajuste activa una ofuscación básica basada en bytecode de VM sin funciones de refuerzo adicionales. Buen equilibrio entre seguridad y tamaño de salida.
{
optionsPreset: 'vm-low-obfuscation'
}
O configúralo individualmente:
{
compact: true,
simplify: true,
identifierNamesGenerator: 'mangled-shuffled',
vmObfuscation: true,
vmForceCompileDynamicCode: false,
vmWrapTopLevelInitializers: true,
vmDynamicOpcodes: false,
vmBytecodeEncoding: false,
vmBytecodeArrayEncoding: false,
vmBytecodeArrayEncodingKey: '',
vmBytecodeArrayEncodingKeyGetter: '',
vmAsyncExecutor: false,
vmJumpsEncoding: false,
vmMacroOps: false,
vmDebugProtection: false,
vmSelfDefending: false,
vmDefenseHook: '',
vmDefenseReaction: {
automation: 'break',
debugger: 'decoy',
sandbox: 'decoy',
domain: 'break',
tamper: 'break',
integrity: 'break'
},
vmStatefulOpcodes: false,
vmCallContextOpcodes: false,
vmStackEncoding: false,
vmCompactDispatcher: false
}
VM Default (VM + protección con String Array)
Este preajuste combina una ofuscación básica basada en bytecode de VM con la protección de string array. Buen punto de partida para la ofuscación VM con protección de cadenas.
{
optionsPreset: 'vm-default'
}
O configúralo individualmente:
{
compact: true,
simplify: true,
identifierNamesGenerator: 'mangled-shuffled',
vmObfuscation: true,
vmForceCompileDynamicCode: false,
vmWrapTopLevelInitializers: true,
vmDynamicOpcodes: true,
vmBytecodeEncoding: false,
vmBytecodeArrayEncoding: true,
vmStringArrayBytecodeOnly: true,
vmAsyncExecutor: false,
vmJumpsEncoding: false,
vmMacroOps: false,
vmDebugProtection: false,
vmSelfDefending: false,
vmDefenseHook: '',
vmDefenseReaction: {
automation: 'break',
debugger: 'decoy',
sandbox: 'decoy',
domain: 'break',
tamper: 'break',
integrity: 'break'
},
vmStatefulOpcodes: false,
vmCallContextOpcodes: false,
vmStackEncoding: false,
vmCompactDispatcher: false,
stringArray: true,
stringArrayRotate: true,
stringArrayShuffle: true,
stringArrayThreshold: 1,
stringArrayIndexShift: true,
stringArrayIndexesType: ['hexadecimal-number'],
stringArrayCallsTransform: true,
stringArrayCallsTransformThreshold: 1,
stringArrayWrappersCount: 3,
stringArrayWrappersType: 'function',
stringArrayWrappersParametersMaxCount: 5,
stringArrayWrappersChainedCalls: true,
stringArrayEncoding: ['base64'],
splitStrings: true,
splitStringsChunkLength: 6
}
compact
Type: boolean Default: true
Compacta el código de salida en una sola línea.
config
Type: string Default: ``
Nombre del archivo de configuración JS/JSON que contiene las opciones del ofuscador. Estas serán anuladas por las opciones pasadas directamente a la CLI
controlFlowFlattening
Type: boolean Default: false
⚠️ Esta opción afecta enormemente al rendimiento, con una velocidad de ejecución hasta 1,5 veces más lenta. Usa controlFlowFlatteningThreshold para establecer el porcentaje de nodos que se verán afectados por el aplanamiento del flujo de control.
Activa el aplanamiento del flujo de control del código. El aplanamiento del flujo de control es una transformación de la estructura del código fuente que dificulta la comprensión del programa.
Ejemplo:
// input
(function(){
function foo () {
return function () {
var sum = 1 + 2;
console.log(1);
console.log(2);
console.log(3);
console.log(4);
console.log(5);
console.log(6);
}
}
foo()();
})();
// output
(function () {
function _0x3bfc5c() {
return function () {
var _0x3260a5 = {
'WtABe': '4|0|6|5|3|2|1',
'GokKo': function _0xf87260(_0x427a8e, _0x43354c) {
return _0x427a8e + _0x43354c;
}
};
var _0x1ad4d6 = _0x3260a5['WtABe']['split']('|'), _0x1a7b12 = 0x0;
while (!![]) {
switch (_0x1ad4d6[_0x1a7b12++]) {
case '0':
console['log'](0x1);
continue;
case '1':
console['log'](0x6);
continue;
case '2':
console['log'](0x5);
continue;
case '3':
console['log'](0x4);
continue;
case '4':
var _0x1f2f2f = _0x3260a5['GokKo'](0x1, 0x2);
continue;
case '5':
console['log'](0x3);
continue;
case '6':
console['log'](0x2);
continue;
}
break;
}
};
}
_0x3bfc5c()();
}());
controlFlowFlatteningThreshold
Type: number Default: 0.75 Min: 0 Max: 1
La probabilidad de que la transformación controlFlowFlattening se aplique a un nodo concreto.
Este ajuste resulta especialmente útil con bases de código grandes, ya que una gran cantidad de transformaciones del flujo de control puede ralentizar tu código y aumentar su tamaño.
controlFlowFlatteningThreshold: 0 equivale a controlFlowFlattening: false.
deadCodeInjection
Type: boolean Default: false
⚠️ Aumenta drásticamente el tamaño del código ofuscado (hasta un 200%); úsala solo si el tamaño del código ofuscado no importa. Usa deadCodeInjectionThreshold para establecer el porcentaje de nodos que se verán afectados por la inyección de código muerto.
⚠️ Esta opción activa de forma forzada la opción stringArray.
⚠️ Esta opción se desactiva silenciosamente cuando vmObfuscation está activada.
Con esta opción, se añadirán bloques aleatorios de código muerto al código ofuscado.
Ejemplo:
// input
(function(){
if (true) {
var foo = function () {
console.log('abc');
};
var bar = function () {
console.log('def');
};
var baz = function () {
console.log('ghi');
};
var bark = function () {
console.log('jkl');
};
var hawk = function () {
console.log('mno');
};
foo();
bar();
baz();
bark();
hawk();
}
})();
// output
var _0x37b8 = [
'YBCtz',
'GlrkA',
'urPbb',
'abc',
'NMIhC',
'yZgAj',
'zrAId',
'EtyJA',
'log',
'mno',
'jkl',
'def',
'Quzya',
'IWbBa',
'ghi'
];
function _0x43a7(_0x12cf56, _0x587376) {
_0x43a7 = function (_0x2f87a8, _0x47eac2) {
_0x2f87a8 = _0x2f87a8 - (0x16a7 * 0x1 + 0x5 * 0x151 + -0x1c92);
var _0x341e03 = _0x37b8[_0x2f87a8];
return _0x341e03;
};
return _0x43a7(_0x12cf56, _0x587376);
}
(function () {
if (!![]) {
var _0xbbe28f = function () {
var _0x2fc85f = _0x43a7;
if (_0x2fc85f(0xaf) === _0x2fc85f(0xae)) {
_0x1dd94f[_0x2fc85f(0xb2)](_0x2fc85f(0xb5));
} else {
console[_0x2fc85f(0xb2)](_0x2fc85f(0xad));
}
};
var _0x5e46bc = function () {
var _0x15b472 = _0x43a7;
if (_0x15b472(0xb6) !== _0x15b472(0xaa)) {
console[_0x15b472(0xb2)](_0x15b472(0xb5));
} else {
_0x47eac2[_0x15b472(0xb2)](_0x15b472(0xad));
}
};
var _0x3669e8 = function () {
var _0x47a442 = _0x43a7;
if (_0x47a442(0xb7) !== _0x47a442(0xb0)) {
console[_0x47a442(0xb2)](_0x47a442(0xb8));
} else {
_0x24e0bf[_0x47a442(0xb2)](_0x47a442(0xb3));
}
};
var _0x28b05a = function () {
var _0x497902 = _0x43a7;
if (_0x497902(0xb1) === _0x497902(0xb1)) {
console[_0x497902(0xb2)](_0x497902(0xb4));
} else {
_0x59c9c6[_0x497902(0xb2)](_0x497902(0xb4));
}
};
var _0x402a54 = function () {
var _0x1906b7 = _0x43a7;
if (_0x1906b7(0xab) === _0x1906b7(0xac)) {
_0xb89cd0[_0x1906b7(0xb2)](_0x1906b7(0xb8));
} else {
console[_0x1906b7(0xb2)](_0x1906b7(0xb3));
}
};
_0xbbe28f();
_0x5e46bc();
_0x3669e8();
_0x28b05a();
_0x402a54();
}
}());
deadCodeInjectionThreshold
Type: number Default: 0.4 Min: 0 Max: 1
Permite establecer el porcentaje de nodos que se verán afectados por deadCodeInjection.
debugProtection
Type: boolean Default: false
⚠️ Puede congelar tu navegador si abres las Herramientas de desarrollo.
⚠️ Esta opción se desactiva silenciosamente cuando vmObfuscation está activada. Usa vmDebugProtection en su lugar.
Esta opción hace casi imposible usar la función debugger de las Herramientas de desarrollo (tanto en navegadores basados en WebKit como en Mozilla Firefox).
debugProtectionInterval
Type: number Default: 0
⚠️ ¡Puede congelar tu navegador! Úsala bajo tu propia responsabilidad.
⚠️ Esta opción se desactiva silenciosamente cuando vmObfuscation está activada. Usa vmDebugProtection en su lugar.
Si se establece, se utiliza un intervalo en milisegundos para forzar el modo de depuración en la pestaña Consola, lo que dificulta usar otras funciones de las Herramientas de desarrollo. Funciona si debugProtection está activada. El valor recomendado está entre 2000 y 4000 milisegundos.
disableConsoleOutput
Type: boolean Default: false
⚠️ Esta opción desactiva las llamadas a console de forma global para todos los scripts
Desactiva el uso de console.log, console.info, console.error, console.warn, console.debug, console.exception y console.trace reemplazándolos por funciones vacías. Esto dificulta el uso del depurador.
domainLock
Type: string[] Default: []
⚠️ Esta opción no funciona con target: 'node', target: 'service-worker' o target: 'bytenode'
Permite ejecutar el código fuente ofuscado únicamente en dominios y/o subdominios concretos. Esto hace muy difícil que alguien se limite a copiar y pegar tu código fuente y ejecutarlo en otro sitio.
Si el código fuente no se ejecuta en los dominios especificados por esta opción, el navegador será redirigido a la URL pasada a la opción domainLockRedirectUrl.
Varios dominios y subdominios
Es posible bloquear tu código en más de un dominio o subdominio. Por ejemplo, para bloquearlo de modo que el código solo se ejecute en www.example.com añade www.example.com. Para que funcione en el dominio raíz incluyendo cualquier subdominio (example.com, sub.example.com), usa .example.com.
domainLockRedirectUrl
Type: string Default: about:blank
⚠️ Esta opción no funciona con target: 'node', target: 'service-worker' o target: 'bytenode'
Permite redirigir el navegador a una URL indicada si el código fuente no se ejecuta en los dominios especificados por domainLock
exclude
Type: string[] Default: []
Nombres de archivo o globs que indican qué archivos excluir de la ofuscación.
forceTransformStrings
Type: string[] Default: []
Activa la transformación forzada de los literales de cadena que coinciden con los patrones RegExp indicados.
⚠️ Esta opción solo afecta a las cadenas que no deberían transformarse según stringArrayThreshold (o posibles otros umbrales en el futuro)
La opción tiene prioridad sobre la opción reservedStrings, pero no sobre los comentarios condicionales.
Ejemplo:
{
forceTransformStrings: [
'some-important-value',
'some-string_\d'
]
}
identifierNamesCache
Type: Object | null Default: null
El objetivo principal de esta opción es poder usar los mismos nombres de identificadores durante la ofuscación de varios códigos fuente/archivos.
Actualmente se admiten dos tipos de identificadores:
- Identificadores globales:
- Todos los identificadores globales se escribirán en la caché;
- Todos los identificadores globales no declarados que coincidan se reemplazarán por los valores de la caché.
- Identificadores de propiedades, solo cuando la opción
renamePropertiesestá activada:- Todos los identificadores de propiedades se escribirán en la caché;
- Todos los identificadores de propiedades que coincidan se reemplazarán por los valores de la caché.
API de Node.js
Si se pasa un valor null, se desactiva por completo la caché.
Si se pasa un objeto vacío ({}), se activa la escritura de nombres de identificadores en el objeto de caché (tipo TIdentifierNamesCache). Se accederá a este objeto de caché mediante la llamada al método getIdentifierNamesCache del objeto ObfuscationResult.
El objeto de caché resultante puede usarse a continuación como valor de la opción identifierNamesGenerator para emplear estos nombres durante la ofuscación de todos los nombres de identificadores coincidentes de los códigos fuente siguientes.
Ejemplo:
const source1ObfuscationResult = JavaScriptObfuscator.obfuscate(
`
function foo(arg) {
console.log(arg)
}
function bar() {
var bark = 2;
}
`,
{
compact: false,
identifierNamesCache: {},
renameGlobals: true
}
)
console.log(source1ObfuscationResult.getIdentifierNamesCache());
/*
{
globalIdentifiers: {
foo: '_0x5de86d',
bar: '_0x2a943b'
}
}
*/
const source2ObfuscationResult = JavaScriptObfuscator.obfuscate(
`
// Expecting that these global functions are defined in another obfuscated file
foo(1);
bar();
// Expecting that this global function is defined in third-party package
baz();
`,
{
compact: false,
identifierNamesCache: source1ObfuscationResult.getIdentifierNamesCache(),
renameGlobals: true
}
)
console.log(source2ObfuscationResult.getObfuscatedCode());
/*
_0x5de86d(0x1);
_0x2a943b();
baz();
*/
CLI
La CLI tiene una opción distinta, --identifier-names-cache-path, que permite definir una ruta a un archivo .json existente que se usará para leer y escribir la caché de nombres de identificadores.
Si se pasa una ruta a un archivo vacío, la caché de nombres de identificadores se escribirá en ese archivo.
Este archivo con la caché existente puede volver a usarse como valor de la opción --identifier-names-cache-path para emplear estos nombres durante la ofuscación de todos los nombres de identificadores coincidentes de los archivos siguientes.
identifierNamesGenerator
Type: string Default: hexadecimal
Establece el generador de nombres de identificadores.
Valores disponibles:
dictionary: nombres de identificadores de la listaidentifiersDictionaryhexadecimal: nombres de identificadores como_0xabc123mangled: nombres de identificadores cortos comoa,b,cmangled-shuffled: igual quemangledpero con el alfabeto mezclado
identifiersDictionary
Type: string[] Default: []
Establece el diccionario de identificadores para la opción identifierNamesGenerator: dictionary. Cada identificador del diccionario se usará en varias variantes con distintas combinaciones de mayúsculas y minúsculas de cada carácter. Por tanto, el número de identificadores del diccionario debería depender de la cantidad de identificadores del código fuente original.
identifiersPrefix
Type: string Default: ''
Establece un prefijo para todos los identificadores globales.
Usa esta opción cuando quieras ofuscar varios archivos. Esta opción ayuda a evitar conflictos entre los identificadores globales de dichos archivos. El prefijo debería ser distinto para cada archivo.
randomIdentifiersPrefix
Type: boolean Default: false
Añade un prefijo aleatorio basado en la semilla (6 caracteres alfanuméricos) a todos los identificadores globales. Usa esta opción para evitar colisiones entre bundles ofuscados por separado que se cargan en el mismo ámbito global: elimina la necesidad de elegir manualmente un identifiersPrefix único para cada bundle.
- El valor aleatorio se deriva de la opción
seedy del hash del código fuente, de modo que los builds reproducibles con la misma semilla producen el mismo prefijo. - Cuando se combina con
identifiersPrefix, los caracteres aleatorios se añaden al prefijo indicado por el usuario (p. ej.,myApp+ aleatorioaBc123→myAppaBc123). - Cuando se combina con
vmObfuscation, el valor aleatorio sustituye al prefijovmpredeterminado: la aleatoriedad ya garantiza la unicidad.
ignoreImports
Type: boolean Default: false
Impide la ofuscación de las importaciones require. Puede resultar útil en algunos casos en los que, por alguna razón, el entorno de ejecución exige estas importaciones solo con cadenas estáticas.
inputFileName
Type: string Default: ''
Permite establecer el nombre del archivo de entrada con el código fuente. Este nombre se usará internamente para la generación del source map.
Obligatorio cuando se usa la API de NodeJS y la opción sourceMapSourcesMode tiene el valor sources.
log
Type: boolean Default: false
Activa el registro de la información en la consola.
numbersToExpressions
Type: boolean Default: false
Activa la conversión de números en expresiones
Ejemplo:
// input
const foo = 1234;
// output
const foo=-0xd93+-0x10b4+0x41*0x67+0x84e*0x3+-0xff8;
optionsPreset
Type: string Default: default
Permite establecer un preajuste de opciones.
Valores disponibles:
vm-default;vm-low-obfuscation;vm-medium-obfuscation;vm-high-obfuscation;vm-ultra-high-obfuscation;vm-anti-llm;default;low-obfuscation;medium-obfuscation;high-obfuscation.
Todas las opciones adicionales se combinarán con el preajuste de opciones seleccionado.
parseHtml
Type: boolean Default: false
Activa la ofuscación de JavaScript dentro de las etiquetas <script> de HTML.
Cuando está activada, el ofuscador:
- Detecta automáticamente si la entrada es HTML (comprobando las etiquetas
<!DOCTYPE,<html>,<head>,<body>o<script>) - Extrae el JavaScript de las etiquetas
<script>marcadas con el atributodata-javascript-obfuscator - Ofusca cada script marcado de forma individual conservando la estructura del HTML
- Reinserta el código ofuscado en sus posiciones originales
Importante: solo se ofuscan los scripts que tengan el atributo data-javascript-obfuscator. Cada script marcado se ofusca de forma individual e independiente. Esto significa que:
- El código dentro de las etiquetas de script marcadas debe estar aislado: NO debe hacer referencia a variables, funciones o clases definidas en otras etiquetas de script marcadas
- Los scripts no marcados aún pueden acceder a los globales definidos por los scripts marcados (mediante declaraciones
varo asignaciones explícitas aglobalThis) - Esto te da un control explícito sobre qué scripts proteger
Se ofuscan (deben tener el atributo data-javascript-obfuscator):
<script data-javascript-obfuscator>- scripts normales<script type="text/javascript" data-javascript-obfuscator>- scripts con tipo explícito- Scripts con cualquier atributo adicional (
id,class, otrosdata-*, etc.)
Se omiten (se dejan sin cambios):
- Scripts sin el atributo
data-javascript-obfuscator <script type="module">- módulos ES (aunque tengan el atributo)<script src="...">- scripts externos (aunque tengan el atributo)- Etiquetas de script vacías
Nota: los source maps no se generan cuando parseHtml está activada, ya que no se corresponderían correctamente con la salida HTML.
Ejemplo:
// input
const html = `<!DOCTYPE html>
<html>
<body>
<!-- This script will NOT be obfuscated -->
<script>
var helper = 'utility';
</script>
<!-- This script WILL be obfuscated -->
<script data-javascript-obfuscator>
var greeting = 'Hello World';
console.log(greeting);
</script>
</body>
</html>`;
JavaScriptObfuscator.obfuscate(html, {
parseHtml: true,
stringArray: true
});
// output: HTML with only the marked script obfuscated
renameGlobals
Type: boolean Default: false
⚠️ esta opción puede romper tu código. ¡Actívala solo si sabes lo que hace!
Activa la ofuscación de los nombres de variables y funciones globales con su declaración.
Cuando esta opción está desactivada y el código de entrada declara funciones o clases en el ámbito global (es decir, el código no está envuelto en una IIFE), sus nombres se conservan tal cual en la salida ofuscada: otros scripts pueden referenciarlos por su nombre. Con vmObfuscation se informa de una advertencia VMGlobalFunctionNamesNotRenamed que lista estos nombres, ya que el cuerpo de la función se oculta como bytecode pero el nombre de nivel superior, legible, sigue revelando lo que hace el código (por ejemplo, a un LLM). Para evitar esta exposición, envuelve el código en una IIFE o activa esta opción.
renameProperties
Type: boolean Default: false
⚠️ esta opción PUEDE romper tu código. ¡Actívala solo si sabes lo que hace!
Activa el renombrado de los nombres de propiedades. Se ignorarán todas las propiedades DOM integradas y las propiedades de las clases fundamentales de JavaScript.
Para alternar entre los modos safe y unsafe de esta opción, usa la opción renamePropertiesMode.
Para establecer el formato de los nombres de propiedades renombrados, usa la opción identifierNamesGenerator.
Para controlar qué propiedades se renombrarán, usa la opción reservedNames.
Ejemplo:
// input
(function () {
const foo = {
prop1: 1,
prop2: 2,
calc: function () {
return this.prop1 + this.prop2;
}
};
console.log(foo.calc());
})();
// output
(function () {
const _0x46529b = {
'_0x10cec7': 0x1,
'_0xc1c0ca': 0x2,
'_0x4b961d': function () {
return this['_0x10cec7'] + this['_0xc1c0ca'];
}
};
console['log'](_0x46529b['_0x4b961d']());
}());
renamePropertiesMode
Type: string Default: safe
⚠️ Incluso en el modo safe, la opción renameProperties PUEDE romper tu código.
Especifica el modo de la opción renameProperties:
safe- comportamiento predeterminado a partir de la versión2.11.0. Intenta renombrar las propiedades de una forma más segura para evitar errores en tiempo de ejecución. Con este modo, algunas propiedades quedarán excluidas del renombrado.unsafe- comportamiento predeterminado anterior a la versión2.11.0. Renombra las propiedades de forma no segura, sin ninguna restricción.
Si un archivo usa propiedades de otro archivo, utiliza la opción identifierNamesCache para mantener los mismos nombres de propiedades entre esos archivos.
reservedNames
Type: string[] Default: []
Desactiva la ofuscación y la generación de los identificadores que coinciden con los patrones RegExp indicados.
Ejemplo:
{
reservedNames: [
'^someVariable',
'functionParameter_\d'
]
}
reservedStrings
Type: string[] Default: []
Desactiva la transformación de los literales de cadena que coinciden con los patrones RegExp indicados. Las cadenas coincidentes permanecerán visibles en la salida ofuscada.
Al usar la ofuscación VM, las cadenas reservadas se almacenan en un array independiente sin cifrar para mantenerlas visibles. Esto es útil para cadenas que deben seguir siendo legibles, como endpoints de API para monitorización o identificadores de bibliotecas.
Ejemplo:
{
reservedStrings: [
'react-native',
'\.\/src\/test',
'some-string_\d'
]
}
seed
Type: string|number Default: 0
Esta opción establece la semilla del generador de números aleatorios. Es útil para crear resultados reproducibles.
Si la semilla es 0, el generador de números aleatorios funcionará sin semilla.
selfDefending
Type: boolean Default: false
⚠️ ¡No modifiques de ninguna manera el código ofuscado tras ofuscarlo con esta opción, porque cualquier cambio, como minificar el código, puede activar la autodefensa y el código dejará de funcionar!
⚠️ Esta opción fuerza el valor de compact a true
⚠️ Esta opción se desactiva silenciosamente cuando vmObfuscation está activada. Usa vmSelfDefending en su lugar.
Esta opción hace que el código de salida sea resistente al formateo y al renombrado de variables. Si alguien intenta aplicar un embellecedor (beautifier) de JavaScript al código ofuscado, el código dejará de funcionar, lo que dificulta entenderlo y modificarlo.
simplify
Type: boolean Default: true
Activa una ofuscación adicional del código mediante simplificación.
⚠️ en versiones futuras, la ofuscación de los literales boolean (true => !![]) se trasladará a esta opción.
Ejemplo:
// input
if (condition1) {
const foo = 1;
const bar = 2;
console.log(foo);
return bar;
} else if (condition2) {
console.log(1);
console.log(2);
console.log(3);
return 4;
} else {
return 5;
}
// output
if (condition1) {
const foo = 0x1, bar = 0x2;
return console['log'](foo), bar;
} else
return condition2 ? (console['log'](0x1), console['log'](0x2), console['log'](0x3), 0x4) : 0x5;
sourceMap
Type: boolean Default: false
Activa la generación de source maps para el código ofuscado.
Los source maps pueden resultar útiles para ayudarte a depurar tu código fuente JavaScript ofuscado. Si quieres o necesitas depurar en producción, puedes subir el archivo de source map por separado a una ubicación secreta y luego apuntar tu navegador a ella.
sourceMapBaseUrl
Type: string Default: ``
Establece la URL base para la URL de importación del source map cuando sourceMapMode: 'separate'.
Ejemplo de CLI:
javascript-obfuscator input.js --output out.js --source-map true --source-map-base-url 'http://localhost:9000'
Resultado:
//# sourceMappingURL=http://localhost:9000/out.js.map
sourceMapFileName
Type: string Default: ``
Establece el nombre de archivo del source map de salida cuando sourceMapMode: 'separate'.
Ejemplo de CLI:
javascript-obfuscator input.js --output out.js --source-map true --source-map-base-url 'http://localhost:9000' --source-map-file-name example
Resultado:
//# sourceMappingURL=http://localhost:9000/example.js.map
sourceMapMode
Type: string Default: separate
Especifica el modo de generación del source map:
inline- añade el source map al final de cada archivo .js;separate- genera el archivo '.map' correspondiente con el source map. Si ejecutas el ofuscador mediante la CLI, añade un enlace al archivo de source map al final del archivo con el código ofuscado//# sourceMappingUrl=file.js.map.
sourceMapSourcesMode
Type: string Default: sources-content
Permite controlar los campos sources y sourcesContent del source map:
sources-content- añade un camposourcesficticio y un camposourcesContentcon el código fuente original;sources- añade un camposourcescon una descripción de origen válida y no añade el camposourcesContent. Al usar la API de NodeJS es necesario definir la opcióninputFileName, que se usará como valor del camposources.
splitStrings
Type: boolean Default: false
Divide las cadenas literales en fragmentos con la longitud del valor de la opción splitStringsChunkLength.
Ejemplo:
// input
(function(){
var test = 'abcdefg';
})();
// output
(function(){
var _0x5a21 = 'ab' + 'cd' + 'ef' + 'g';
})();
splitStringsChunkLength
Type: number Default: 10
Establece la longitud de los fragmentos de la opción splitStrings.
stringArray
Type: boolean Default: true
Elimina los literales de cadena y los coloca en un array especial. Por ejemplo, la cadena "Hello World" en var m = "Hello World"; se reemplazará por algo como var m = _0x12c456[0x1];
stringArrayCallsTransform
Type: boolean Default: false
⚠️ la opción stringArray debe estar activada
Activa la transformación de las llamadas al stringArray. Todos los argumentos de estas llamadas pueden extraerse a un objeto distinto en función del valor de stringArrayCallsTransformThreshold.
Así resulta aún más difícil localizar automáticamente las llamadas al string array.
Ejemplo:
function foo() {
var k = {
c: 0x2f2,
d: '0x396',
e: '0x397',
f: '0x39a',
g: '0x39d',
h: 0x398,
l: 0x394,
m: '0x39b',
n: '0x39f',
o: 0x395,
p: 0x395,
q: 0x399,
r: '0x399'
};
var c = i(k.d, k.e);
var d = i(k.f, k.g);
var e = i(k.h, k.l);
var f = i(k.m, k.n);
function i(c, d) {
return b(c - k.c, d);
}
var g = i(k.o, k.p);
var h = i(k.q, k.r);
}
function j(c, d) {
var l = { c: 0x14b };
return b(c - -l.c, d);
}
console[j(-'0xa6', -'0xa6')](foo());
function b(c, d) {
var e = a();
b = function (f, g) {
f = f - 0xa3;
var h = e[f];
return h;
};
return b(c, d);
}
function a() {
var m = [
'string5',
'string1',
'log',
'string3',
'string6',
'string2',
'string4'
];
a = function () {
return m;
};
return a();
}
stringArrayCallsTransformThreshold
Type: number Default: 0.5
⚠️ las opciones stringArray y stringArrayCallsTransformThreshold deben estar activadas
Puedes usar este ajuste para regular la probabilidad (de 0 a 1) de que se transformen las llamadas al string array.
stringArrayEncoding
Type: string[] Default: []
⚠️ la opción stringArray debe estar activada
Esta opción puede ralentizar tu script.
Codifica todos los literales de cadena del stringArray usando base64 o rc4 e inserta un código especial que se emplea para decodificarlos de nuevo en tiempo de ejecución.
Cada valor del stringArray se codificará con la codificación elegida al azar de la lista indicada. Esto permite usar varias codificaciones.
Valores disponibles:
'none'(boolean): no codifica el valor delstringArray'base64'(string): codifica el valor delstringArrayusandobase64'rc4'(string): codifica el valor delstringArrayusandorc4. Alrededor de un 30-50% más lento quebase64, pero dificulta más obtener los valores iniciales.
Por ejemplo, con los siguientes valores de opción, algún valor del stringArray no se codificará y otros valores se codificarán con las codificaciones base64 y rc4:
stringArrayEncoding: [
'none',
'base64',
'rc4'
]
stringArrayIndexesType
Type: string[] Default: ['hexadecimal-number']
⚠️ la opción stringArray debe estar activada
Permite controlar el tipo de los índices de las llamadas al string array.
Cada índice de llamada al stringArray se transformará con el tipo elegido al azar de la lista indicada. Esto permite usar varios tipos.
Valores disponibles:
'hexadecimal-number'(default): transforma los índices de las llamadas al string array como números hexadecimales'hexadecimal-numeric-string': transforma los índices de las llamadas al string array como cadenas numéricas hexadecimales
Antes de la versión 2.9.0, javascript-obfuscator transformaba todos los índices de las llamadas al string array con el tipo hexadecimal-numeric-string. Esto dificulta ligeramente cierta desofuscación manual, pero permite que los desofuscadores automáticos detecten fácilmente estas llamadas.
El nuevo tipo hexadecimal-number busca dificultar la detección automática de los patrones de llamada al string array en el código.
Se añadirán más tipos en el futuro.
stringArrayIndexShift
Type: boolean Default: true
⚠️ la opción stringArray debe estar activada
Activa un desplazamiento de índice adicional para todas las llamadas al string array
stringArrayRotate
Type: boolean Default: true
⚠️ stringArray debe estar activada
Desplaza el array stringArray un número de posiciones fijo y aleatorio (generado durante la ofuscación del código). Esto dificulta hacer coincidir el orden de las cadenas eliminadas con su lugar original.
stringArrayShuffle
Type: boolean Default: true
⚠️ stringArray debe estar activada
Baraja aleatoriamente los elementos del array stringArray.
stringArrayWrappersCount
Type: number Default: 1
⚠️ la opción stringArray debe estar activada
Establece el número de wrappers del string array dentro de cada ámbito raíz o de función.
El número real de wrappers dentro de cada ámbito está limitado por la cantidad de nodos literal de ese ámbito.
Ejemplo:
// Input
const foo = 'foo';
const bar = 'bar';
function test () {
const baz = 'baz';
const bark = 'bark';
const hawk = 'hawk';
}
const eagle = 'eagle';
// Output, stringArrayWrappersCount: 5
const _0x3f6c = [
'bark',
'bar',
'foo',
'eagle',
'hawk',
'baz'
];
const _0x48f96e = _0x2e13;
const _0x4dfed8 = _0x2e13;
const _0x55e970 = _0x2e13;
function _0x2e13(_0x33c4f5, _0x3f6c62) {
_0x2e13 = function (_0x2e1388, _0x60b1e) {
_0x2e1388 = _0x2e1388 - 0xe2;
let _0x53d475 = _0x3f6c[_0x2e1388];
return _0x53d475;
};
return _0x2e13(_0x33c4f5, _0x3f6c62);
}
const foo = _0x48f96e(0xe4);
const bar = _0x4dfed8(0xe3);
function test() {
const _0x1c262f = _0x2e13;
const _0x54d7a4 = _0x2e13;
const _0x5142fe = _0x2e13;
const _0x1392b0 = _0x1c262f(0xe7);
const _0x201a58 = _0x1c262f(0xe2);
const _0xd3a7fb = _0x1c262f(0xe6);
}
const eagle = _0x48f96e(0xe5);
stringArrayWrappersChainedCalls
Type: boolean Default: true
⚠️ las opciones stringArray y stringArrayWrappersCount deben estar activadas
Activa las llamadas encadenadas entre los wrappers del string array.
Ejemplo:
// Input
const foo = 'foo';
const bar = 'bar';
function test () {
const baz = 'baz';
const bark = 'bark';
function test1() {
const hawk = 'hawk';
const eagle = 'eagle';
}
}
// Output, stringArrayWrappersCount: 5, stringArrayWrappersChainedCalls: true
const _0x40c2 = [
'bar',
'bark',
'hawk',
'eagle',
'foo',
'baz'
];
const _0x31c087 = _0x3280;
const _0x31759a = _0x3280;
function _0x3280(_0x1f52ee, _0x40c2a2) {
_0x3280 = function (_0x3280a4, _0xf07b02) {
_0x3280a4 = _0x3280a4 - 0x1c4;
let _0x57a182 = _0x40c2[_0x3280a4];
return _0x57a182;
};
return _0x3280(_0x1f52ee, _0x40c2a2);
}
const foo = _0x31c087(0x1c8);
const bar = _0x31c087(0x1c4);
function test() {
const _0x848719 = _0x31759a;
const _0x2693bf = _0x31c087;
const _0x2c08e8 = _0x848719(0x1c9);
const _0x359365 = _0x2693bf(0x1c5);
function _0x175e90() {
const _0x310023 = _0x848719;
const _0x2302ef = _0x2693bf;
const _0x237437 = _0x310023(0x1c6);
const _0x56145c = _0x310023(0x1c7);
}
}
stringArrayWrappersParametersMaxCount
Type: number Default: 2
⚠️ la opción stringArray debe estar activada
⚠️ Actualmente esta opción solo afecta a los wrappers añadidos por el valor function de la opción stringArrayWrappersType
Permite controlar el número máximo de parámetros de los wrappers del string array.
El valor predeterminado y mínimo es 2. El valor recomendado está entre 2 y 5.
stringArrayWrappersType
Type: string Default: variable
⚠️ las opciones stringArray y stringArrayWrappersCount deben estar activadas
Permite seleccionar el tipo de los wrappers que añade la opción stringArrayWrappersCount.
Valores disponibles:
'variable': añade wrappers de variable al principio de cada ámbito. Rendimiento rápido.'function': añade wrappers de función en posiciones aleatorias dentro de cada ámbito. Rendimiento más lento que convariable, pero ofrece una ofuscación más estricta.
Muy recomendable usar los wrappers function para una mayor ofuscación cuando la pérdida de rendimiento no tenga un gran impacto en la aplicación ofuscada.
Ejemplo del valor de opción 'function':
// input
const foo = 'foo';
function test () {
const bar = 'bar';
console.log(foo, bar);
}
test();
// output
const a = [
'log',
'bar',
'foo'
];
const foo = d(0x567, 0x568);
function b(c, d) {
b = function (e, f) {
e = e - 0x185;
let g = a[e];
return g;
};
return b(c, d);
}
function test() {
const c = e(0x51c, 0x51b);
function e (c, g) {
return b(c - 0x396, g);
}
console[f(0x51b, 0x51d)](foo, c);
function f (c, g) {
return b(c - 0x396, g);
}
}
function d (c, g) {
return b(g - 0x3e1, c);
}
test();
stringArrayThreshold
Type: number Default: 0.8 Min: 0 Max: 1
⚠️ la opción stringArray debe estar activada
Puedes usar este ajuste para regular la probabilidad (de 0 a 1) de que un literal de cadena se inserte en el stringArray.
Este ajuste resulta especialmente útil con bases de código grandes, ya que realiza llamadas repetidas al string array y puede ralentizar tu código.
stringArrayThreshold: 0 equivale a stringArray: false.
strictMode
Type: boolean | null Default: null
Permite especificar cómo debe tratar el ofuscador el código en relación con el modo estricto de JavaScript.
Valores disponibles:
null(predeterminado) - detecta automáticamente el modo estricto a partir del código. Si el código tiene una directiva'use strict'explícita, sintaxis de módulo ES o métodos de clase, se trata como modo estricto. En caso contrario, se asume el modo permisivo (sloppy).true- fuerza el tratamiento en modo estricto para todo el código, incluso sin una directiva'use strict'explícita. Úsalo cuando tu código vaya a ejecutarse en un contexto de modo estricto (por ejemplo, en módulos ES, bundlers o frameworks modernos).false- solo se tratan como estrictos los indicadores explícitos de modo estricto ('use strict', módulos ES, métodos de clase). La herencia del ámbito padre sigue aplicándose según la especificación de JS.
target
Type: string Default: browser
Permite establecer el entorno de destino del código ofuscado.
Valores disponibles:
browser(predeterminado) — entorno estándar de página web. El código de salida es idéntico al denode, pero algunas opciones específicas del navegador no pueden usarse con el targetnodebrowser-no-eval— igual quebrowser, pero la salida no usaeval(). Úsalo cuando la página de destino tenga una Content Security Policy que prohíbaeval/unsafe-eval.node— entorno Node.js. Las opciones específicas del navegador se desactivan (requierenwindow/documenty serían inoperantes o lanzarían errores en Node). Algunas defensas devmSelfDefendingque dependen de APIs exclusivas del navegador —detección de navegadores headless, recuperación de realm limpio basada en iframe, comprobaciones anti-inspector/DOM— no se emiten para este target.service-worker— contexto de Service Worker. Sinwindow, sindocument, con un globalselfdistinto.userscript— sandbox de un gestor de userscripts (p. ej., Tampermonkey). Las defensas devmSelfDefendingse ajustan en consecuencia.bytenode— código de Node.js que se compilará con el cargador bytenode (bytecode en caché de V8.jsc) tras la ofuscación. El propio ofuscador no invocabytenode; emite JavaScript ofuscado con VM cuyo runtime está estructurado para sobrevivir al paso de compilación de bytenode, y las defensas devmSelfDefendingse ajustan en consecuencia. Ejecuta tú mismobytenodesobre la salida ofuscada para producir el.jscfinal.
transformObjectKeys
Type: boolean Default: false
Activa la transformación de las claves de objeto.
Ejemplo:
// input
(function(){
var object = {
foo: 'test1',
bar: {
baz: 'test2'
}
};
})();
// output
var _0x4735 = [
'foo',
'baz',
'bar',
'test1',
'test2'
];
function _0x390c(_0x33d6b6, _0x4735f4) {
_0x390c = function (_0x390c37, _0x1eed85) {
_0x390c37 = _0x390c37 - 0x198;
var _0x2275f8 = _0x4735[_0x390c37];
return _0x2275f8;
};
return _0x390c(_0x33d6b6, _0x4735f4);
}
(function () {
var _0x17d1b7 = _0x390c;
var _0xc9b6bb = {};
_0xc9b6bb[_0x17d1b7(0x199)] = _0x17d1b7(0x19c);
var _0x3d959a = {};
_0x3d959a[_0x17d1b7(0x198)] = _0x17d1b7(0x19b);
_0x3d959a[_0x17d1b7(0x19a)] = _0xc9b6bb;
var _0x41fd86 = _0x3d959a;
}());
warnings
Type: string | object Default: all
Controla qué advertencias de ofuscación no fatales se emiten a través del método ObfuscationResult.getWarnings().
Valores disponibles:
'all'(predeterminado) — se emite cada advertencia.'none'— se suprimen todas las advertencias.- un objeto que asocia tipos de advertencia a booleanos — un tipo asociado a
falsese suprime; cada tipo no presente (o asociado atrue) permanece activado. Por ejemplo,{ "VMGlobalFunctionNamesNotRenamed": false }mantiene todas las advertencias salvo esa.
Tipos de advertencia:
VMGlobalFunctionNamesNotRenamed— convmObfuscation, los nombres de las declaraciones de funciones de nivel superior, las declaraciones de clase y las variables a las que se asigna una expresión de función/flecha/clase se conservaron tal cual (la opciónrenameGlobalsestá desactivada y el código no está envuelto en una IIFE), por lo que siguen siendo legibles en la salida aunque los cuerpos se oculten como bytecode. Los nombres exportados no se informan.VMTopLevelInitializerNotVirtualized— los inicializadores de variables de nivel superior permanecieron en JavaScript plano bajo la ofuscación VM porquevmWrapTopLevelInitializersestá desactivada o no pudo virtualizarlos.DynamicCodeRenameRisk— el código construye una función a partir de una cadena en tiempo de ejecución (evaldirecto, el constructorFunctionofn.toString()inyectado en un<script>/Worker), lo que puede hacer referencia a identificadores que el ofuscador ha renombrado.VMDynamicCodeSkipped— una función se omitió de la conversión a bytecode de la VM porque contieneevaldirecto /new Functiondinámico /Function(consultavmForceCompileDynamicCode).VMSyncFunctionSkippedInAsyncMode— convmAsyncExecutoractivada, una función que marcaste explícitamente en el modocommentresultó ser síncrona y se omitió (en ese modo solo se virtualizan las funciones asíncronas).VMAsyncGeneratorSkippedInAsyncMode— convmAsyncExecutory un getter de clave asíncrono activo, no se pudo virtualizar un generador asíncrono marcado (debe devolver su iterador de forma síncrona).BrowserTargetWithNodeStyleCode— el código parece dirigido a Node.js (p. ej.,require('fs'),__dirname,process.argv) mientras la opcióntargetestá establecida en un entorno de tipo navegador.
vmObfuscation
Type: boolean Default: false
Activa la ofuscación basada en bytecode de VM. Cuando está activada, las funciones de JavaScript se compilan a un bytecode personalizado que se ejecuta en una máquina virtual embebida. Esto proporciona el máximo nivel de protección, ya que la lógica original del código se transforma por completo.
Ejemplo:
Tu código legible, como return qty * price, se convierte en una lista de números como [0x15,0x03,0x17,...] que solo el intérprete embebido de la VM puede ejecutar. La lógica original deja de ser visible como JavaScript.
vmTargetFunctions
Type: string[] Default: []
Especifica exactamente por su nombre qué funciones de nivel raíz deben recibir protección VM.
Ejemplo:
{
vmObfuscation: true,
vmTargetFunctions: ['someFunctionName']
}
Resultado: Solo estas tres funciones quedan protegidas con VM. Todo lo demás permanece como JavaScript normal (pero aún ofuscado). Perfecto para proteger comprobaciones de licencia sensibles o la lógica de autenticación manteniendo el resto de tu código ligero.
vmExcludeFunctions
Type: string[] Default: []
Especifica funciones de nivel raíz que nunca deben recibir protección VM. Tiene prioridad sobre otros ajustes.
Ejemplo:
{
vmObfuscation: true,
vmExcludeFunctions: ['someFunctionName']
}
Cuándo usarla: Las funciones de nivel raíz críticas para el rendimiento (bucles de animación, procesamiento de datos en tiempo real) pueden excluirse para evitar la sobrecarga de la VM sin dejar de proteger todo lo demás.
vmTargetFunctionsMode
Type: string Default: root
Controla cómo se seleccionan las funciones/métodos para la ofuscación VM.
Ejemplo - Modo comment:
// Source code
function regularFunction() {
return 'not virtualized';
}
/* javascript-obfuscator:vm */
function sensitiveFunction() {
return 'this will be VM-protected';
}
function outer() {
/* javascript-obfuscator:vm */
function nestedSensitive() {
return 'nested but still VM-protected';
}
return nestedSensitive();
}
// Obfuscator options
{
vmObfuscation: true,
vmTargetFunctionsMode: 'comment'
}
Cuándo usarlo: Cuando necesitas un control quirúrgico sobre exactamente qué funciones reciben protección VM, especialmente funciones anidadas que contienen lógica sensible. A diferencia de vmTargetFunctions, que solo funciona con funciones con nombre de nivel raíz, el modo comment te permite proteger cualquier función en cualquier parte de tu código.
vmForceCompileDynamicCode
Type: boolean Default: false
Controla qué hace la ofuscación VM con una función que contiene una llamada a eval directo, new Function(...) o Function(...).
De forma predeterminada, dicha función (y cada función definida dentro de ella) se omite de la conversión a bytecode de la VM y se informa de una advertencia VMDynamicCodeSkipped en result.getWarnings(). Esto se debe a que el código fuente construido en tiempo de ejecución puede hacer referencia a identificadores de la cadena de ámbitos circundante, identificadores que el ofuscador ha renombrado.
Cuando se establece en true, la función se convierte a bytecode de todos modos y la advertencia VMDynamicCodeSkipped deja de emitirse.
La advertencia independiente DynamicCodeRenameRisk se sigue emitiendo con independencia de esta opción, porque el riesgo de renombrado que describe es independiente de la omisión de la VM: activar esta opción no hace que el patrón subyacente sea más seguro.
// Source code
function loadConfig(src) {
return eval(src);
}
loadConfig('1 + 2');
// Options
{
vmObfuscation: true,
vmForceCompileDynamicCode: true
}
Con la opción desactivada (predeterminado), loadConfig se deja como JavaScript plano. Con la opción activada, loadConfig se compila a bytecode de la VM como cualquier otra función. Úsala cuando hayas auditado el sitio de la llamada y sepas que el código construido en tiempo de ejecución no depende de identificadores renombrados del closure.
vmWrapTopLevelInitializers
Type: boolean Default: false
Envuelve algunos inicializadores de variables de nivel superior en IIFE (expresiones de función invocadas inmediatamente) para que puedan ofuscarse con VM.
Qué hace: Sin esta opción, las constantes y variables de nivel superior permanecen visibles en la salida:
// Input
const MY_STRING = "my-string";
// Output (without vmWrapTopLevelInitializers)
const MY_STRING = "my-string"; // String is visible!
Con esta opción activada, el inicializador se envuelve en una IIFE que se ofusca con VM:
// Input
const MY_STRING = "my-string";
// Output (with vmWrapTopLevelInitializers: true)
const MY_STRING = (() => { return /* VM bytecode call */ })(); // String hidden in bytecode
Nota: Esta opción solo funciona cuando vmTargetFunctionsMode es 'root' (el valor predeterminado).
Advertencias: Siempre que un inicializador de nivel superior acabe en JavaScript plano bajo la ofuscación VM, se informa de una advertencia VMTopLevelInitializerNotVirtualized que lista los nombres de las variables afectadas. Esto abarca: que esta opción esté desactivada, los inicializadores que esta opción tuvo que omitir (cada uno con su motivo, p. ej., el inicializador hace referencia a un declarador hermano o contiene un await de nivel superior) y el modo vmAsyncExecutor, donde los wrappers síncronos no pueden virtualizarse en absoluto.
vmDynamicOpcodes
Type: boolean Default: false
Hace que el intérprete de la VM sea más pequeño y único para cada build.
Qué hace:
- Filtra las instrucciones no usadas - Si tu código no usa clases, las instrucciones relacionadas con clases se eliminan por completo
- Aleatoriza la estructura - El orden de los manejadores de instrucciones se baraja en cada build
Como resultado, una salida más pequeña y cada build tiene un aspecto diferente.
vmBytecodeEncoding
Type: boolean Default: false
Codifica cada instrucción del bytecode. Las instrucciones se decodifican una a una durante la ejecución.
vmBytecodeArrayEncoding
Type: boolean Default: false
Codifica todo el array de bytecode como un único bloque. El array se decodifica una sola vez al inicio, antes de que comience la ejecución. Úsala junto con vmBytecodeEncoding para obtener dos capas de protección.
vmBytecodeArrayEncodingKey
Type: string Default: ''
Clave de cifrado personalizada para la codificación del array de bytecode. Cuando se establece, esta clave se usa en lugar de la clave predeterminada derivada del entorno. La clave debe proporcionarse en tiempo de ejecución mediante vmBytecodeArrayEncodingKeyGetter.
Esta opción externaliza la clave de cifrado: no se incrusta en el propio código ofuscado. Aunque la clave sigue siendo accesible en tiempo de ejecución (y, por tanto, no es realmente secreta), esta separación impide que las herramientas de análisis estático encuentren la clave examinando únicamente el código.
Importante: La clave debe estar disponible de forma síncrona cuando se carga el código ofuscado. Usa almacenamiento síncrono como cookies, localStorage, sessionStorage, variables globales o elementos del DOM (p. ej., meta tags inyectados por el servidor). Los métodos asíncronos como fetch() no pueden usarse directamente en la expresión del getter de clave.
vmBytecodeArrayEncodingKeyGetter
Type: string Default: ''
Expresión de JavaScript síncrona que devuelve la clave de cifrado en tiempo de ejecución. Esta expresión se evalúa cuando se carga el código ofuscado y debe devolver la misma clave que se proporcionó en vmBytecodeArrayEncodingKey. Para resolver la clave de forma asíncrona (una Promise), activa vmAsyncExecutor.
Nota: un getter que devuelve una Promise requiere vmAsyncExecutor. Esto no puede comprobarse en tiempo de compilación, por lo que un getter con Promise y vmAsyncExecutor desactivada falla en tiempo de ejecución: el decodificador recibe la Promise en lugar de la clave.
El código ofuscado solo funcionará cuando el getter de clave devuelva exactamente la misma clave que se usó durante la ofuscación. Si las claves no coinciden, el descifrado fallará y el código producirá datos basura o errores. Si el getter de clave devuelve undefined, null o una cadena vacía, el código lanzará un error: "VM decryption key not available".
Importante: Mantén la clave fuera del mismo archivo/script que el código ofuscado; incluirla ahí en línea permite que incluso un análisis puramente estático del bundle la recupere. Almacénala en cambio en una fuente independiente: cookies establecidas por el servidor, localStorage rellenado por otro script, un meta tag HTML inyectado por el servidor, un global establecido por un script distinto o (con vmAsyncExecutor) obtenida de tu backend en tiempo de ejecución.
Cuando la clave se obtiene de tu backend (mediante vmAsyncExecutor), añade comprobaciones basadas en la sesión o en el origen en ese endpoint: devuelve la clave correcta a los usuarios reales (sesión válida, Origin/Referer esperados) y una clave basura a las solicitudes sospechosas (p. ej., un origen localhost/inesperado, sin sesión). Los usuarios reales se ejecutan con normalidad; una copia que se ejecute fuera de tu entorno obtiene una clave que no descifra nada. La lógica exacta depende de tu sitio.
Ejemplos:
// From cookie
vmBytecodeArrayEncodingKeyGetter: "document.cookie.match(/vmKey=([^;]+)/)?.[1]"
// From localStorage
vmBytecodeArrayEncodingKeyGetter: "localStorage.getItem('vmKey')"
// From global variable
vmBytecodeArrayEncodingKeyGetter: "window.__VM_KEY__"
// From meta tag (server-injected)
vmBytecodeArrayEncodingKeyGetter: "document.querySelector('meta[name=\"vm-key\"]').content"
// From nested object
vmBytecodeArrayEncodingKeyGetter: "window.config.encryption.key"
// From backend, async (requires vmAsyncExecutor)
vmBytecodeArrayEncodingKeyGetter: 'fetch("/vm-key").then((res) => res.text())'
Ejemplo de uso:
// Build time
JavaScriptObfuscator.obfuscate(code, {
vmObfuscation: true,
vmBytecodeArrayEncoding: true,
vmBytecodeArrayEncodingKey: 'mySecretKey123',
vmBytecodeArrayEncodingKeyGetter: 'window.__VM_KEY__'
});
// Runtime - key must be set before obfuscated code runs
window.__VM_KEY__ = 'mySecretKey123';
vmAsyncExecutor
Type: boolean Default: false
Activa el ejecutor asíncrono de la VM, que permite que vmBytecodeArrayEncodingKeyGetter devuelva una Promise (un getter de clave asíncrono), de modo que la clave de descifrado puede obtenerse en tiempo de ejecución (petición de red, IndexedDB, etc.) en lugar de tener que estar disponible de forma síncrona cuando se carga el código.
Muy recomendable para bases de código totalmente asíncronas. En este modo solo se virtualizan las funciones async: una función síncrona no puede convertirse en asíncrona sin transformar su valor de retorno en una Promise y romper a quienes la llaman, por lo que el código que es async de principio a fin obtiene la mayor cobertura. Sigue funcionando cuando la raíz es síncrona (p. ej., una IIFE síncrona / wrapper UMD): las funciones async más externas del interior quedan protegidas y las partes síncronas se dejan tal cual.
Qué se transforma: cada función async más externa, dondequiera que aparezca (incluso anidada dentro de wrappers síncronos). La función asíncrona más externa de cada cadena es la unidad protegida: todo lo que hay dentro de ella, síncrono y asíncrono, se compila. Las funciones síncronas y los generadores normales se dejan sin ofuscar.
function foo() { // sync — left as-is
function bar() {} // sync — left as-is
async function baz() { // transformed
// any code here, including calls to other async or sync functions
}
async function bark() { // transformed
// any code here, including calls to other async or sync functions
}
}
Omisiones y advertencias. Los generadores asíncronos también se dejan sin ofuscar cuando hay un getter de clave asíncrono activo (un generador asíncrono debe devolver su iterador de forma síncrona y no puede esperar a la clave). En el modo predeterminado vmTargetFunctionsMode: 'root', las omisiones son silenciosas (la selección es automática); en el modo comment se emite una advertencia a través de ObfuscationResult.getWarnings() siempre que una función que marcaste explícitamente no pueda virtualizarse: resultó ser síncrona o es un generador asíncrono bajo un getter de clave asíncrono.
El getter de clave asíncrono requiere además vmBytecodeArrayEncoding con un vmBytecodeArrayEncodingKeyGetter.
Ejemplo de uso:
JavaScriptObfuscator.obfuscate(code, {
vmObfuscation: true,
vmAsyncExecutor: true,
vmBytecodeArrayEncoding: true,
vmBytecodeArrayEncodingKey: 'mySecretKey123',
// the key getter may now return a Promise
vmBytecodeArrayEncodingKeyGetter: 'fetch("/vm-key").then((res) => res.text())'
});
vmJumpsEncoding
Type: boolean Default: false
Codifica los destinos de salto en el bytecode. Los desplazamientos de salto se calculan en tiempo de ejecución, lo que oculta la estructura del flujo de control (if/else, bucles, etc.) del análisis estático.
vmMacroOps
Type: boolean Default: false
Combina secuencias de instrucciones comunes en opcodes «macro» únicos. Por ejemplo, LOAD + ADD + STORE podría convertirse en una única instrucción MACRO_ADD_TO_VAR. Esto rompe el reconocimiento de patrones y puede mejorar el rendimiento.
vmDebugProtection
Type: boolean Default: false
Añade defensas multicapa antidepuración, antianálisis y anti-LLM al runtime de la VM. Funciona mejor con los targets browser/browser-no-eval.
vmSelfDefending
Type: boolean Default: false
Añade al runtime de la VM protección multicapa de detección de manipulación, anti-hooking y anti-ingeniería inversa.
⚠️ Esta opción fuerza la activación de vmBytecodeArrayEncoding.
⚠️ Detección de entornos sensibles. Esta opción vincula el código ofuscado a su entorno de ejecución de destino y utiliza fingerprinting avanzado del navegador para detectar herramientas de automatización. El código protegido con esta opción se romperá de forma intencionada cuando se ejecute en:
- Navegadores headless (Chrome/Chromium headless, PhantomJS)
- Herramientas de automatización de navegadores (Puppeteer, Playwright, Cypress, Selenium/ChromeDriver, Nightmare)
- Node.js (cuando
targetestá establecido enbrowser) - jsdom o emulaciones de DOM del lado del servidor similares
- Entornos donde los builtins nativos del navegador han sido interceptados (hooked) o reemplazados
El código funcionará correctamente en navegadores normales (Chrome, Firefox, Safari, Edge), incluso cuando se carga dentro de iframes, extensiones de navegador (content scripts) y Web Workers. Si necesitas ejecutar pruebas automatizadas contra código protegido, desactiva vmSelfDefending en los builds de prueba: esta opción está diseñada para impedir el análisis automatizado y no puede usarse de forma segura con ningún framework de automatización.
Muy recomendable usarla junto con vmDebugProtection, vmBytecodeArrayEncodingKey y vmBytecodeArrayEncodingKeyGetter.
vmDefenseHook
Type: { name: string, aliases?: object } Default: ''
vmDefenseHook toma un objeto con dos claves: name (obligatoria) y aliases (opcional).
name es una función global que define tu página anfitriona y que una defensa de la VM (vmDebugProtection / vmSelfDefending) llama con un objeto de señal cuando detecta una señal hostil: un depurador o inspector, un navegador headless / de automatización, un proceso de agente de codificación con IA, un dominio no permitido, etc. Úsala para informar del evento a tu backend (p. ej., navigator.sendBeacon). El hook es un mero sumidero de telemetría: su valor de retorno se ignora, y un hook ausente o que lanza una excepción es una operación nula silenciosa que nunca puede desactivar una defensa. Para cambiar lo que una defensa hace al detectar algo, usa vmDefenseReaction.
aliases renombra opcionalmente los campos de ese objeto de señal, lo que se explica más abajo en Renombrar los campos de señal.
El objeto de señal. El hook recibe una única signal:
source— el detector concreto que se activó (consulta la tabla).category— el grupo bajo el que informa:automation(navegadores no humanos),debugger(hay un depurador/inspector activo),sandbox(host instrumentado/falso),domain(violación del bloqueo de dominio),tamper(builtins parcheados en tiempo de ejecución) ointegrity(se alteró el propio código de la VM).score/threshold— con qué intensidad se activó el detector y el valor que tenía que alcanzar; el hook se dispara solo cuandoscore >= threshold. La mayoría de las comprobaciones son de todo o nada (una única señal decisiva);headlesssuma varias señales sobre la forma del navegador, por lo que suscoresuele ser mayor que suthreshold.
Registrar el hook. Defínelo como un global normal antes de que se cargue el bundle ofuscado: el runtime de la VM y sus defensas se ejecutan antes que tu programa (protegido), por lo que muchas detecciones se disparan durante el arranque:
// in your page, before the obfuscated script:
window.__vmDetection = function (signal) { navigator.sendBeacon('/vm-defense', JSON.stringify(signal)); };
// obfuscation option:
vmDefenseHook: { name: '__vmDetection' }
Un hook definido dentro del código fuente ofuscado se registra demasiado tarde para captar las detecciones del momento de arranque, y si se compila con la VM no puede alcanzarse hasta que tu programa se ejecute. En cualquier caso se mantiene seguro (un hook ausente no hace nada y una protección contra reentrada evita cualquier desbordamiento), pero para una cobertura completa regístralo por adelantado. Para proteger de todos modos tu lógica de notificación, mantén el hook registrado como un búfer de una sola línea ((window.__vmDet = window.__vmDet || []).push(signal)) y lee/envía ese búfer desde tu código ofuscado.
Renombrar los campos de señal (aliases). Los valores predeterminados source/category son nombres descriptivos, de modo que cualquiera que instrumente el callback (o lea la salida) puede reconocer la protección y qué detector se activó. aliases renombra los campos de señal a tokens opacos de tu elección, aplicados dentro de la VM antes de que se emita la señal, por lo que esos nombres nunca aparecen en la salida ni llegan al callback. Tu aplicación conoce su propio mapeo y reenvía los tokens a tu backend.
Los alias son por campo, manteniendo separados los renombrados de clave y de valor: cada campo toma una key (el nombre de propiedad que recibe el callback); los campos de nombre de tipo cadena source y category también toman un mapa values, mientras que score/threshold son números y solo toman una key. Los nombres que puedes mapear (cualquier otro se rechaza en tiempo de compilación):
- claves de campo —
source,category,score,threshold - valores de
source—headless,agent,node,debugger,timing,sandbox,domain,nativeHook,integrity - valores de
category—automation,debugger,sandbox,domain,tamper,integrity
vmDefenseHook: {
name: '__vmDetection',
aliases: {
source: { key: 'a8Qm', values: { headless: 'xP4m9Q' } },
category: { key: 'p3Tx', values: { automation: 'bQ7s1M' } },
score: { key: 's1' },
threshold: { key: 't1' }
}
// the callback now receives e.g. { a8Qm: 'xP4m9Q', p3Tx: 'bQ7s1M', s1: <score>, t1: <threshold> }
}
Esto es evasión de fingerprint, no secretismo: el mapeo aún puede inferirse mediante pruebas repetidas, por lo que su único beneficio es no exponer nombres estables y autoexplicativos. Las entradas sin definir conservan sus nombres predeterminados.
Una cadena simple (vmDefenseHook: '__vmDetection') se acepta como forma abreviada de { name: '__vmDetection' } pero está obsoleta: prefiere la forma de objeto.
vmDefenseReaction
Type: object Default: { automation: 'break', debugger: 'decoy', sandbox: 'decoy', domain: 'break', tamper: 'break', integrity: 'break' }
Configura cómo reacciona cada categoría de detección. No activa nada: las defensas en sí se activan con vmSelfDefending, vmDebugProtection y vmDomainLock; esta opción solo selecciona cómo reacciona una defensa ya activada. La categoría es la unidad de control: cada detector de una categoría aplica la reacción de esa categoría.
Cada categoría agrupa los detectores que vigilan un tipo de condición hostil. Una categoría solo reacciona cuando la opción que emite sus detectores está activada:
Cada categoría se corresponde con una o varias de vmSelfDefending, vmDebugProtection y vmDomainLock; no existe ninguna categoría fuera de esas tres opciones, y una reacción establecida para una categoría cuya opción está desactivada simplemente no tiene efecto.
Las claves son estos seis nombres de categoría, o default (un valor de reserva para las categorías no especificadas). Los valores son:
break— interrumpe inmediatamentedecoy— sigue ejecutándose con un estado envenenado, produciendo resultados incorrectos de forma silenciosanone— no hace nada localmente (solo telemetría)
Los valores predeterminados por categoría se muestran arriba; una categoría que no establezcas (o que establezcas a su valor predeterminado) usa ese valor predeterminado. default alcanza a todas las categorías, incluidas las que son correctas por construcción (integrity, tamper), de modo que { default: 'none' } es un build genuinamente no disruptivo, solo de telemetría:
vmDefenseReaction: { default: 'none' } // never break — pair with vmDefenseHook
vmDefenseReaction: { automation: 'none', domain: 'break' } // tolerate automation FPs, still break on a bad domain
vmStatefulOpcodes
Type: boolean Default: false
Hace que el significado de los opcodes dependa de su posición en el bytecode. Cada posición tiene un mapeo de opcode a manejador distinto derivado de una semilla, de modo que el mismo número de opcode realiza operaciones diferentes en posiciones diferentes.
vmCallContextOpcodes
Type: boolean Default: false
Hace que una función protegida dependa del lugar desde el que se la llama, de modo que no pueda extraerse del código y ejecutarse o analizarse por sí sola: solo se comporta correctamente cuando se la invoca a través de sus sitios de llamada reales dentro del programa. Esta opción afecta al rendimiento en tiempo de ejecución.
Actualmente solo se admiten las siguientes construcciones:
- declaraciones de función (
function f() {}); - expresiones de función y funciones flecha asignadas a una variable (
const f = () => {}); - métodos privados de instancia (
this.#m()).
En todos los casos, la función debe alcanzarse siempre mediante una llamada directa (f(), this.#m()). Si se almacena en otra variable, se pasa como argumento o se usa de cualquier otra forma como valor, se deja sin proteger. Se admiten las funciones asíncronas; los generadores no.
Esta opción es experimental y puede romper tu código, así que prueba la salida a fondo antes de usarla.
vmStackEncoding
Type: boolean Default: false
Cifra los valores de la pila de la VM durante la ejecución. Los valores se codifican al insertarlos (push) y se decodifican al extraerlos (pop), de modo que la inspección de la memoria muestra datos cifrados en lugar de los valores reales.
Esta opción afecta mucho al rendimiento.
vmCompactDispatcher
Type: boolean Default: false
Usa un único ejecutor de VM en lugar de ejecutores duales (síncrono + generador). Reduce el tamaño del código ofuscado, pero añade una sobrecarga de rendimiento de ~20% en código con mucha recursión.
false(predeterminado): ejecutores duales — rendimiento óptimo, salida más grandetrue: ejecutor único — salida más pequeña, ligeramente más lento
vmStringArrayBytecodeOnly
Type: boolean Default: false
Cuando está activada, el string array solo extraerá cadenas de los datos del bytecode; no se transforma ninguna otra cadena del código. Esto activa de forma forzada stringArray aunque no se haya establecido explícitamente.
Por qué usarla: Extraer todas las cadenas del runtime de la VM a un string array es lento. Esta opción apunta únicamente al contenido del bytecode para la extracción del string array, lo que mejora el rendimiento sin dejar de proteger las constantes del bytecode.
- Cuando
vmBytecodeArrayEncoding: false— se extraen las cadenas de los pools de constantes del bytecode (arraysc) - Cuando
vmBytecodeArrayEncoding: true— se extraen las cadenas de bytecode de nivel superior codificadas en base64 stringArrayThresholdsigue controlando qué porcentaje de esas cadenas de bytecode se extraen
vmDomainLock
Type: string[] Default: []
⚠️ Esta opción no funciona con target: 'node', target: 'service-worker' o target: 'bytenode'
Restringe el código ofuscado a dominios y/o subdominios concretos, y es mucho más difícil de localizar y eliminar que domainLock.
Si el código fuente no se ejecuta en los dominios especificados por esta opción, el navegador será redirigido a la URL pasada a vmDomainLockRedirectUrl, y las llamadas protegidas posteriores devolverán resultados incorrectos incluso si se suprime la redirección.
Varios dominios y subdominios
Es posible bloquear tu código en más de un dominio o subdominio. Por ejemplo, para bloquearlo de modo que el código solo se ejecute en www.example.com añade www.example.com. Para que funcione en el dominio raíz incluyendo cualquier subdominio (example.com, sub.example.com), usa .example.com.
vmDomainLockRedirectUrl
Type: string Default: about:blank
⚠️ Esta opción no funciona con target: 'node', target: 'service-worker' o target: 'bytenode'
Permite redirigir el navegador a una URL indicada si el código fuente no se ejecuta en los dominios especificados por vmDomainLock.
Preset Options
Ofuscación alta, rendimiento bajo
El rendimiento será mucho más lento que sin ofuscación
{
compact: true,
controlFlowFlattening: true,
controlFlowFlatteningThreshold: 1,
deadCodeInjection: true,
deadCodeInjectionThreshold: 1,
debugProtection: true,
debugProtectionInterval: 4000,
disableConsoleOutput: true,
identifierNamesGenerator: 'hexadecimal',
log: false,
numbersToExpressions: true,
renameGlobals: false,
selfDefending: true,
simplify: true,
splitStrings: true,
splitStringsChunkLength: 5,
strictMode: null,
stringArray: true,
stringArrayCallsTransform: true,
stringArrayEncoding: ['rc4'],
stringArrayIndexShift: true,
stringArrayRotate: true,
stringArrayShuffle: true,
stringArrayWrappersCount: 5,
stringArrayWrappersChainedCalls: true,
stringArrayWrappersParametersMaxCount: 5,
stringArrayWrappersType: 'function',
stringArrayThreshold: 1,
transformObjectKeys: true
}
Ofuscación media, rendimiento óptimo
El rendimiento será más lento que sin ofuscación
{
compact: true,
controlFlowFlattening: true,
controlFlowFlatteningThreshold: 0.75,
deadCodeInjection: true,
deadCodeInjectionThreshold: 0.4,
debugProtection: false,
debugProtectionInterval: 0,
disableConsoleOutput: true,
identifierNamesGenerator: 'hexadecimal',
log: false,
numbersToExpressions: true,
renameGlobals: false,
selfDefending: true,
simplify: true,
splitStrings: true,
splitStringsChunkLength: 10,
strictMode: null,
stringArray: true,
stringArrayCallsTransform: true,
stringArrayCallsTransformThreshold: 0.75,
stringArrayEncoding: ['base64'],
stringArrayIndexShift: true,
stringArrayRotate: true,
stringArrayShuffle: true,
stringArrayWrappersCount: 2,
stringArrayWrappersChainedCalls: true,
stringArrayWrappersParametersMaxCount: 4,
stringArrayWrappersType: 'function',
stringArrayThreshold: 0.75,
transformObjectKeys: true
}
Ofuscación baja, rendimiento alto
El rendimiento se mantendrá en un nivel relativamente normal
{
compact: true,
controlFlowFlattening: false,
deadCodeInjection: false,
debugProtection: false,
debugProtectionInterval: 0,
disableConsoleOutput: true,
identifierNamesGenerator: 'hexadecimal',
log: false,
numbersToExpressions: false,
renameGlobals: false,
selfDefending: true,
simplify: true,
splitStrings: false,
strictMode: null,
stringArray: true,
stringArrayCallsTransform: false,
stringArrayEncoding: [],
stringArrayIndexShift: true,
stringArrayRotate: true,
stringArrayShuffle: true,
stringArrayWrappersCount: 1,
stringArrayWrappersChainedCalls: true,
stringArrayWrappersParametersMaxCount: 2,
stringArrayWrappersType: 'variable',
stringArrayThreshold: 0.75
}
Preajuste predeterminado, rendimiento alto
{
compact: true,
controlFlowFlattening: false,
deadCodeInjection: false,
debugProtection: false,
debugProtectionInterval: 0,
disableConsoleOutput: false,
identifierNamesGenerator: 'hexadecimal',
log: false,
numbersToExpressions: false,
renameGlobals: false,
selfDefending: false,
simplify: true,
splitStrings: false,
strictMode: null,
stringArray: true,
stringArrayCallsTransform: false,
stringArrayCallsTransformThreshold: 0.5,
stringArrayEncoding: [],
stringArrayIndexShift: true,
stringArrayRotate: true,
stringArrayShuffle: true,
stringArrayWrappersCount: 1,
stringArrayWrappersChainedCalls: true,
stringArrayWrappersParametersMaxCount: 2,
stringArrayWrappersType: 'variable',
stringArrayThreshold: 0.75
}
Ofuscación VM Ultra High (seguridad máxima)
Este preajuste activa la ofuscación basada en bytecode de VM con todas las funciones de refuerzo, incluido el despacho indirecto. Ofrece la protección más fuerte, pero con un mayor tamaño de salida y una ejecución mucho más lenta.
{
optionsPreset: 'vm-ultra-high-obfuscation'
}
O configúralo individualmente:
{
compact: true,
simplify: true,
identifierNamesGenerator: 'mangled-shuffled',
vmObfuscation: true,
vmForceCompileDynamicCode: false,
vmWrapTopLevelInitializers: true,
vmDynamicOpcodes: true,
vmBytecodeEncoding: true,
vmBytecodeArrayEncoding: true,
vmBytecodeArrayEncodingKey: '',
vmBytecodeArrayEncodingKeyGetter: '',
vmAsyncExecutor: false,
vmJumpsEncoding: true,
vmMacroOps: true,
vmDebugProtection: true,
vmSelfDefending: true,
vmDefenseHook: '',
vmDefenseReaction: {
automation: 'break',
debugger: 'decoy',
sandbox: 'decoy',
domain: 'break',
tamper: 'break',
integrity: 'break'
},
vmStatefulOpcodes: true,
vmCallContextOpcodes: false,
vmStackEncoding: true,
vmCompactDispatcher: true,
controlFlowFlattening: true,
controlFlowFlatteningThreshold: 0.5,
deadCodeInjection: true,
deadCodeInjectionThreshold: 0.5,
debugProtection: true,
debugProtectionInterval: 4000,
disableConsoleOutput: true,
identifierNamesGenerator: 'hexadecimal',
log: false,
numbersToExpressions: true,
renameGlobals: false,
selfDefending: true,
simplify: true,
splitStrings: true,
splitStringsChunkLength: 5,
strictMode: null,
stringArray: true,
stringArrayCallsTransform: true,
stringArrayEncoding: ['rc4'],
stringArrayIndexShift: true,
stringArrayRotate: true,
stringArrayShuffle: true,
stringArrayWrappersCount: 5,
stringArrayWrappersChainedCalls: true,
stringArrayWrappersParametersMaxCount: 5,
stringArrayWrappersType: 'function',
stringArrayThreshold: 0.5,
transformObjectKeys: true
}
VM Anti-LLM (protección contra agentes de IA)
Este preajuste está diseñado específicamente para impedir que los agentes de IA y los LLM apliquen ingeniería inversa al código convertido a bytecode de VM. Se basa en vm-default con la autodefensa y la protección de depuración activadas. Es más ligero que vm-high-obfuscation, pero está reforzado específicamente contra el análisis automatizado.
{
optionsPreset: 'vm-anti-llm'
}
Incluye:
- Ofuscación con bytecode de VM con string array (de
vm-default) vmSelfDefending— detección anti-hook, hash de integridad, fingerprint del código fuente, verificación de realm limpio con iframe, derivación de clave con cifrado ARXvmDebugProtection— comprobaciones antidepuración en el bucle de despacho de la VMdebugProtection: false— sin protección de depuración heredada (la protección de depuración de la VM es superior)
Ofuscación VM High (seguridad más alta)
Este preajuste activa la ofuscación basada en bytecode de VM con la mayoría de las funciones de refuerzo. Ofrece una protección fuerte con mejor rendimiento que el preajuste ultra-high.
{
optionsPreset: 'vm-high-obfuscation'
}
O configúralo individualmente:
{
compact: true,
simplify: true,
identifierNamesGenerator: 'mangled-shuffled',
vmObfuscation: true,
vmForceCompileDynamicCode: false,
vmWrapTopLevelInitializers: true,
vmDynamicOpcodes: true,
vmBytecodeEncoding: true,
vmBytecodeArrayEncoding: true,
vmBytecodeArrayEncodingKey: '',
vmBytecodeArrayEncodingKeyGetter: '',
vmAsyncExecutor: false,
vmJumpsEncoding: true,
vmMacroOps: true,
vmDebugProtection: true,
vmSelfDefending: true,
vmDefenseHook: '',
vmDefenseReaction: {
automation: 'break',
debugger: 'decoy',
sandbox: 'decoy',
domain: 'break',
tamper: 'break',
integrity: 'break'
},
vmStatefulOpcodes: true,
vmCallContextOpcodes: false,
vmStackEncoding: true,
vmCompactDispatcher: false
}
Ofuscación VM Medium (seguridad equilibrada)
Este preajuste activa la ofuscación basada en bytecode de VM con un conjunto equilibrado de funciones de refuerzo. Buen compromiso entre seguridad y rendimiento.
{
optionsPreset: 'vm-medium-obfuscation'
}
O configúralo individualmente:
{
compact: true,
simplify: true,
identifierNamesGenerator: 'mangled-shuffled',
vmObfuscation: true,
vmForceCompileDynamicCode: false,
vmWrapTopLevelInitializers: true,
vmDynamicOpcodes: true,
vmBytecodeEncoding: true,
vmBytecodeArrayEncoding: false,
vmBytecodeArrayEncodingKey: '',
vmBytecodeArrayEncodingKeyGetter: '',
vmAsyncExecutor: false,
vmJumpsEncoding: true,
vmMacroOps: true,
vmDebugProtection: true,
vmSelfDefending: false,
vmDefenseHook: '',
vmDefenseReaction: {
automation: 'break',
debugger: 'decoy',
sandbox: 'decoy',
domain: 'break',
tamper: 'break',
integrity: 'break'
},
vmStatefulOpcodes: false,
vmCallContextOpcodes: false,
vmStackEncoding: false,
vmCompactDispatcher: false
}
Ofuscación VM Low (seguridad básica, mejor rendimiento)
Este preajuste activa una ofuscación básica basada en bytecode de VM sin funciones de refuerzo adicionales. Buen equilibrio entre seguridad y tamaño de salida.
{
optionsPreset: 'vm-low-obfuscation'
}
O configúralo individualmente:
{
compact: true,
simplify: true,
identifierNamesGenerator: 'mangled-shuffled',
vmObfuscation: true,
vmForceCompileDynamicCode: false,
vmWrapTopLevelInitializers: true,
vmDynamicOpcodes: false,
vmBytecodeEncoding: false,
vmBytecodeArrayEncoding: false,
vmBytecodeArrayEncodingKey: '',
vmBytecodeArrayEncodingKeyGetter: '',
vmAsyncExecutor: false,
vmJumpsEncoding: false,
vmMacroOps: false,
vmDebugProtection: false,
vmSelfDefending: false,
vmDefenseHook: '',
vmDefenseReaction: {
automation: 'break',
debugger: 'decoy',
sandbox: 'decoy',
domain: 'break',
tamper: 'break',
integrity: 'break'
},
vmStatefulOpcodes: false,
vmCallContextOpcodes: false,
vmStackEncoding: false,
vmCompactDispatcher: false
}
VM Default (VM + protección con String Array)
Este preajuste combina una ofuscación básica basada en bytecode de VM con la protección de string array. Buen punto de partida para la ofuscación VM con protección de cadenas.
{
optionsPreset: 'vm-default'
}
O configúralo individualmente:
{
compact: true,
simplify: true,
identifierNamesGenerator: 'mangled-shuffled',
vmObfuscation: true,
vmForceCompileDynamicCode: false,
vmWrapTopLevelInitializers: true,
vmDynamicOpcodes: true,
vmBytecodeEncoding: false,
vmBytecodeArrayEncoding: true,
vmStringArrayBytecodeOnly: true,
vmAsyncExecutor: false,
vmJumpsEncoding: false,
vmMacroOps: false,
vmDebugProtection: false,
vmSelfDefending: false,
vmDefenseHook: '',
vmDefenseReaction: {
automation: 'break',
debugger: 'decoy',
sandbox: 'decoy',
domain: 'break',
tamper: 'break',
integrity: 'break'
},
vmStatefulOpcodes: false,
vmCallContextOpcodes: false,
vmStackEncoding: false,
vmCompactDispatcher: false,
stringArray: true,
stringArrayRotate: true,
stringArrayShuffle: true,
stringArrayThreshold: 1,
stringArrayIndexShift: true,
stringArrayIndexesType: ['hexadecimal-number'],
stringArrayCallsTransform: true,
stringArrayCallsTransformThreshold: 1,
stringArrayWrappersCount: 3,
stringArrayWrappersType: 'function',
stringArrayWrappersParametersMaxCount: 5,
stringArrayWrappersChainedCalls: true,
stringArrayEncoding: ['base64'],
splitStrings: true,
splitStringsChunkLength: 6
}
