javascript-obfuscator 5.4.1 → 5.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/CLAUDE.md +9 -2
  3. package/README.md +87 -37
  4. package/dist/index.browser.js +19 -4
  5. package/dist/index.browser.js.map +1 -1
  6. package/dist/index.cli.js +1 -1
  7. package/dist/index.cli.js.map +1 -1
  8. package/dist/index.js +1 -1
  9. package/dist/index.js.map +1 -1
  10. package/package.json +3 -6
  11. package/typings/src/container/InversifyContainerFacade.d.ts +6 -6
  12. package/typings/src/container/modules/analyzers/AnalyzersModule.d.ts +2 -2
  13. package/typings/src/container/modules/code-transformers/CodeTransformersModule.d.ts +2 -2
  14. package/typings/src/container/modules/custom-code-helpers/CustomCodeHelpersModule.d.ts +2 -2
  15. package/typings/src/container/modules/custom-nodes/CustomNodesModule.d.ts +2 -2
  16. package/typings/src/container/modules/generators/GeneratorsModule.d.ts +2 -2
  17. package/typings/src/container/modules/node/NodeModule.d.ts +2 -2
  18. package/typings/src/container/modules/node-transformers/ControlFlowTransformersModule.d.ts +2 -2
  19. package/typings/src/container/modules/node-transformers/ConvertingTransformersModule.d.ts +2 -2
  20. package/typings/src/container/modules/node-transformers/DeadCodeInjectionTransformersModule.d.ts +2 -2
  21. package/typings/src/container/modules/node-transformers/FinalizingTransformersModule.d.ts +2 -2
  22. package/typings/src/container/modules/node-transformers/InitializingTransformersModule.d.ts +2 -2
  23. package/typings/src/container/modules/node-transformers/NodeTransformersModule.d.ts +2 -2
  24. package/typings/src/container/modules/node-transformers/PreparingTransformersModule.d.ts +2 -2
  25. package/typings/src/container/modules/node-transformers/RenameIdentifiersTransformersModule.d.ts +2 -2
  26. package/typings/src/container/modules/node-transformers/RenamePropertiesTransformersModule.d.ts +2 -2
  27. package/typings/src/container/modules/node-transformers/SimplifyingTransformersModule.d.ts +2 -2
  28. package/typings/src/container/modules/node-transformers/StringArrayTransformersModule.d.ts +2 -2
  29. package/typings/src/container/modules/options/OptionsModule.d.ts +2 -2
  30. package/typings/src/container/modules/storages/StoragesModule.d.ts +2 -2
  31. package/typings/src/container/modules/utils/UtilsModule.d.ts +2 -2
  32. package/typings/src/interfaces/container/IInversifyContainerFacade.d.ts +3 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  Change Log
2
2
 
3
+ v5.4.3
4
+ ---
5
+ * Fixed `controlFlowFlattening` occasionally dropping the `?.` short-circuit on `foo?.(arg)` calls, causing `TypeError: <X> is not a function`. Fixes https://github.com/javascript-obfuscator/javascript-obfuscator/issues/1408
6
+
7
+ v5.4.2
8
+ ---
9
+ * Fixed obfuscated code hanging in Bun when `selfDefending` is enabled. Fixes https://github.com/javascript-obfuscator/javascript-obfuscator/issues/1404
10
+
3
11
  v5.4.1
4
12
  ---
5
13
  * Fixed `Utils.nodeRequire` causing `ReferenceError: require is not defined` in browser build by making it lazy-evaluated
package/CLAUDE.md CHANGED
@@ -42,7 +42,7 @@
42
42
  - **Parser**: Acorn 8.8.2 (ES3-ES2020 support)
43
43
  - **Code Generator**: @javascript-obfuscator/escodegen 2.3.0
44
44
  - **AST Traversal**: @javascript-obfuscator/estraverse 5.4.0
45
- - **DI Framework**: InversifyJS 6.0.1
45
+ - **DI Framework**: InversifyJS 7.10.8
46
46
  - **Testing**: Mocha 10.4.0 + Chai 4.3.7
47
47
  - **Build System**: Webpack 5.75.0
48
48
 
@@ -210,7 +210,7 @@ The obfuscation process follows a multi-stage pipeline defined in `JavaScriptObf
210
210
 
211
211
  ### Dependency Injection Architecture
212
212
 
213
- The project uses **InversifyJS** for dependency injection, providing:
213
+ The project uses **InversifyJS v7** for dependency injection, providing:
214
214
 
215
215
  - **Modularity**: Clean separation of concerns
216
216
  - **Testability**: Easy mocking and testing
@@ -219,6 +219,13 @@ The project uses **InversifyJS** for dependency injection, providing:
219
219
 
220
220
  All components are registered in container modules located in `src/container/modules/`.
221
221
 
222
+ **Key Changes in InversifyJS v7:**
223
+ - Container modules now use `ContainerModuleLoadOptions` instead of separate `bind`, `unbind`, etc. parameters
224
+ - `getNamed`, `getTagged`, etc. are replaced by `get(serviceId, { name: ... })` or `get(serviceId, { tag: ... })`
225
+ - `load()` and `unload()` are now async, with `loadSync()` and `unloadSync()` alternatives for synchronous operations
226
+ - Types like `Context`, `Newable`, `Factory` are now directly exported instead of through `interfaces` namespace
227
+ - Custom metadata and middleware features have been removed
228
+
222
229
  ## Key Components Deep Dive
223
230
 
224
231
  ### 1. JavaScriptObfuscator (Main Engine)
package/README.md CHANGED
@@ -4,24 +4,53 @@
4
4
  Author: Timofei Kachalov
5
5
  -->
6
6
 
7
- #### You can support this project by donating:
8
- * (Github) https://github.com/sponsors/sanex3339
9
-
10
- Huge thanks to all supporters!
11
-
12
7
  # JavaScript obfuscator
13
8
 
14
9
  ![logo](https://raw.githubusercontent.com/javascript-obfuscator/javascript-obfuscator/master/images/logo.png)
15
10
 
16
11
  ---
17
12
 
18
- ### :rocket: Obfuscator.io with VM Obfuscation is out!
13
+ ### Do you use JavaScript Obfuscator at your company?
14
+
15
+ JavaScript Obfuscator has reached over **1 million npm downloads per week**. I am currently preparing an **EB-1 immigration case** and collecting independent evidence of the project’s real-world professional usage and impact.
16
+
17
+ If you use JavaScript Obfuscator in a company project — especially at a well-known company, large organization, or widely used product — I would be very grateful if you could contact me.
18
+
19
+ Helpful evidence may include a brief confirmation or, ideally, a 1–2 page reference letter describing:
20
+
21
+ - how your team or company used JavaScript Obfuscator;
22
+ - why you chose it;
23
+ - what problem it helped solve;
24
+ - whether it was used in production or an important internal workflow;
25
+ - your role and how you are familiar with the usage.
26
+
27
+ I can provide a simple draft/template to make this easy.
28
+
29
+ Please contact me at: **referenceletter@obfuscator.io**
30
+
31
+ Thank you for supporting the project.
32
+
33
+ ---
34
+
35
+ ### :rocket: Obfuscator.io with VM Obfuscation
19
36
 
20
- **Obfuscator.io** features **VM-based bytecode obfuscation** the most advanced code protection available. Your JavaScript functions are transformed into custom bytecode running on an embedded virtual machine, making reverse engineering extremely difficult.
37
+ **Obfuscator.io** adds **VM-based bytecode obfuscation** to this package - your JavaScript functions are compiled to custom bytecode that runs on an embedded virtual machine. Each build produces unique opcodes and VM structure, making reverse engineering and automated deobfuscation dramatically harder.
21
38
 
22
- [Try it at obfuscator.io](https://obfuscator.io)
39
+ | Protection goal | Free (this package) | [obfuscator.io](https://obfuscator.io) |
40
+ | --- |-----------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
41
+ | Rename identifiers | ✅ variable/function renaming | ✅ + VM-local symbols never exposed as JavaScript |
42
+ | Obscure strings | ✅ string array + base64/rc4 | ✅ + strings embedded in bytecode constants |
43
+ | Obscure control flow | ✅ control flow flattening | ✅ full bytecode virtualization, [`vmJumpsEncoding`](#vmjumpsencoding) (runtime-computed jump targets), [`vmDeadCodeInjection`](#vmdeadcodeinjection) (fake bytecode sequences) |
44
+ | Resist decompilation | ⚠️ output is still JavaScript | ✅ custom opcodes, [`vmStatefulOpcodes`](#vmstatefulopcodes) (position-dependent opcode mapping), [`vmMacroOps`](#vmmacroops) (fused instructions), [`vmDecoyOpcodes`](#vmdecoyopcodes) (fake opcode handlers) |
45
+ | Resist automated LLM-based analysis | ❌ fully vulnerable (no LLM-specific defenses) | ✅ bytecode encryption + anti-LLM defenses in [`vmSelfDefending`](#vmselfdefending) and [`vmDebugProtection`](#vmdebugProtection) |
46
+ | Encryption | ✅ [`stringArrayEncoding`](#stringarrayencoding) (base64/rc4 on extracted strings) | ✅ [`vmBytecodeEncoding`](#vmbytecodeencoding) (per-instruction encoding), [`vmBytecodeArrayEncoding`](#vmbytecodeArrayEncoding) (whole bytecode array as single block) |
47
+ | Anti-debugging | ✅ `debugProtection` (freezes browser DevTools) | ✅ [`vmDebugProtection`](#vmdebugProtection) (multi-layered anti-debugging and anti-analysis defenses) |
48
+ | Tamper detection | ✅ `selfDefending` (breaks if beautified) | ✅ [`vmSelfDefending`](#vmselfdefending) (multi-layered tamper detection, anti-hooking, anti-reverse-engineering protection) |
49
+ | Runs offline, no network | ✅ | ❌ uses obfuscator.io API (requires token) |
23
50
 
24
- This package provides access to Obfuscator.io Pro API via CLI and Node.js API.
51
+ [Visit Obfuscator.io](https://obfuscator.io) · [Pro API methods](#shield-pro-api-methods-vm-obfuscation)
52
+
53
+ This package provides access to Obfuscator.io API via CLI and Node.js API.
25
54
 
26
55
  ---
27
56
 
@@ -51,6 +80,7 @@ The example of obfuscated code: [github.com](https://github.com/javascript-obfus
51
80
  * Malta: [malta-js-obfuscator](https://github.com/fedeghe/malta-js-obfuscator)
52
81
  * Netlify plugin: [netlify-plugin-js-obfuscator](https://www.npmjs.com/package/netlify-plugin-js-obfuscator)
53
82
  * Snowpack plugin: [snowpack-javascript-obfuscator](https://www.npmjs.com/package/snowpack-javascript-obfuscator)
83
+ * Vite plugin: [vite-plugin-bundle-obfuscator](https://github.com/z0ffy/vite-plugin-bundle-obfuscator)
54
84
 
55
85
  [![npm version](https://badge.fury.io/js/javascript-obfuscator.svg)](https://badge.fury.io/js/javascript-obfuscator)
56
86
  [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fjavascript-obfuscator%2Fjavascript-obfuscator.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fjavascript-obfuscator%2Fjavascript-obfuscator?ref=badge_shield)
@@ -513,6 +543,8 @@ When using CLI this prefix will be added automatically.
513
543
 
514
544
  ## JavaScript Obfuscator Options
515
545
 
546
+ > :shield: **Looking for VM obfuscation?** Options like `vmObfuscation`, `parseHtml`, and every `vm*` option are Pro-only and require an API token from [obfuscator.io](https://obfuscator.io). Use them via the [`obfuscatePro()`](#shield-pro-api-methods-vm-obfuscation) method, or the `--pro-api-token` CLI flag — see [Pro API Methods](#shield-pro-api-methods-vm-obfuscation).
547
+
516
548
  Following options are available for the JS Obfuscator:
517
549
 
518
550
  #### options:
@@ -1870,8 +1902,8 @@ Specify exactly which root-level functions should get VM protection by name.
1870
1902
  **Example:**
1871
1903
  ```javascript
1872
1904
  {
1873
- vmObfuscation: true,
1874
- vmTargetFunctions: ['someFunctionName']
1905
+ vmObfuscation: true,
1906
+ vmTargetFunctions: ['someFunctionName']
1875
1907
  }
1876
1908
  ```
1877
1909
 
@@ -1885,8 +1917,8 @@ Specify root-level functions that should never get VM protection. Takes preceden
1885
1917
  **Example:**
1886
1918
  ```javascript
1887
1919
  {
1888
- vmObfuscation: true,
1889
- vmExcludeFunctions: ['someFunctionName']
1920
+ vmObfuscation: true,
1921
+ vmExcludeFunctions: ['someFunctionName']
1890
1922
  }
1891
1923
  ```
1892
1924
 
@@ -1906,28 +1938,28 @@ Controls how functions/methods are selected for VM obfuscation.
1906
1938
  ```javascript
1907
1939
  // Source code
1908
1940
  function regularFunction() {
1909
- return 'not virtualized';
1941
+ return 'not virtualized';
1910
1942
  }
1911
1943
 
1912
1944
  /* javascript-obfuscator:vm */
1913
1945
  function sensitiveFunction() {
1914
- return 'this will be VM-protected';
1946
+ return 'this will be VM-protected';
1915
1947
  }
1916
1948
 
1917
1949
  function outer() {
1918
- /* javascript-obfuscator:vm */
1919
- function nestedSensitive() {
1920
- return 'nested but still VM-protected';
1921
- }
1922
- return nestedSensitive();
1950
+ /* javascript-obfuscator:vm */
1951
+ function nestedSensitive() {
1952
+ return 'nested but still VM-protected';
1953
+ }
1954
+ return nestedSensitive();
1923
1955
  }
1924
1956
  ```
1925
1957
 
1926
1958
  ```javascript
1927
1959
  // Obfuscator options
1928
1960
  {
1929
- vmObfuscation: true,
1930
- vmTargetFunctionsMode: 'comment'
1961
+ vmObfuscation: true,
1962
+ vmTargetFunctionsMode: 'comment'
1931
1963
  }
1932
1964
  ```
1933
1965
 
@@ -2020,10 +2052,10 @@ vmBytecodeArrayEncodingKeyGetter: "window.config.encryption.key"
2020
2052
  ```ts
2021
2053
  // Build time
2022
2054
  JavaScriptObfuscator.obfuscate(code, {
2023
- vmObfuscation: true,
2024
- vmBytecodeArrayEncoding: true,
2025
- vmBytecodeArrayEncodingKey: 'mySecretKey123',
2026
- vmBytecodeArrayEncodingKeyGetter: 'window.__VM_KEY__'
2055
+ vmObfuscation: true,
2056
+ vmBytecodeArrayEncoding: true,
2057
+ vmBytecodeArrayEncodingKey: 'mySecretKey123',
2058
+ vmBytecodeArrayEncodingKeyGetter: 'window.__VM_KEY__'
2027
2059
  });
2028
2060
 
2029
2061
  // Runtime - key must be set before obfuscated code runs
@@ -2045,26 +2077,24 @@ Type: `boolean` Default: `false`
2045
2077
 
2046
2078
  Injects fake bytecode sequences that are never executed. These look like real instructions but are skipped during runtime, confusing analysis tools that process them.
2047
2079
 
2048
- ### `vmCompactDispatcher`
2080
+ ### `vmMacroOps`
2049
2081
  Type: `boolean` Default: `false`
2050
2082
 
2051
- Uses a single unified dispatcher (generator-based) for both sync and async/generator code execution. By default (`false`), the VM generates two separate dispatchers: a non-generator version for sync code (faster) and a generator version for async/generator code. When enabled, only the generator-based dispatcher is used for all execution.
2083
+ Combines common instruction sequences into single "macro" opcodes. For example, `LOAD + ADD + STORE` might become a single `MACRO_ADD_TO_VAR` instruction. This breaks pattern recognition and can improve performance.
2052
2084
 
2053
- **Trade-offs:**
2054
- - `false` (default): Larger code size due to dual dispatchers, but faster sync execution (no generator overhead)
2055
- - `true`: Smaller code size with single dispatcher, but sync code has generator protocol overhead
2085
+ ### `vmDebugProtection`
2086
+ Type: `boolean` Default: `false`
2056
2087
 
2057
- Use this when code size is more important than sync execution speed.
2088
+ Adds multi-layered anti-debugging, anti-analysis, and anti-LLM defenses to the VM runtime. For best results, allow `unsafe-eval` in your Content Security Policy. Works best with `browser`/`browser-no-eval` targets.
2058
2089
 
2059
- ### `vmMacroOps`
2090
+ ### `vmSelfDefending`
2060
2091
  Type: `boolean` Default: `false`
2061
2092
 
2062
- Combines common instruction sequences into single "macro" opcodes. For example, `LOAD + ADD + STORE` might become a single `MACRO_ADD_TO_VAR` instruction. This breaks pattern recognition and can improve performance.
2093
+ Adds multi-layered tamper detection, anti-hooking, and anti-reverse-engineering protection to the VM runtime.
2063
2094
 
2064
- ### `vmDebugProtection`
2065
- Type: `boolean` Default: `false`
2095
+ > :warning: This option force-enables [`vmBytecodeArrayEncoding`](#vmbytecodeArrayEncoding).
2066
2096
 
2067
- Adds anti-debugging measures to the VM runtime. Detects debugger presence and alters behavior when debugging is detected.
2097
+ Strongly recommended to use together with [`vmDebugProtection`](#vmDebugProtection), [`vmBytecodeArrayEncodingKey`](#vmbytecodeArrayEncodingKey), and [`vmBytecodeArrayEncodingKeyGetter`](#vmbytecodeArrayEncodingKeyGetter).
2068
2098
 
2069
2099
  ### `vmStatefulOpcodes`
2070
2100
  Type: `boolean` Default: `false`
@@ -2078,6 +2108,26 @@ Encrypts values on the VM stack during execution. Values are encoded when pushed
2078
2108
 
2079
2109
  This option heavily affects performance.
2080
2110
 
2111
+ ### `vmCompactDispatcher`
2112
+ Type: `boolean` Default: `false`
2113
+
2114
+ Uses a single VM executor instead of dual executors (sync + generator). Reduces obfuscated code size but adds ~20% performance overhead on recursion-heavy code.
2115
+
2116
+ - `false` (default): dual executors — optimal performance, larger output
2117
+ - `true`: single executor — smaller output, slightly slower
2118
+
2119
+ ### `vmStringArrayBytecodeOnly`
2120
+ Type: `boolean` Default: `false`
2121
+
2122
+ When enabled, the string array will **only** extract strings from bytecode data — no other strings in the code are transformed. This force-enables `stringArray` even if it's not explicitly set.
2123
+
2124
+ **Why use this:** Extracting all VM runtime strings to a string array is slow. This option targets only bytecode content for string array extraction, improving performance while still protecting bytecode constants.
2125
+
2126
+ - When `vmBytecodeArrayEncoding: false` — strings inside bytecode constant pools (`c` arrays) are extracted
2127
+ - When `vmBytecodeArrayEncoding: true` — top-level base64 encoded bytecode strings are extracted
2128
+ - `stringArrayThreshold` still controls what percentage of those bytecode strings are extracted
2129
+
2130
+
2081
2131
  ### `strictMode`
2082
2132
  Type: `boolean | null` Default: `null`
2083
2133