VM Obfuscation

What is VM Obfuscation?

Highest Security

VM obfuscation is the most advanced form of code protection. It transforms your JavaScript functions into custom bytecode that runs on a virtual machine embedded in the output. The original logic is completely hidden — no JavaScript to reverse-engineer.

Targeting Specific Functions

Recommended

For optimal performance, VM-obfuscate only your most sensitive code using vmTargetFunctionsMode.

Strict Mode Compatibility

Important

VM obfuscation needs to know at compile time whether code runs in strict mode. If your code relies on strict mode behavior, you must explicitly declare it.

Identifier Preprocessing

Recommended

The vmPreprocessIdentifiers option (enabled by default) renames all non-global identifiers to unique hexadecimal names before VM obfuscation. This step eliminates variable shadowing that can cause scope resolution issues in the VM bytecode.

Debug Protection

Pro

The vmDebugProtection option adds anti-debugging measures to the VM runtime, making it significantly harder to reverse-engineer your protected code.

More anti-debugging techniques will be added in future releases.

VM Options Reference

Using the NPM Package

Pro

You can use VM obfuscation in your build pipeline via the javascript-obfuscator npm package. The obfuscatePro() method connects to the obfuscator.io cloud service for VM-based bytecode obfuscation.

Installation

npm install --save-dev javascript-obfuscator

Usage

const JavaScriptObfuscator = require('javascript-obfuscator');

const sourceCode = `
function calculatePrice(qty, price) {
    const discount = 0.15;
    return qty * price * (1 - discount);
}
`;

const result = await JavaScriptObfuscator.obfuscatePro(
    sourceCode,
    {
        vmObfuscation: true,
        vmObfuscationThreshold: 1,
        compact: true
    },
    {
        apiToken: process.env.OBFUSCATOR_API_TOKEN
    }
);

console.log(result.getObfuscatedCode());

How VM Transforms Code

With vmTargetFunctionsMode: 'root' (default), VM obfuscation transforms the body of each root-level function into bytecode (depending on vmObfuscationThreshold), but keeps the function name unchanged.

// Input
function fibonacci(n) {
    if (n <= 1) return n;
    return fibonacci(n - 1) + fibonacci(n - 2);
}

// Output - function NAME is preserved, BODY is VM-transformed
function fibonacci(b) {  // name kept as-is
    return vm.call(...); // body converted to bytecode
}

This design maintains compatibility with code that calls these functions from the global scope or expects them on the global object. The function body is fully protected, but the name remains visible.

Hiding sensitive function names:

If a function name reveals what the code does (e.g., validateLicense, decryptData), use one of these approaches:

  • Option 1: Wrap in an IIFE (Recommended)

    Place sensitive functions inside an IIFE or any other function body. Functions inside other functions are not root-level, so they get fully VM-transformed including their names.

    // Wrap sensitive code in IIFE
    (function() {
        function fibonacci(n) {
            if (n <= 1) return n;
            return fibonacci(n - 1) + fibonacci(n - 2);
        }
        // Use fibonacci here...
    })();
    // "fibonacci" name is completely hidden in output
  • Option 2: Rename globals + encoding (Use with caution)

    Enable renameGlobals: true, vmPreprocessIdentifiers: true, vmBytecodeEncoding: true, and vmBytecodeArrayEncoding: true. This renames root-level identifiers and encrypts them in the bytecode.

Troubleshooting VM Obfuscation Issues

VM obfuscation completely transforms your code into custom bytecode. Ideally, this transformation should handle all possible code patterns and edge cases seamlessly. However, due to the complexity of VM obfuscation, there are still edge cases that may not be fully supported. This means that VM-obfuscated code must be carefully tested in at least all happy-path scenarios before deployment.

If your code doesn't work after VM obfuscation:

  • 1. Ensure identifier preprocessing is enabled

    Check that vmPreprocessIdentifiers is enabled (default: true). This option eliminates variable shadowing issues that can cause scope resolution errors in VM bytecode. If it's disabled, try enabling it first.

  • 2. Narrow down the problematic code

    Use vmTargetFunctionsMode: 'comment' to selectively VM-obfuscate specific functions. Add the /* javascript-obfuscator:vm */ comment only to individual functions and test incrementally to identify which function causes the issue.

  • 3. Contact support with details

    Email support@obfuscator.io with as much information as possible:

    • Error message and stack trace
    • Environment (browser/Node.js version)
    • Obfuscator options/preset used
    • Obfuscator version (shown in the bottom-right corner of the editor)
    • Minimal code sample that reproduces the issue (ideally the narrowed-down problematic function)
VM Obfuscation | Obfuscator.io Documentation