Documentación
/
Recetas
/

Telemetría y reacciones de las defensas VM

Telemetría y reacciones de defensa de la VM

Pro
v7.1.0+

Reporta las detecciones de defensa de la VM a tu backend con vmDefenseHook, y ajusta cómo reacciona cada categoría de detección con vmDefenseReaction, desde un build totalmente no disruptivo de solo telemetría hasta uno que rompa por completo ante un bundle robado.

El problema

Las defensas de la VM —vmSelfDefending, vmDebugProtection y vmDomainLock— actúan localmente: cuando se detecta un depurador, una herramienta de automatización, un entorno manipulado o un dominio no autorizado, el código protegido se rompe o envenena silenciosamente sus propios resultados. Eso detiene al atacante, pero por defecto nunca te enteras. No puedes saber con qué frecuencia se está sondeando tu bundle, qué detector se disparó, ni si una defensa está rompiendo el uso de un usuario legítimo.

Desde la v7.1.0, dos opciones cierran esa brecha. Ninguna de ellas activa ninguna defensa: solo observan y dirigen las defensas que ya has activado:

  • vmDefenseHook - un callback global que recibe un objeto de señal cada vez que una defensa detecta algo. Úsalo para enviar telemetría a tu backend.
  • vmDefenseReaction - un mapa por categoría que selecciona cómo reacciona una defensa activada: romper, envenenar o no hacer nada localmente.

Receta 1 - reportar detecciones a tu backend

Paso 1 - registra una función hook global, 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. Define el hook como una global normal en la página host, por delante de la etiqueta de script ofuscado:

<script>
    // In your page, BEFORE the obfuscated script:
    window.__vmDetection = function (signal) {
        navigator.sendBeacon('/api/vm-defense', JSON.stringify(signal));
    };
</script>
<script src="/app.obfuscated.js"></script>

Paso 2 - apunta vmDefenseHook hacia él

La opción es un objeto cuyo name es la función global a llamar (aliases es opcional; ver más abajo):

JavaScriptObfuscator.obfuscate(source, {
    vmObfuscation: true,
    // the hook alone enables nothing - a defense must be on for detectors to run:
    vmSelfDefending: true,
    vmDebugProtection: true,
    vmDefenseHook: { name: '__vmDetection' }
});

La forma de cadena simple (vmDefenseHook: '__vmDetection') sigue aceptándose como abreviatura de { name: '__vmDetection' }, pero está obsoleta: prefiere la forma de objeto.

En el panel, el campo VM Defense Hook aparece en el panel de opciones de VM una vez que al menos una defensa (vmSelfDefending, vmDebugProtection o vmDomainLock) está activada.

Paso 3 - recibe la señal en tu backend

Cada detección llama al hook con un único objeto signal:

  • source - el detector concreto: headless, node, agent, domain, debugger, sandbox, nativeHook, timing o integrity. A partir de la v7.4.0, los antiguos detectores env e inspector reportan bajo source: 'debugger'.
  • category - automation, debugger, sandbox, domain, tamper o integrity. La fuente node reporta bajo category: 'debugger' (v7.4.0+).
  • score, threshold - la puntuación de detección y el umbral que superó

Un endpoint de recepción mínimo (se muestra con Express; funciona cualquier backend que acepte un POST). Normaliza el cuerpo a un array para que también maneje la forma por lotes que envía el patrón de búfer de más abajo:

app.post('/api/vm-defense', express.text({ type: '*/*' }), (req, res) => {
    // a signal: { source: 'headless', category: 'automation', score: 7, threshold: 4 }
    const signals = [].concat(JSON.parse(req.body));
    for (const signal of signals) {
        console.warn('vm-defense', { ...signal, ip: req.ip, ua: req.get('user-agent') });
    }
    res.sendStatus(204);
});

Renombrar los campos de la señal (aliases) v7.4.0+

Los valores source / category por defecto son nombres descriptivos, así que cualquiera que instrumente el callback (o lea la salida) puede reconocer la protección y qué detector se disparó. aliases renombra los campos de la señal a tokens opacos de tu elección, aplicados dentro de la VM antes de que se emita la señal, de modo 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 aliases son por campo: cada uno toma una key (el nombre de propiedad que recibe el callback); los campos de nombre de cadena source y category también toman un mapa values, mientras que score / threshold son números y solo toman una key. Las entradas sin establecer conservan sus nombres por defecto.

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> }
}

En el panel, la sección Signal aliases se sitúa bajo el campo VM Defense Hook.

Receta 2 - ajustar las reacciones por defecto

vmDefenseReaction configura cómo reacciona cada categoría de detección. No activa nada: las defensas en sí las activan vmSelfDefending, vmDebugProtection y vmDomainLock; esta opción solo selecciona cómo reacciona una defensa activada. La categoría es la unidad de control: cada detector de una categoría aplica la reacción de esa categoría, y una reacción establecida para una categoría cuya opción está desactivada simplemente no tiene efecto.

CategoríaActivada porReacciona cuando
automationvmSelfDefending o vmDebugProtectionEl código está siendo controlado por software en lugar de por una persona: un navegador headless o automatizado, un framework de scraping / testing, o un agente de codificación con IA recorriendo la página.
debuggervmDebugProtection o vmSelfDefendingAlguien tiene abierto un depurador o el inspector de las herramientas de desarrollo del navegador y está recorriendo el código en ejecución para entenderlo.
sandboxvmDebugProtectionEl código no se está ejecutando en un navegador real en absoluto: se ha trasladado a un entorno JavaScript emulado o programado para ejecutarse y estudiarse sin conexión.
domainvmDomainLockEl código se está ejecutando en un sitio que no autorizaste: un host que no está en la lista de permitidos de tu vmDomainLock (por ejemplo, tu bundle copiado en el dominio de otra persona).
tampervmSelfDefendingEl entorno JavaScript que rodea a la VM ha sido modificado para vigilarla o secuestrarla, por ejemplo, builtins nativos del navegador reemplazados por versiones instrumentadas.
integrityvmSelfDefendingEl propio código del bundle protegido ha sido editado o parcheado desde que lo generaste.

Las claves son estos seis nombres de categoría, o default (un recurso de reserva para las categorías no especificadas). Los valores son:

  • break - romper de inmediato
  • decoy - seguir ejecutándose con un estado envenenado, produciendo silenciosamente resultados incorrectos
  • none - no hacer nada localmente (solo telemetría)

Una categoría que no establezcas recurre a los valores por defecto integrados:

// built-in defaults
vmDefenseReaction: {
    automation: 'break',
    debugger: 'decoy',
    sandbox: 'decoy',
    domain: 'break',
    tamper: 'break',
    integrity: 'break'
}

default alcanza a todas las categorías, incluidas las correctas por construcción (integrity, tamper), así que { default: 'none' } es un build genuinamente no disruptivo, de solo telemetría:

vmDefenseReaction: { default: 'none' } // never break - pair with vmDefenseHook
vmDefenseReaction: { automation: 'none' } // tolerate automation FPs; the rest keep their defaults (a bad domain still breaks)

En el panel, los selectores VM Defense Reactions aparecen en el panel de opciones de VM una vez que hay una defensa activada; cada categoría solo es editable mientras esté activa una defensa que emita sus detectores.

De la telemetría a la aplicación

No tienes que elegir entre visibilidad y aplicación desde el primer día. Despliega las defensas en dos builds: uno que solo reporta y, luego —una vez que la telemetría se ve limpia—, uno que reacciona.

Paso 1 - publica un build de solo observación

Activa todas las defensas que pienses usar, apunta vmDefenseHook a tu endpoint y desactiva todas las reacciones. Cada detector sigue ejecutándose y reportando cada acierto a tu backend; simplemente nunca rompe nada:

JavaScriptObfuscator.obfuscate(source, {
    vmObfuscation: true,
    vmSelfDefending: true,
    vmDebugProtection: true,
    vmDomainLock: ['example.com'],
    vmDefenseHook: '__vmDetection',
    vmDefenseReaction: { default: 'none' } // observe only
});

Paso 2 - revisa las señales recopiladas

Una vez que el build haya visto tráfico real, busca detecciones que haya disparado el uso legítimo. Las dos más habituales:

  • Aciertos de automation de tus propias pruebas end-to-end o de la monitorización de disponibilidad (uptime): construye esos artefactos sin las defensas en lugar de tolerar la categoría en producción.
  • Aciertos de domain de un host de staging o preview que olvidaste incluir en la lista de permitidos de vmDomainLock: añade el host.

Prefiere corregir la causa antes que suavizar una reacción: cada categoría dejada en none es un detector del que un atacante ya no tiene que preocuparse.

Paso 3 - activa las reacciones

Elimina el override default: 'none' para que se apliquen las reacciones por categoría integradas: todo el cambio es esa única línea. Si una categoría seguía produciendo falsos positivos que no puedes eliminar, mantén solo esa categoría en none (por ejemplo, vmDefenseReaction: { automation: 'none' }) y aplica el resto.