
Offusca il codice JavaScript e Node.js con rinomina delle variabili, crittografia delle stringhe, appiattimento del flusso di controllo e anti-debugging per proteggere il codice sorgente dal reverse engineering.

Obfuscator.io aggiunge l'offuscamento del bytecode basato su VM a questo pacchetto: le tue funzioni JavaScript vengono compilate in un bytecode personalizzato che viene eseguito su una macchina virtuale incorporata. Ogni build produce opcode e strutture VM unici, rendendo il reverse engineering e la deoffuscazione automatizzata notevolmente più difficili.
| Obiettivo di protezione | Gratuito (questo pacchetto) | obfuscator.io |
|---|
| Rinomina identificatori | ✅ rinomina variabili/funzioni | ✅ + simboli locali alla VM mai esposti come JavaScript |
| Offusca stringhe | ✅ array di stringhe + base64/rc4 | ✅ + stringhe incorporate nelle costanti del bytecode |
| Offusca il flusso di controllo | ✅ appiattimento del flusso di controllo | ✅ virtualizzazione completa del bytecode, vmJumpsEncoding (destinazioni di salto calcolate a runtime), vmDeadCodeInjection (sequenze di bytecode finte) |
| Resiste alla decompilazione | ⚠️ l'output è comunque JavaScript | ✅ opcode personalizzati, vmStatefulOpcodes (mappatura degli opcode dipendente dalla posizione), vmMacroOps (istruzioni fuse), vmDecoyOpcodes (gestori di opcode finti) |
| Resiste all'analisi automatizzata basata su LLM | ❌ completamente vulnerabile (nessuna difesa specifica per LLM) | ✅ crittografia del bytecode + difese anti-LLM in vmSelfDefending e vmDebugProtection |
| Crittografia | ✅ stringArrayEncoding (base64/rc4 sulle stringhe estratte) | ✅ vmBytecodeEncoding (codifica per istruzione), vmBytecodeArrayEncoding (intero array di bytecode come blocco singolo) |
| Anti-debugging | ✅ debugProtection (blocca gli strumenti di sviluppo del browser) | ✅ vmDebugProtection (difese anti-debugging e anti-analisi a più livelli) |
| Rilevamento manomissioni | ✅ selfDefending (si rompe se abbellito) | ✅ vmSelfDefending (rilevamento manomissioni a più livelli, protezione anti-hooking e anti-reverse engineering) |
| Funziona offline, senza rete | ✅ | ❌ usa l'API di obfuscator.io (richiede token) |
Questo pacchetto fornisce accesso all'API di Obfuscator.io tramite CLI e API Node.js.
JavaScript Obfuscator ha superato 1 milione di download npm a settimana. Attualmente sto preparando un caso di immigrazione EB-1 e sto raccogliendo prove indipendenti dell'uso professionale reale e dell'impatto del progetto.
Se usi JavaScript Obfuscator in un progetto aziendale — soprattutto in un'azienda nota, una grande organizzazione o un prodotto ampiamente utilizzato — ti sarei molto grato se potessi contattarmi.
Le prove utili possono includere una breve conferma o, idealmente, una lettera di referenza di 1–2 pagine che descriva:
Posso fornire una bozza/modello semplice per rendere tutto più facile.
Contattami a: [email protected]
Grazie per il supporto al progetto.
JavaScript Obfuscator è un potente offuscatore gratuito per JavaScript, con una varietà di funzionalità che forniscono protezione per il tuo codice sorgente.
Caratteristiche principali:
Esempio di codice offuscato: github.com
Non è consigliato offuscare script di vendor e polyfill, poiché il codice offuscato è più lento del 15-80% (dipende dalle opzioni) e i file sono significativamente più grandi.
Installa il pacchetto con Yarn o NPM e aggiungilo alle tue dependencies o devDependencies:```sh
$ yarn add --dev javascript-obfuscator
o```sh
$ npm install --save-dev javascript-obfuscator
Da CDN:```html
Da `node_modules`:```html
<script src="./node_modules/javascript-obfuscator/dist/index.browser.js"></script>
var JavaScriptObfuscator = require('javascript-obfuscator');
var obfuscationResult = JavaScriptObfuscator.obfuscate(
(function(){ var variable1 = '5' - 3; var variable2 = '5' + 3; var variable3 = '5' + - '2'; var variable4 = ['10','10','10','10','10'].map(parseInt); var variable5 = 'foo ' + 1 + 1; console.log(variable1); console.log(variable2); console.log(variable3); console.log(variable4); console.log(variable5); })(); ,
{
compact: false,
controlFlowFlattening: true,
controlFlowFlatteningThreshold: 1,
numbersToExpressions: true,
simplify: true,
stringArrayShuffle: true,
splitStrings: true,
stringArrayThreshold: 1
}
);
console.log(obfuscationResult.getObfuscatedCode()); /* var _0x9947 = [ 'map', 'log', 'foo\x20', 'bvmqO', '133039ViRMWR', 'xPfLC', 'ytpdx', '1243717qSZCyh', '2|7|4|6|9|', '1ErtbCr', '1608314VKvthn', '1ZRaFKN', 'XBoAA', '423266kQOYHV', '3|0|5|8|1', '235064xPNdKe', '13RUDZfG', '157gNPQGm', '1639212MvnHZL', 'rDjOa', 'iBHph', '9926iRHoRl', 'split' ]; function _0x33e4(_0x1809b5, _0x37ef6e) { return _0x33e4 = function (_0x338a69, _0x39ad79) { _0x338a69 = _0x338a69 - (0x1939 + -0xf * 0x1f3 + 0x1 * 0x469); var _0x2b223a = _0x9947[_0x338a69]; return _0x2b223a; }, _0x33e4(_0x1809b5, _0x37ef6e); } (function (_0x431d87, _0x156c7f) { var _0x10cf6e = _0x33e4; while (!![]) { try { var _0x330ad1 = -parseInt(_0x10cf6e(0x6c)) * -parseInt(_0x10cf6e(0x6d)) + -parseInt(_0x10cf6e(0x74)) * -parseInt(_0x10cf6e(0x78)) + parseInt(_0x10cf6e(0x6a)) + -parseInt(_0x10cf6e(0x70)) + parseInt(_0x10cf6e(0x6e)) * -parseInt(_0x10cf6e(0x75)) + parseInt(_0x10cf6e(0x72)) + -parseInt(_0x10cf6e(0x67)) * parseInt(_0x10cf6e(0x73)); if (_0x330ad1 === _0x156c7f) break; else _0x431d87'push'); } catch (_0x9f878) { _0x431d87'push'); } } }(_0x9947, -0xb6270 + 0x4dfd2 * 0x2 + 0x75460 * 0x2), function () { var _0x1f346d = _0x33e4, _0x860db8 = { 'ytpdx': _0x1f346d(0x6b) + _0x1f346d(0x71), 'bvmqO': function (_0x560787, _0x519b9e) { return _0x560787 - _0x519b9e; }, 'rDjOa': function (_0x4501fe, _0x2b07a3) { return _0x4501fe + _0x2b07a3; }, 'xPfLC': function (_0x5f3c9b, _0x434936) { return _0x5f3c9b + _0x434936; }, 'XBoAA': function (_0x535b8a, _0x42eef4) { return _0x535b8a + _0x42eef4; }, 'iBHph': _0x1f346d(0x65) }, _0x346c55 = _0x860db8[_0x1f346d(0x69)]_0x1f346d(0x79), _0x3bf817 = 0x4bb * 0x1 + 0x801 + -0xcbc; while (!![]) { switch (_0x346c55[_0x3bf817++]) { case '0': console_0x1f346d(0x7b); continue; case '1': console_0x1f346d(0x7b); continue; case '2': var _0x65977d = _0x860db8[_0x1f346d(0x66)]('5', -0x586 + -0x2195 + -0x6 * -0x685); continue; case '3': console_0x1f346d(0x7b); continue; case '4': var _0x56d39b = _0x860db8[_0x1f346d(0x76)]('5', -'2'); continue; case '5': console_0x1f346d(0x7b); continue; case '6': var _0x544285 = [ '10', '10', '10', '10', '10' ]_0x1f346d(0x7a); continue; case '7': var _0x4c96d8 = _0x860db8[_0x1f346d(0x68)]('5', 0x622 * -0x6 + 0x4a * 0x3 + 0x1 * 0x23f1); continue; case '8': console_0x1f346d(0x7b); continue; case '9': var _0x101028 = _0x860db8_0x1f346d(0x6f)](_0x860db8[_0x1f346d(0x77)], 0x6fb * 0x5 + 0x1ebf * 0x1 + -0x41a5), 0x209 * 0xa + 0x1314 + -0x276d); continue; } break; } }()); */
### `obfuscate(sourceCode, options)`
Restituisce un oggetto `ObfuscationResult` che contiene due metodi pubblici:
* `getObfuscatedCode()` - restituisce una `string` con il codice offuscato;
* `getSourceMap()` - se l'opzione [`sourceMap`](#sourcemap) è abilitata - restituisce una `string` con la source map o una stringa vuota se l'opzione [`sourceMapMode`](#sourcemapmode) è impostata su `inline`;
* `getIdentifierNamesCache()` - restituisce un oggetto con la cache dei nomi degli identificatori se l'opzione `identifierNamesCache` è abilitata, `null` altrimenti.
Chiamare `toString()` sull'oggetto `ObfuscationResult` restituirà una `string` con il codice offuscato.
Il metodo accetta due parametri, `sourceCode` e `options` – rispettivamente il codice sorgente e le opzioni:
* `sourceCode` (`string`, default: `null`) – qualsiasi codice sorgente valido, passato come stringa;
* `options` (`Object`, default: `null`) – un oggetto con le opzioni.
Per le opzioni disponibili, vedere [options](#options).
### `obfuscateMultiple(sourceCodesObject, options)`
Accetta `sourceCodesObject` che è una mappa le cui chiavi sono identificatori dei codici sorgente e i cui valori sono i codici sorgente:```
{
foo: 'var foo = 1;',
bar: 'var bar = 2;'
}
Restituisce un oggetto map le cui chiavi sono identificatori dei codici sorgente e i valori sono oggetti ObfuscationResult.
getOptionsByPreset(optionsPreset)Restituisce un oggetto di opzioni per il nome del preset di opzioni passato.
I metodi API Pro forniscono accesso all'offuscamento del bytecode basato su VM tramite il servizio cloud obfuscator.io. L'offuscamento VM è la forma più avanzata e sicura di protezione del codice disponibile, trasformando le funzioni JavaScript in bytecode personalizzato che viene eseguito su una macchina virtuale integrata.
Perché l'offuscamento VM?
Per utilizzare i metodi API Pro, hai bisogno di un token API valido da obfuscator.io:
obfuscatePro(sourceCode, options, proApiConfig, onProgress?) 🆕Metodo asincrono che offusca il codice utilizzando l'API Pro con offuscamento del bytecode basato su VM.```javascript const JavaScriptObfuscator = require('javascript-obfuscator');
const result = await JavaScriptObfuscator.obfuscatePro(
function hello() { console.log("Hello World"); },
{
vmObfuscation: true, // Required!
compact: true
},
{
apiToken: 'your_javascript_obfuscator_pro_api_token'
}
);
console.log(result.getObfuscatedCode());
**Parametri:**
* `sourceCode` (`string`) – codice sorgente da offuscare
* `options` (`Object`) – opzioni di offuscamento. Per utilizzare l'API Pro, includi almeno una funzionalità Pro: `vmObfuscation: true` o `parseHtml: true`. Quando nessuna funzionalità Pro è abilitata, `obfuscatePro` ripiega sull'API di offuscamento di base (locale).
* `apiConfig` (`Object`) – configurazione dell'API Pro:
* `apiToken` (`string`, obbligatorio) – il tuo token API da obfuscator.io
* `timeout` (`number`, opzionale) – timeout della richiesta in ms (predefinito: `300000` - 5 minuti)
* `version` (`string`, opzionale) – versione di Obfuscator.io da utilizzare (es. `'5.0.3'`). Se non specificata, viene utilizzata l'ultima versione disponibile.
* `onProgress` (`function`, opzionale) – callback per gli aggiornamenti di avanzamento durante l'offuscamento
**Restituisce:** `Promise<ObfuscationResult>`
> **Nota:** Quando nessuna funzionalità Pro (`vmObfuscation` o `parseHtml`) è abilitata, l'API Pro non è necessaria, quindi `obfuscatePro` ripiega sull'API di offuscamento di base (locale) e non viene effettuata alcuna richiesta API.
**Genera un'eccezione:** `ApiError` se:
- Il token API non è valido o è scaduto
- La richiesta API fallisce
### API Pro con versione specifica
Puoi specificare quale versione dell'offuscatore utilizzare tramite l'opzione `version`:```javascript
const result = await JavaScriptObfuscator.obfuscatePro(
sourceCode,
{
vmObfuscation: true
},
{
apiToken: 'your_javascript_obfuscator_pro_api_token',
version: '5.0.3' // Use specific version
}
);
L'API utilizza la modalità di streaming per fornire aggiornamenti di avanzamento in tempo reale durante l'offuscamento:```javascript const result = await JavaScriptObfuscator.obfuscatePro( sourceCode, { vmObfuscation: true }, { apiToken: 'your_javascript_obfuscator_pro_api_token' }, (message) => { console.log('Progress:', message); // Output: "Validating request...", "Authenticating...", "Obfuscating...", etc. } );
### Verifica delle funzionalità Pro
Usa `ProApiClient.hasProFeatures()` per verificare se le opzioni richiedono l'API Pro:```javascript
const { ProApiClient } = require('javascript-obfuscator');
const options = { vmObfuscation: true, compact: true };
if (ProApiClient.hasProFeatures(options)) {
// Use obfuscatePro() - requires API token
const result = await JavaScriptObfuscator.obfuscatePro(sourceCode, options, { apiToken });
} else {
// Use regular obfuscate() - no API token needed
const result = JavaScriptObfuscator.obfuscate(sourceCode, options);
}
Funzionalità Pro:
vmObfuscation: true – offuscamento del bytecode basato su VMparseHtml: true – parsing HTML con offuscamento JavaScript inlineconst { ApiError } = require('javascript-obfuscator');
try {
const result = await JavaScriptObfuscator.obfuscatePro(sourceCode, options, config);
} catch (error) {
if (error instanceof ApiError) {
console.error(API Error (${error.statusCode}): ${error.message});
} else {
throw error;
}
}
### Utilizzo da CLI con API Pro
Puoi anche utilizzare le funzionalità dell'API Pro direttamente dalla CLI fornendo il tuo token API:```sh
javascript-obfuscator input.js --pro-api-token YOUR_API_TOKEN --vm-obfuscation true -o output.js
Con una versione specifica dell'obfuscator:```sh javascript-obfuscator input.js --pro-api-token YOUR_API_TOKEN --pro-api-version 5.0.3 --vm-obfuscation true -o output.js
**Opzioni CLI:**
- `--pro-api-token <string>` – Il tuo token API da [obfuscator.io](https://obfuscator.io)
- `--pro-api-version <string>` – Versione di Obfuscator.io da utilizzare (opzionale, predefinita all'ultima)
La CLI rileva automaticamente quando le funzionalità Pro (`vmObfuscation` o `parseHtml`) sono abilitate e instrada la richiesta attraverso l'API Pro.
### Caricamenti di File di Grandi Dimensioni
Per file più grandi di circa 4MB, l'API Pro utilizza caricamenti lato client verso lo storage Vercel Blob. Per abilitare questa funzionalità, installa il pacchetto opzionale `@vercel/blob`:```sh
npm install @vercel/blob
Senza questo pacchetto, l'offuscamento di file di grandi dimensioni fallirà con un messaggio di errore che ti invita a installarlo.
Consulta le opzioni CLI.
Utilizzo:```sh javascript-obfuscator input_file_name.js [options] javascript-obfuscator input_file_name.js --output output_file_name.js [options] javascript-obfuscator input_file_name.js --output output_folder_name [options] javascript-obfuscator input_folder_name --output output_folder_name [options]
Obfuscazione di un singolo file di input con estensione `.js`.
Se il percorso di destinazione non è specificato con l'opzione `--output`, il file offuscato verrà salvato nella directory del file di input, con il nome `INPUT_FILE_NAME-obfuscated.js`.
Alcuni esempi:```sh
javascript-obfuscator samples/sample.js --compact true --self-defending false
// creates a new file samples/sample-obfuscated.js
javascript-obfuscator samples/sample.js --output output/output.js --compact true --self-defending false
// creates a new file output/output.js
Utilizzo:```sh
javascript-obfuscator ./dist [options]
// creates a new obfuscated files under ./dist directory near the input files with obfuscated postfix
javascript-obfuscator ./dist --output ./dist/obfuscated [options]
// creates a folder structure with obfuscated files under ./dist/obfuscated path
Offuscamento di tutti i file `.js` nella directory di input. Se questa directory contiene già file offuscati con il suffisso `-obfuscated`, questi file verranno ignorati.
I file offuscati verranno salvati nella directory di input con il nome `NOME_FILE_INPUT-obfuscated.js`.
## Commenti condizionali
Puoi disabilitare e abilitare l'offuscamento per parti specifiche del codice aggiungendo i seguenti commenti:
* disabilita: `// javascript-obfuscator:disable` o `/* javascript-obfuscator:disable */`;
* abilita: `// javascript-obfuscator:enable` o `/* javascript-obfuscator:enable */`.
Esempio:```javascript
// input
var foo = 1;
// javascript-obfuscator:disable
var bar = 2;
// output
var _0xabc123 = 0x1;
var bar = 2;
I commenti condizionali influenzano solo le trasformazioni dirette dei nodi dell'albero AST. Tutte le trasformazioni figlie verranno comunque applicate ai nodi dell'albero AST.
Ad esempio:
Il tipo di variabili dei nodi inseriti verrà rilevato automaticamente, in base al tipo di variabili prevalente nel codice sorgente.
Durante l'offuscamento di file diversi, possono essere generati gli stessi nomi per gli identificatori globali tra questi file.
Per prevenire ciò, imposta un prefisso univoco per tutti gli identificatori globali di ogni file offuscato con l'opzione identifiersPrefix.
Quando si utilizza la CLI, questo prefisso verrà aggiunto automaticamente.
🛡️ Cerchi l'offuscamento VM? Opzioni come
vmObfuscation,parseHtmle ogni opzionevm*sono disponibili solo nella versione Pro e richiedono un token API da obfuscator.io. Usale tramite il metodoobfuscatePro()o il flag CLI--pro-api-token— vedi Metodi API Pro.
Le seguenti opzioni sono disponibili per l'offuscatore JS:
{ compact: true, controlFlowFlattening: false, controlFlowFlatteningThreshold: 0.75, deadCodeInjection: false, deadCodeInjectionThreshold: 0.4, debugProtection: false, debugProtectionInterval: 0, disableConsoleOutput: false, domainLock: [], domainLockRedirectUrl: 'about:blank', forceTransformStrings: [], identifierNamesCache: null, identifierNamesGenerator: 'hexadecimal', identifiersDictionary: [], identifiersPrefix: '', ignoreImports: false, inputFileName: '', log: false, numbersToExpressions: false, optionsPreset: 'default', renameGlobals: false, renameProperties: false, renamePropertiesMode: 'safe', reservedNames: [], reservedStrings: [], seed: 0, selfDefending: false, simplify: true, sourceMap: false, sourceMapBaseUrl: '', sourceMapFileName: '', sourceMapMode: 'separate', sourceMapSourcesMode: 'sources-content', splitStrings: false, splitStringsChunkLength: 10, stringArray: true, stringArrayCallsTransform: true, stringArrayCallsTransformThreshold: 0.5, stringArrayEncoding: [], stringArrayIndexesType: [ 'hexadecimal-number' ], stringArrayIndexShift: true, stringArrayRotate: true, stringArrayShuffle: true, stringArrayWrappersCount: 1, stringArrayWrappersChainedCalls: true, stringArrayWrappersParametersMaxCount: 2, stringArrayWrappersType: 'variable', stringArrayThreshold: 0.75, target: 'browser', transformObjectKeys: false, unicodeEscapeSequence: false }
#### Opzioni CLI:```sh
-v, --version
-h, --help
-o, --output
--compact <boolean>
--config <string>
--control-flow-flattening <boolean>
--control-flow-flattening-threshold <number>
--dead-code-injection <boolean>
--dead-code-injection-threshold <number>
--debug-protection <boolean>
--debug-protection-interval <number>
--disable-console-output <boolean>
--domain-lock '<list>' (comma separated)
--domain-lock-redirect-url <string>
--exclude '<list>' (comma separated)
--force-transform-strings '<list>' (comma separated)
--identifier-names-cache-path <string>
--identifier-names-generator <string> [dictionary, hexadecimal, mangled, mangled-shuffled]
--identifiers-dictionary '<list>' (comma separated)
--identifiers-prefix <string>
--random-identifiers-prefix <boolean>
--ignore-imports <boolean>
--log <boolean>
--numbers-to-expressions <boolean>
--options-preset <string> [default, low-obfuscation, medium-obfuscation, high-obfuscation]
--rename-globals <boolean>
--rename-properties <boolean>
--rename-properties-mode <string> [safe, unsafe]
--reserved-names '<list>' (comma separated)
--reserved-strings '<list>' (comma separated)
--seed <string|number>
--self-defending <boolean>
--simplify <boolean>
--source-map <boolean>
--source-map-base-url <string>
--source-map-file-name <string>
--source-map-mode <string> [inline, separate]
--source-map-sources-mode <string> [sources, sources-content]
--split-strings <boolean>
--split-strings-chunk-length <number>
--string-array <boolean>
--string-array-calls-transform <boolean>
--string-array-calls-transform-threshold <number>
--string-array-encoding '<list>' (comma separated) [none, base64, rc4]
--string-array-indexes-type '<list>' (comma separated) [hexadecimal-number, hexadecimal-numeric-string]
--string-array-index-shift <boolean>
--string-array-rotate <boolean>
--string-array-shuffle <boolean>
--string-array-wrappers-count <number>
--string-array-wrappers-chained-calls <boolean>
--string-array-wrappers-parameters-max-count <number>
--string-array-wrappers-type <string> [variable, function]
--string-array-threshold <number>
--target <string> [browser, browser-no-eval, node]
--browser-environment <string> [http, https]
--transform-object-keys <boolean>
--unicode-escape-sequence <boolean>
--pro-api-token <string>
--pro-api-version <string>
--vm-obfuscation <boolean>
--vm-obfuscation-threshold <number>
--vm-preprocess-identifiers <boolean>
--vm-dynamic-opcodes <boolean>
--vm-target-functions '<list>' (comma separated)
--vm-exclude-functions '<list>' (comma separated)
--vm-target-functions-mode <string> [root, comment]
--vm-force-compile-dynamic-code <boolean>
--vm-wrap-top-level-initializers <boolean>
--vm-opcode-shuffle <boolean>
--vm-bytecode-encoding <boolean>
--vm-bytecode-array-encoding <boolean>
--vm-bytecode-array-encoding-key <string>
--vm-bytecode-array-encoding-key-getter <string>
--vm-instruction-shuffle <boolean>
--vm-jumps-encoding <boolean>
--vm-decoy-opcodes <boolean>
--vm-dead-code-injection <boolean>
--vm-split-dispatcher <boolean>
--vm-macro-ops <boolean>
--vm-debug-protection <boolean>
--vm-self-defending <boolean>
--vm-runtime-opcode-derivation <boolean>
--vm-stateful-opcodes <boolean>
--vm-async-executor <boolean>
--vm-call-context-opcodes <boolean>
--vm-stack-encoding <boolean>
--vm-randomize-keys <boolean>
--vm-indirect-dispatch <boolean>
--vm-compact-dispatcher <boolean>
--vm-register-based <boolean>
--vm-string-array-bytecode-only <boolean>
--vm-domain-lock '<list>' (comma separated)
--vm-domain-lock-redirect-url <string>
--vm-bytecode-format <string> [binary, json]
--parse-html <boolean>
--strict-mode <boolean>
compactTipo: boolean Predefinito: true
Output del codice compatto su una singola riga.
configTipo: string Predefinito: ``
Nome del file di configurazione JS/JSON che contiene le opzioni dell'obfuscator. Queste verranno sovrascritte dalle opzioni passate direttamente alla CLI.
controlFlowFlatteningTipo: boolean Predefinito: false
controlFlowFlatteningThreshold per impostare la percentuale di nodi che saranno interessati dall'appiattimento del flusso di controllo.Abilita l'appiattimento del flusso di controllo del codice. L'appiattimento del flusso di controllo è una trasformazione strutturale del codice sorgente che ostacola la comprensione del programma.
Esempio:```ts // 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'; continue; case '1': console'log'; continue; case '2': console'log'; continue; case '3': console'log'; continue; case '4': var _0x1f2f2f = _0x3260a5['GokKo'](0x1, 0x2); continue; case '5': console'log'; continue; case '6': console'log'; continue; } break; } }; }
_0x3bfc5c()();
}());
### `controlFlowFlatteningThreshold`
Tipo: `number` Predefinito: `0.75` Min: `0` Max: `1`
La probabilità che la trasformazione [`controlFlowFlattening`](#controlflowflattening) venga applicata a un determinato nodo.
Questa impostazione è particolarmente utile per codici di grandi dimensioni, poiché un elevato numero di trasformazioni del flusso di controllo può rallentare il codice e aumentarne le dimensioni.
`controlFlowFlatteningThreshold: 0` equivale a `controlFlowFlattening: false`.
### `deadCodeInjection`
Tipo: `boolean` Predefinito: `false`
##### :warning: Aumenta drasticamente le dimensioni del codice offuscato (fino al 200%), usalo solo se le dimensioni del codice offuscato non sono un problema. Usa [`deadCodeInjectionThreshold`](#deadcodeinjectionthreshold) per impostare la percentuale di nodi che saranno interessati dall'iniezione di codice morto.
##### :warning: Questa opzione abilita forzatamente l'opzione `stringArray`.
Con questa opzione, blocchi casuali di codice morto verranno aggiunti al codice offuscato.
Esempio:```ts
// 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)](https://github.com/javascript-obfuscator/javascript-obfuscator/blob/master/_0x2fc85f%280xb5));
} else {
console[_0x2fc85f(0xb2)](https://github.com/javascript-obfuscator/javascript-obfuscator/blob/master/_0x2fc85f%280xad));
}
};
var _0x5e46bc = function () {
var _0x15b472 = _0x43a7;
if (_0x15b472(0xb6) !== _0x15b472(0xaa)) {
console[_0x15b472(0xb2)](https://github.com/javascript-obfuscator/javascript-obfuscator/blob/master/_0x15b472%280xb5));
} else {
_0x47eac2[_0x15b472(0xb2)](https://github.com/javascript-obfuscator/javascript-obfuscator/blob/master/_0x15b472%280xad));
}
};
var _0x3669e8 = function () {
var _0x47a442 = _0x43a7;
if (_0x47a442(0xb7) !== _0x47a442(0xb0)) {
console[_0x47a442(0xb2)](https://github.com/javascript-obfuscator/javascript-obfuscator/blob/master/_0x47a442%280xb8));
} else {
_0x24e0bf[_0x47a442(0xb2)](https://github.com/javascript-obfuscator/javascript-obfuscator/blob/master/_0x47a442%280xb3));
}
};
var _0x28b05a = function () {
var _0x497902 = _0x43a7;
if (_0x497902(0xb1) === _0x497902(0xb1)) {
console[_0x497902(0xb2)](https://github.com/javascript-obfuscator/javascript-obfuscator/blob/master/_0x497902%280xb4));
} else {
_0x59c9c6[_0x497902(0xb2)](https://github.com/javascript-obfuscator/javascript-obfuscator/blob/master/_0x497902%280xb4));
}
};
var _0x402a54 = function () {
var _0x1906b7 = _0x43a7;
if (_0x1906b7(0xab) === _0x1906b7(0xac)) {
_0xb89cd0[_0x1906b7(0xb2)](https://github.com/javascript-obfuscator/javascript-obfuscator/blob/master/_0x1906b7%280xb8));
} else {
console[_0x1906b7(0xb2)](https://github.com/javascript-obfuscator/javascript-obfuscator/blob/master/_0x1906b7%280xb3));
}
};
_0xbbe28f();
_0x5e46bc();
_0x3669e8();
_0x28b05a();
_0x402a54();
}
}());
deadCodeInjectionThresholdTipo: number Predefinito: 0.4 Min: 0 Max: 1
Consente di impostare la percentuale di nodi che saranno interessati da deadCodeInjection.
debugProtectionTipo: boolean Predefinito: false
Questa opzione rende quasi impossibile utilizzare la funzione debugger degli Strumenti di Sviluppo (sia nei browser basati su WebKit che in Mozilla Firefox).
debugProtectionIntervalTipo: number Predefinito: 0
Se impostato, viene utilizzato un intervallo in millisecondi per forzare la modalità di debug nella scheda Console, rendendo più difficile utilizzare altre funzionalità degli Strumenti di Sviluppo. Funziona se debugProtection è abilitato. Il valore consigliato è compreso tra 2000 e 4000 millisecondi.
disableConsoleOutputTipo: boolean Predefinito: false
console a livello globale per tutti gli scriptDisabilita l'uso di console.log, console.info, console.error, console.warn, console.debug, console.exception e console.trace sostituendoli con funzioni vuote. Questo rende più difficile l'uso del debugger.
domainLockTipo: string[] Predefinito: []
target: 'node'Consente di eseguire il codice sorgente offuscato solo su domini specifici e/o sottodomini. Questo rende davvero difficile per qualcuno copiare e incollare il tuo codice sorgente ed eseguirlo altrove.
Se il codice sorgente non viene eseguito sui domini specificati da questa opzione, il browser verrà reindirizzato a un URL passato all'opzione domainLockRedirectUrl.
È possibile bloccare il codice su più di un dominio o sottodominio. Ad esempio, per bloccarlo in modo che il codice venga eseguito solo su www.example.com, aggiungi www.example.com. Per farlo funzionare sul dominio principale inclusi eventuali sottodomini (example.com, sub.example.com), usa .example.com.
domainLockRedirectUrlTipo: string Predefinito: about:blank
target: 'node'Consente al browser di essere reindirizzato a un URL passato se il codice sorgente non viene eseguito sui domini specificati da domainLock
excludeTipo: string[] Predefinito: []
Nomi di file o glob che indicano i file da escludere dall'offuscamento.
forceTransformStringsTipo: string[] Predefinito: []
Abilita la trasformazione forzata delle stringhe letterali che corrispondono ai pattern RegExp passati.
stringArrayThreshold (o possibili altre soglie in futuro)L'opzione ha priorità sull'opzione reservedStrings ma non ha priorità sui commenti condizionali.
Esempio:```ts { forceTransformStrings: [ 'some-important-value', 'some-string_\d' ] }
### `identifierNamesCache`
Tipo: `Object | null` Predefinito: `null`
L'obiettivo principale di questa opzione è la possibilità di utilizzare gli stessi nomi di identificatori durante l'offuscamento di più sorgenti/file.
Attualmente sono supportati due tipi di identificatori:
- Identificatori globali:
* Tutti gli identificatori globali verranno scritti nella cache;
* Tutti gli identificatori globali **non dichiarati** corrispondenti verranno sostituiti con i valori dalla cache.
- Identificatori di proprietà, solo quando l'opzione `renameProperties` è abilitata:
* Tutti gli identificatori di proprietà verranno scritti nella cache;
* Tutti gli identificatori di proprietà corrispondenti verranno sostituiti con i valori dalla cache.
#### API Node.js
Se viene passato un valore `null`, la cache viene completamente disabilitata.
Se viene passato un oggetto vuoto (`{}`), viene abilitata la scrittura dei nomi degli identificatori nell'oggetto cache (tipo `TIdentifierNamesCache`). Questo oggetto cache sarà accessibile tramite la chiamata al metodo `getIdentifierNamesCache` dell'oggetto `ObfuscationResult`.
L'oggetto cache risultante può essere successivamente utilizzato come valore dell'opzione `identifierNamesGenerator` per utilizzare questi nomi durante l'offuscamento di tutti i nomi di identificatori corrispondenti delle sorgenti successive.
Esempio:```ts
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 ha un'opzione diversa --identifier-names-cache-path che consente di definire un percorso al file .json esistente che verrà utilizzato per leggere e scrivere la cache dei nomi degli identificatori.
Se viene passato un percorso a un file vuoto, la cache dei nomi degli identificatori verrà scritta in quel file.
Questo file con la cache esistente può essere riutilizzato come valore dell'opzione --identifier-names-cache-path per utilizzare questi nomi durante l'offuscamento di tutti i nomi degli identificatori corrispondenti dei file successivi.
identifierNamesGeneratorTipo: string Predefinito: hexadecimal
Imposta il generatore di nomi degli identificatori.
Valori disponibili:
dictionary: nomi degli identificatori dall'elenco identifiersDictionaryhexadecimal: nomi degli identificatori come _0xabc123mangled: nomi degli identificatori brevi come a, b, cmangled-shuffled: come mangled ma con alfabeto mescolatoidentifiersDictionaryTipo: string[] Predefinito: []
Imposta il dizionario degli identificatori per l'opzione identifierNamesGenerator: dictionary. Ogni identificatore del dizionario verrà utilizzato in alcune varianti con una diversa capitalizzazione di ogni carattere. Pertanto, il numero di identificatori nel dizionario dovrebbe dipendere dalla quantità di identificatori nel codice sorgente originale.
identifiersPrefixTipo: string Predefinito: ''
Imposta il prefisso per tutti gli identificatori globali.
Utilizza questa opzione quando vuoi offuscare più file. Questa opzione aiuta a evitare conflitti tra gli identificatori globali di questi file. Il prefisso dovrebbe essere diverso per ogni file.
ignoreImportsTipo: boolean Predefinito: false
Impedisce l'offuscamento degli import require. Può essere utile in alcuni casi quando, per qualche motivo, l'ambiente di runtime richiede questi import solo con stringhe statiche.
inputFileNameTipo: string Predefinito: ''
Consente di impostare il nome del file di input con il codice sorgente. Questo nome verrà utilizzato internamente per la generazione della source map.
Richiesto quando si utilizza l'API NodeJS e l'opzione sourceMapSourcesMode ha il valore sources.
logTipo: boolean Predefinito: false
Abilita la registrazione delle informazioni nella console.
numbersToExpressionsTipo: boolean Predefinito: false
Abilita la conversione dei numeri in espressioni.
Esempio:```ts // input const foo = 1234;
// output const foo=-0xd93+-0x10b4+0x410x67+0x84e0x3+-0xff8;
### `optionsPreset`
Tipo: `string` Default: `default`
Consente di impostare un [preset di opzioni](#preset-options).
Valori disponibili:
* `default`;
* `low-obfuscation`;
* `medium-obfuscation`;
* `high-obfuscation`.
Tutte le opzioni aggiuntive verranno unite al preset di opzioni selezionato.
### `renameGlobals`
Tipo: `boolean` Default: `false`
##### :warning: questa opzione può rompere il tuo codice. Abilitala solo se sai cosa fa!
Abilita l'offuscamento dei nomi di variabili e funzioni globali **con dichiarazione**.
### `renameProperties`
Tipo: `boolean` Default: `false`
##### :warning: questa opzione **PUÒ** rompere il tuo codice. Abilitala solo se sai cosa fa!
Abilita la rinomina dei nomi delle proprietà. Tutte le proprietà DOM integrate e le proprietà delle classi JavaScript core verranno ignorate.
Per passare tra le modalità `safe` e `unsafe` di questa opzione, utilizza l'opzione [`renamePropertiesMode`](#renamepropertiesmode).
Per impostare il formato dei nomi delle proprietà rinominate, utilizza l'opzione [`identifierNamesGenerator`](#identifiernamesgenerator).
Per controllare quali proprietà verranno rinominate, utilizza l'opzione [`reservedNames`](#reservednames).
Esempio:```ts
// 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'](https://github.com/javascript-obfuscator/javascript-obfuscator/blob/master/_0x46529b%5B%27_0x4b961d%27%5D%28));
}());
renamePropertiesModeTipo: string Default: safe
safe, l'opzione renameProperties POTREBBE rompere il tuo codice.Specifica la modalità dell'opzione renameProperties:
safe - comportamento predefinito dopo il rilascio di 2.11.0. Tenta di rinominare le proprietà in modo più sicuro per prevenire errori di runtime. Con questa modalità alcune proprietà saranno escluse dalla rinomina.unsafe - comportamento predefinito prima del rilascio di 2.11.0. Rinomina le proprietà in modo non sicuro senza alcuna restrizione.Se un file utilizza proprietà da un altro file, usa l'opzione identifierNamesCache per mantenere gli stessi nomi di proprietà tra questi file.
reservedNamesTipo: string[] Default: []
Disabilita l'offuscamento e la generazione di identificatori che corrispondono ai pattern RegExp passati.
Esempio:```ts { reservedNames: [ '^someVariable', 'functionParameter_\d' ] }
### `reservedStrings`
Tipo: `string[]` Predefinito: `[]`
Disabilita la trasformazione dei literal di stringa che corrispondono ai pattern RegExp passati.
Esempio:```ts
{
reservedStrings: [
'react-native',
'\.\/src\/test',
'some-string_\d'
]
}
seedTipo: string|number Predefinito: 0
Questa opzione imposta il seed per il generatore casuale. È utile per creare risultati ripetibili.
Se il seed è 0 - il generatore casuale funzionerà senza seed.
selfDefendingTipo: boolean Predefinito: false
compact su trueQuesta opzione rende il codice di output resistente alla formattazione e alla rinomina delle variabili. Se si tenta di utilizzare un beautifier JavaScript sul codice offuscato, il codice non funzionerà più, rendendo più difficile comprenderlo e modificarlo.
simplifyTipo: boolean Predefinito: true
Abilita un'ulteriore offuscamento del codice tramite semplificazione.
boolean (true => !![]) verrà spostato sotto questa opzione.Esempio:```ts // 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', bar; } else return condition2 ? (console'log', console'log', console'log', 0x4) : 0x5;
### `sourceMap`
Tipo: `boolean` Predefinito: `false`
Abilita la generazione della source map per il codice offuscato.
Le source map possono essere utili per aiutarti a eseguire il debug del tuo codice JavaScript offuscato. Se vuoi o hai bisogno di eseguire il debug in produzione, puoi caricare il file della source map separato in una posizione segreta e poi puntare il tuo browser lì.
### `sourceMapBaseUrl`
Tipo: `string` Predefinito: ``
Imposta l'URL di base per l'URL di importazione della source map quando [`sourceMapMode: 'separate'`](#sourcemapmode).
Esempio CLI:```
javascript-obfuscator input.js --output out.js --source-map true --source-map-base-url 'http://localhost:9000'
Risultato:``` //# sourceMappingURL=http://localhost:9000/out.js.map
### `sourceMapFileName`
Tipo: `string` Predefinito: ``
Imposta il nome del file per la mappa sorgente di output quando `sourceMapMode: 'separate'`.
Esempio CLI:```
javascript-obfuscator input.js --output out.js --source-map true --source-map-base-url 'http://localhost:9000' --source-map-file-name example
Risultato:``` //# sourceMappingURL=http://localhost:9000/example.js.map
### `sourceMapMode`
Tipo: `string` Predefinito: `separate`
Specifica la modalità di generazione della source map:
* `inline` - aggiunge la source map alla fine di ogni file .js;
* `separate` - genera il corrispondente file '.map' con la source map. Se esegui l'obfuscator tramite CLI, aggiunge il link al file della source map alla fine del file con codice offuscato `//# sourceMappingUrl=file.js.map`.
### `sourceMapSourcesMode`
Tipo: `string` Predefinito: `sources-content`
Consente di controllare i campi `sources` e `sourcesContent` della source map:
* `sources-content` - aggiunge un campo `sources` fittizio, aggiunge il campo `sourcesContent` con il codice sorgente originale;
* `sources` - aggiunge il campo `sources` con una descrizione valida della sorgente, non aggiunge il campo `sourcesContent`. Quando si utilizza l'API NodeJS è necessario definire l'opzione `inputFileName` che verrà utilizzata come valore del campo `sources`.
### `splitStrings`
Tipo: `boolean` Predefinito: `false`
Divide le stringhe letterali in blocchi con lunghezza pari al valore dell'opzione [`splitStringsChunkLength`](#splitstringschunklength).
Esempio:```ts
// input
(function(){
var test = 'abcdefg';
})();
// output
(function(){
var _0x5a21 = 'ab' + 'cd' + 'ef' + 'g';
})();
splitStringsChunkLengthTipo: number Predefinito: 10
Imposta la lunghezza dei blocchi dell'opzione splitStrings.
stringArrayTipo: boolean Predefinito: true
Rimuove i literal di stringa e li inserisce in un array speciale. Ad esempio, la stringa "Hello World" in var m = "Hello World"; verrà sostituita con qualcosa come var m = _0x12c456[0x1];
stringArrayCallsTransformTipo: boolean Predefinito: false
stringArray deve essere abilitataAbilita la trasformazione delle chiamate al stringArray. Tutti gli argomenti di queste chiamate possono essere estratti in un oggetto diverso a seconda del valore di stringArrayCallsTransformThreshold.
In questo modo diventa ancora più difficile trovare automaticamente le chiamate all'array di stringhe.
Esempio:``` 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); } consolej(-'0xa6', -'0xa6')); 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`
Tipo: `number` Predefinito: `0.5`
##### :warning: le opzioni [`stringArray`](#stringarray) e [`stringArrayCallsTransformThreshold`](#stringarraycallstransformthreshold) devono essere abilitate
Puoi usare questa impostazione per regolare la probabilità (da 0 a 1) che le chiamate all'array di stringhe vengano trasformate.
### `stringArrayEncoding`
Tipo: `string[]` Predefinito: `[]`
##### :warning: l'opzione `stringArray` deve essere abilitata
Questa opzione può rallentare il tuo script.
Codifica tutte le stringhe letterali di [`stringArray`](#stringarray) usando `base64` o `rc4` e inserisce un codice speciale che viene utilizzato per decodificarle nuovamente in fase di esecuzione.
Ogni valore di `stringArray` verrà codificato con la codifica scelta casualmente dall'elenco passato. Questo rende possibile utilizzare più codifiche.
Valori disponibili:
* `'none'` (`boolean`): non codifica il valore di `stringArray`
* `'base64'` (`string`): codifica il valore di `stringArray` usando `base64`
* `'rc4'` (`string`): codifica il valore di `stringArray` usando `rc4`. **Circa il 30-50% più lento di `base64`, ma più difficile ottenere i valori iniziali.** Si consiglia di disabilitare l'opzione [`unicodeEscapeSequence`](#unicodeescapesequence) quando si utilizza la codifica `rc4` per evitare una dimensione molto grande del codice offuscato.
Ad esempio, con i seguenti valori di opzione, alcuni valori di `stringArray` non verranno codificati e alcuni valori verranno codificati con la codifica `base64` e `rc4`:```ts
stringArrayEncoding: [
'none',
'base64',
'rc4'
]
stringArrayIndexesTypeTipo: string[] Predefinito: ['hexadecimal-number']
stringArray deve essere abilitataConsente di controllare il tipo di indici di chiamata dell'array di stringhe.
Ogni indice di chiamata stringArray verrà trasformato dal tipo scelto casualmente dall'elenco passato. Ciò rende possibile utilizzare più tipi.
Valori disponibili:
'hexadecimal-number' (predefinito): trasforma gli indici di chiamata dell'array di stringhe come numeri esadecimali'hexadecimal-numeric-string': trasforma gli indici di chiamata dell'array di stringhe come stringhe numeriche esadecimaliPrima della versione 2.9.0, javascript-obfuscator trasformava tutti gli indici di chiamata dell'array di stringhe con il tipo hexadecimal-numeric-string. Ciò rende la deoffuscazione manuale leggermente più difficile, ma consente una facile rilevazione di queste chiamate da parte di deoffuscatori automatici.
Il nuovo tipo hexadecimal-number mira a rendere più difficile l'auto-rilevamento dei modelli di chiamata dell'array di stringhe nel codice.
In futuro verranno aggiunti altri tipi.
stringArrayIndexShiftTipo: boolean Predefinito: true
stringArray deve essere abilitataAbilita uno spostamento aggiuntivo dell'indice per tutte le chiamate all'array di stringhe
stringArrayRotateTipo: boolean Predefinito: true
stringArray deve essere abilitatoSposta l'array stringArray di posizioni fisse e casuali (generate durante l'offuscamento del codice). Ciò rende più difficile abbinare l'ordine delle stringhe rimosse alla loro posizione originale.
stringArrayShuffleTipo: boolean Predefinito: true
stringArray deve essere abilitatoMescola casualmente gli elementi dell'array stringArray.
stringArrayWrappersCountTipo: number Predefinito: 1
stringArray deve essere abilitataImposta il numero di wrapper per l'array di stringhe all'interno di ogni ambito radice o di funzione.
Il numero effettivo di wrapper all'interno di ogni ambito è limitato dal numero di nodi literal all'interno di tale ambito.
Esempio:```ts // 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`
Tipo: `boolean` Predefinito: `true`
##### :warning: le opzioni [`stringArray`](#stringarray) e [`stringArrayWrappersCount`](#stringarraywrapperscount) devono essere abilitate
Abilita le chiamate concatenate tra i wrapper di `string array`.
Esempio:```ts
// 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);
}
}
stringArrayWrappersParametersMaxCountTipo: number Predefinito: 2
stringArray deve essere abilitatafunction di stringArrayWrappersTypeConsente di controllare il numero massimo di parametri dei wrapper dell'array di stringhe.
Il valore predefinito e minimo è 2. Valore consigliato tra 2 e 5.
stringArrayWrappersTypeTipo: string Predefinito: variable
stringArray e stringArrayWrappersCount devono essere abilitateConsente di selezionare un tipo di wrapper che vengono aggiunti dall'opzione stringArrayWrappersCount.
Valori disponibili:
'variable': aggiunge wrapper variabili all'inizio di ogni ambito. Prestazioni veloci.'function': aggiunge wrapper di funzione in posizioni casuali all'interno di ogni ambito. Prestazioni più lente rispetto a variable ma fornisce un'offuscamento più rigoroso.Altamente consigliato utilizzare wrapper function per un maggiore offuscamento quando la perdita di prestazioni non ha un impatto elevato su un'applicazione offuscata.
Esempio del valore dell'opzione 'function':```ts
// 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`
Tipo: `number` Default: `0.8` Min: `0` Max: `1`
##### :warning: l'opzione [`stringArray`](#stringarray) deve essere abilitata
Puoi usare questa impostazione per regolare la probabilità (da 0 a 1) che una stringa letterale venga inserita nel `stringArray`.
Questa impostazione è particolarmente utile per codice di grandi dimensioni, poiché le chiamate ripetute al `string array` possono rallentare il tuo codice.
`stringArrayThreshold: 0` equivale a `stringArray: false`.
### `target`
Tipo: `string` Default: `browser`
Consente di impostare l'ambiente di destinazione per il codice offuscato.
Valori disponibili:
* `browser`;
* `browser-no-eval`;
* `node`.
Attualmente il codice generato per gli ambienti `browser` e `node` è identico, ma alcune opzioni specifiche del browser non sono consentite con l'ambiente `node`.
Il codice generato per l'ambiente `browser-no-eval` non utilizza `eval`.
### `transformObjectKeys`
Tipo: `boolean` Default: `false`
Abilita la trasformazione delle chiavi degli oggetti.
Esempio:```ts
// 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;
}());
unicodeEscapeSequenceTipo: boolean Predefinito: false
Consente di abilitare/disabilitare la conversione delle stringhe in sequenze di escape Unicode.
Le sequenze di escape Unicode aumentano notevolmente le dimensioni del codice e le stringhe possono essere facilmente riportate alla loro vista originale. Si consiglia di abilitare questa opzione solo per codice sorgente di piccole dimensioni.
Le prestazioni saranno molto più lente rispetto a senza offuscamento```javascript
{
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,
stringArray: true,
stringArrayCallsTransform: true,
stringArrayEncoding: ['rc4'],
stringArrayIndexShift: true,
stringArrayRotate: true,
stringArrayShuffle: true,
stringArrayWrappersCount: 5,
stringArrayWrappersChainedCalls: true,
stringArrayWrappersParametersMaxCount: 5,
stringArrayWrappersType: 'function',
stringArrayThreshold: 1,
transformObjectKeys: true,
unicodeEscapeSequence: false
}
### Offuscamento medio, prestazioni ottimali
Le prestazioni saranno più lente rispetto a senza offuscamento```javascript
{
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,
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,
unicodeEscapeSequence: false
}
Le prestazioni saranno a un livello relativamente normale```javascript { 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, stringArray: true, stringArrayCallsTransform: false, stringArrayEncoding: [], stringArrayIndexShift: true, stringArrayRotate: true, stringArrayShuffle: true, stringArrayWrappersCount: 1, stringArrayWrappersChainedCalls: true, stringArrayWrappersParametersMaxCount: 2, stringArrayWrappersType: 'variable', stringArrayThreshold: 0.75, unicodeEscapeSequence: false }
### Preset predefinito, Alte prestazioni```javascript
{
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,
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,
unicodeEscapeSequence: false
}
⚠️ Le seguenti opzioni di offuscamento VM/Pro sono disponibili solo tramite la API Pro di Obfuscator.io.
Per utilizzare queste opzioni, hai bisogno di un token API Pro da obfuscator.io e devi chiamare il metodo
obfuscatePro()invece diobfuscate(). Consulta la sezione Metodi API Pro per i dettagli.
vmObfuscationTipo: boolean Predefinito: false
Abilita l'offuscamento del bytecode basato su VM. Quando è abilitato, le funzioni JavaScript vengono compilate in bytecode personalizzato che viene eseguito su una macchina virtuale incorporata. Questo fornisce il massimo livello di protezione poiché la logica del codice originale viene completamente trasformata.
Esempio:
Il tuo codice leggibile come return qty * price diventa un elenco di numeri come [0x15,0x03,0x17,...] che solo l'interprete VM incorporato può eseguire. La logica originale non è più visibile come JavaScript.
vmTargetFunctionsTipo: string[] Predefinito: []
Specifica esattamente quali funzioni di livello radice devono ricevere la protezione VM per nome.
Esempio:```javascript { vmObfuscation: true, vmTargetFunctions: ['someFunctionName'] }
**Risultato:** Solo queste tre funzioni vengono protette con VM. Tutto il resto rimane JavaScript normale (ma comunque offuscato). Perfetto per proteggere controlli di licenza sensibili o logica di autenticazione mantenendo il resto del codice snello.
### `vmExcludeFunctions`
Tipo: `string[]` Predefinito: `[]`
Specifica le funzioni a livello di root che non devono mai ricevere la protezione VM. Ha precedenza rispetto alle altre impostazioni.
**Esempio:**```javascript
{
vmObfuscation: true,
vmExcludeFunctions: ['someFunctionName']
}
Quando usarlo: Le funzioni critiche a livello di root (loop di animazione, elaborazione dati in tempo reale) possono essere escluse per evitare l'overhead della VM, proteggendo comunque tutto il resto.
vmTargetFunctionsModeTipo: string Default: root
Controlla come le funzioni/metodi vengono selezionati per l'offuscamento VM.
| Modalità | Descrizione |
|---|---|
root | Comportamento predefinito. Solo le funzioni a livello di root vengono considerate per l'offuscamento VM. Utilizza la lista di consentiti vmTargetFunctions e la lista di blocco vmExcludeFunctions per il filtraggio. |
comment | Solo le funzioni/metodi decorati con il commento /* javascript-obfuscator:vm */ vengono offuscati con VM. Funziona con funzioni/metodi a qualsiasi livello di annidamento. |
Esempio - Modalità commento:```javascript // 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'
}
```
**Quando usarlo:** Quando hai bisogno di un controllo chirurgico su esattamente quali funzioni ricevono la protezione VM, specialmente funzioni annidate che contengono logica sensibile. A differenza di `vmTargetFunctions`, che funziona solo con funzioni nominate a livello di radice, la modalità commento ti consente di proteggere qualsiasi funzione ovunque nel tuo codice.
### `vmForceCompileDynamicCode`
Tipo: `boolean` Predefinito: `false`
Controlla cosa fa l'offuscamento VM con una funzione che contiene una chiamata diretta a `eval`, `new Function(...)` o `Function(...)`.
Per impostazione predefinita, tale funzione (e ogni funzione definita al suo interno) viene saltata dalla codifica in bytecode VM e viene segnalato un avviso `VMDynamicCodeSkipped` su `result.getWarnings()`. Questo perché il sorgente costruito a runtime può fare riferimento a identificatori dalla catena di scope circostante — identificatori che l'offuscatore ha rinominato.
Quando è impostato su `true`, la funzione viene comunque codificata in bytecode e l'avviso `VMDynamicCodeSkipped` non viene più emesso.
Il separato avviso `DynamicCodeRenameRisk` continua a scattare indipendentemente da questa opzione, perché il rischio di rinomina che descrive è indipendente dal salto VM — attivare questa opzione non rende il pattern sottostante più sicuro.```javascript
// Source code
function loadConfig(src) {
return eval(src);
}
loadConfig('1 + 2');
```
Please provide the Markdown content to translate.```javascript
// Options
{
vmObfuscation: true,
vmForceCompileDynamicCode: true
}
```
Con l'opzione disattivata (predefinita), `loadConfig` rimane come JavaScript semplice. Con l'opzione attivata, `loadConfig` viene compilato in bytecode VM come qualsiasi altra funzione. Usa questa opzione quando hai verificato il punto di chiamata e sai che il codice generato a runtime non dipende da identificatori rinominati tramite closure.
### `vmWrapTopLevelInitializers`
Tipo: `boolean` Predefinito: `false`
Avvolge alcuni inizializzatori di variabili a livello top-level in IIFE (Immediately Invoked Function Expressions) così da poter essere offuscati tramite VM.
**Cosa fa:**
Senza questa opzione, costanti e variabili a livello top-level rimangono visibili nell'output:```javascript
// Input
const MY_STRING = "my-string";
// Output (without vmWrapTopLevelInitializers)
const MY_STRING = "my-string"; // String is visible!
```
Con questa opzione abilitata, l'inizializzatore viene racchiuso in un'IIFE che viene offuscato tramite VM:```javascript
// Input
const MY_STRING = "my-string";
// Output (with vmWrapTopLevelInitializers: true)
const MY_STRING = (() => { return /* VM bytecode call */ })(); // String hidden in bytecode
```
**Nota:** Questa opzione funziona solo quando `vmTargetFunctionsMode` è `'root'` (il valore predefinito).
### `vmDynamicOpcodes`
Tipo: `boolean` Predefinito: `false`
Rende l'interprete VM più piccolo e unico per ogni build.
**Cosa fa:**
1. **Filtra le istruzioni non utilizzate** - Se il tuo codice non usa le classi, le istruzioni relative alle classi vengono rimosse completamente
2. **Randomizza la struttura** - L'ordine dei gestori di istruzioni viene mescolato a ogni build
Di conseguenza - output più piccolo e ogni build appare diversa.
### `vmBytecodeEncoding`
Tipo: `boolean` Predefinito: `false`
Codifica ogni istruzione del bytecode. Le istruzioni vengono decodificate una alla volta durante l'esecuzione.
### `vmBytecodeArrayEncoding`
Tipo: `boolean` Predefinito: `false`
Codifica l'intero array di bytecode come un unico blocco. L'array viene decodificato una volta all'avvio, prima che inizi l'esecuzione. Da usare insieme a `vmBytecodeEncoding` per due livelli di protezione.
### `vmBytecodeArrayEncodingKey`
Tipo: `string` Predefinito: `''`
Chiave di crittografia personalizzata per la codifica dell'array di bytecode. Quando impostata, questa chiave viene usata al posto della chiave predefinita derivata dall'ambiente. La chiave deve essere fornita in fase di esecuzione tramite `vmBytecodeArrayEncodingKeyGetter`.
Questa opzione esternalizza la chiave di crittografia - non è incorporata nel codice offuscato stesso. Sebbene la chiave sia ancora accessibile in fase di esecuzione (e quindi non realmente segreta), questa separazione impedisce agli strumenti di analisi statica di trovare la chiave esaminando il solo codice.
**Importante:** La chiave deve essere disponibile **in modo sincrono** quando il codice offuscato viene caricato. Usa archivi sincroni come cookie, localStorage, sessionStorage, variabili globali o elementi DOM (ad es. meta tag iniettati dal server). Metodi asincroni come `fetch()` non possono essere usati direttamente nell'espressione del getter della chiave.
### `vmBytecodeArrayEncodingKeyGetter`
Tipo: `string` Predefinito: `''`
Espressione JavaScript **sincrona** che **restituisce** la chiave di crittografia in fase di esecuzione. Questa espressione viene valutata quando il codice offuscato viene caricato e deve restituire la stessa chiave fornita in `vmBytecodeArrayEncodingKey`.
**Il codice offuscato funzionerà solo quando il getter della chiave restituisce esattamente la stessa chiave usata durante l'offuscamento.** Se le chiavi non corrispondono, la decrittazione fallirà e il codice produrrà dati corrotti o errori. Se il getter della chiave restituisce `undefined`, `null` o una stringa vuota, il codice genererà un errore: "VM decryption key not available".
**Importante:** La chiave NON deve essere definita nello stesso file/script JavaScript del codice offuscato. In questo modo si vanifica lo scopo dell'esternalizzazione della chiave, poiché l'analisi statica potrebbe comunque trovare la chiave. Archivia la chiave in una sorgente separata: cookie impostati dal server, localStorage popolato da un altro script, meta tag HTML iniettati dal server o una variabile globale impostata da uno script diverso che viene caricato prima del codice offuscato.
Esempi:```ts
// 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"
```
**Esempio di utilizzo:**```ts
// 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`
Tipo: `boolean` Default: `false`
Abilita l'esecutore VM asincrono, che consente a [`vmBytecodeArrayEncodingKeyGetter`](#vmbytecodearrayencodingkeygetter) di restituire una `Promise` (un **getter di chiave asincrono**) — così la chiave di decrittazione può essere recuperata a runtime (richiesta di rete, IndexedDB, ecc.) invece di dover essere disponibile in modo sincrono quando il codice viene caricato.
**Fortemente consigliato per codebase completamente asincrone.** In questa modalità vengono virtualizzate solo le funzioni `async` — una funzione sincrona non può essere resa asincrona senza trasformare il suo valore di ritorno in una `Promise` e rompere i suoi chiamanti — quindi il codice che è `async` in tutto ottiene la massima copertura. Funziona comunque quando la radice è sincrona (ad es. un IIFE sincrono / wrapper UMD): le funzioni `async` più esterne al suo interno sono protette, e le parti sincrone vengono lasciate invariate.
**Cosa viene trasformato:** ogni funzione `async` **più esterna**, ovunque appaia (incluso annidata all'interno di wrapper sincroni). L'async più esterno in ogni catena è l'unità protetta — tutto ciò che contiene, sincrono e asincrono, viene compilato. Le funzioni sincrone e i generatori semplici vengono lasciati non offuscati.```js
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
}
}
```
**Salti e avvisi.** I generatori asincroni vengono inoltre lasciati non offuscati quando è attivo un getter di chiave asincrono (un generatore asincrono deve restituire il proprio iteratore in modo sincrono e non può attendere la chiave). Nella modalità predefinita `vmTargetFunctionsMode: 'root'` i salti sono silenziosi (la selezione è automatica); nella [modalità](#vmtargetfunctionsmode) `comment` viene emesso un avviso tramite `ObfuscationResult.getWarnings()` ogni volta che una funzione marcata esplicitamente non può essere virtualizzata — si è rivelata sincrona, oppure è un generatore asincrono sotto un getter di chiave asincrono.
Il getter di chiave asincrono richiede inoltre `vmBytecodeArrayEncoding` con un `vmBytecodeArrayEncodingKeyGetter`.
**Esempio di utilizzo:**```ts
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`
Tipo: `boolean` Predefinito: `false`
Codifica le destinazioni dei salti nel bytecode. Gli offset dei salti vengono calcolati a runtime, nascondendo la struttura del flusso di controllo (`if`/`else`, cicli, ecc.) dall'analisi statica.
### `vmDecoyOpcodes`
Tipo: `boolean` Predefinito: `false`
Aggiunge gestori di opcode fittizi al dispatcher della VM che non vengono mai chiamati. Ad esempio, se la VM usa 20 opcode reali, questo potrebbe aggiungere 30 gestori fittizi, rendendo l'interprete più complesso di quanto sia realmente.
### `vmDeadCodeInjection`
Tipo: `boolean` Predefinito: `false`
Inietta sequenze di bytecode fittizie che non vengono mai eseguite. Queste sembrano istruzioni reali ma vengono saltate durante il runtime, confondendo gli strumenti di analisi che le elaborano.
### `vmMacroOps`
Tipo: `boolean` Predefinito: `false`
Combina sequenze di istruzioni comuni in singoli opcode "macro". Ad esempio, `LOAD + ADD + STORE` potrebbe diventare una singola istruzione `MACRO_ADD_TO_VAR`. Questo rompe il riconoscimento dei pattern e può migliorare le prestazioni.
### `vmDebugProtection`
Tipo: `boolean` Predefinito: `false`
Aggiunge difese anti-debug, anti-analisi e anti-LLM a più livelli al runtime della VM. Per risultati ottimali, consenti `unsafe-eval` nella tua Content Security Policy. Funziona meglio con i target `browser`/`browser-no-eval`.
### `vmSelfDefending`
Tipo: `boolean` Predefinito: `false`
Aggiunge protezione anti-manomissione, anti-hooking e anti-reverse-engineering a più livelli al runtime della VM.
> :warning: Questa opzione forza l'abilitazione di [`vmBytecodeArrayEncoding`](#vmbytecodeArrayEncoding).
Fortemente consigliato l'uso insieme a [`vmDebugProtection`](#vmDebugProtection), [`vmBytecodeArrayEncodingKey`](#vmbytecodeArrayEncodingKey) e [`vmBytecodeArrayEncodingKeyGetter`](#vmbytecodeArrayEncodingKeyGetter).
### `vmDefenseHook`
Tipo: `{ name: string, aliases?: object }` Predefinito: `''`
`vmDefenseHook` accetta un oggetto con due chiavi: **`name`** (obbligatoria) e **`aliases`** (opzionale).
`name` è una **funzione globale definita dalla tua pagina host** che una difesa della VM (`vmDebugProtection` / `vmSelfDefending`) chiama con un oggetto segnale quando rileva un segnale ostile — un debugger o inspector, un browser headless / di automazione, un processo di agente AI di codifica, un dominio non consentito e così via. Usala per segnalare l'evento al tuo backend (ad es. `navigator.sendBeacon`). L'hook è un **semplice sink di telemetria**: il suo valore di ritorno viene ignorato, e un hook mancante o che genera un'eccezione è un no-op silenzioso che non può mai disabilitare una difesa. Per cambiare cosa una difesa *fa* al rilevamento, usa [`vmDefenseReaction`](#vmdefensereaction).
`aliases` rinomina opzionalmente i campi di quell'oggetto segnale — trattato in *Rinomina dei campi del segnale* di seguito.
**L'oggetto segnale.** L'hook riceve un singolo `signal`:
- `source` — il rilevatore specifico che è scattato (vedi la tabella).
- `category` — il gruppo sotto cui riporta: `automation` (browser non umani), `debugger` (un debugger/inspector è attivo), `sandbox` (host strumentato/fittizio), `domain` (violazione del blocco dominio), `tamper` (built-in modificati a runtime) o `integrity` (il codice stesso della VM è stato alterato).
- `score` / `threshold` — quanto fortemente il rilevatore è scattato e il valore che doveva raggiungere; l'hook scatta solo quando `score >= threshold`. La maggior parte dei controlli è tutto-o-niente (un singolo segnale decisivo); `headless` somma diversi segnali di forma del browser, quindi il suo `score` è tipicamente più alto della sua `threshold`.
| `source` | rileva | `category` |
|---|----------------------------------------------------------------------------------|---|
| `integrity` | il codice VM offuscato stesso è stato modificato | `integrity` |
| `node` | codice destinato al browser eseguito sotto Node.js | `debugger` |
| `debugger` | una sessione di debugger o inspector collegata o attiva, o un ambiente di debug | `debugger` |
| `headless` | un browser headless viene usato per eseguire il codice | `automation` |
| `agent` | un agente AI di codifica che esegue il codice | `automation` |
| `timing` | una pausa di esecuzione che suggerisce un breakpoint o un debugger a passi | `debugger` |
| `sandbox` | il codice viene eseguito in una sandbox o in un ambiente host fittizio | `sandbox` |
| `domain` | l'origine della pagina non è nella lista consentita di [`vmDomainLock`](#vmdomainlock) | `domain` |
| `nativeHook` | una funzione nativa built-in è stata sostituita o agganciata | `tamper` |
**Registrazione dell'hook.** Definiscilo come una variabile globale semplice **prima** che il bundle offuscato venga caricato — il runtime della VM e le sue difese vengono eseguiti prima del tuo programma (protetto), quindi molti rilevamenti scattano durante l'avvio:```js
// in your page, before the obfuscated script:
window.__vmDetection = function (signal) { navigator.sendBeacon('/vm-defense', JSON.stringify(signal)); };
```
```js
// obfuscation option:
vmDefenseHook: { name: '__vmDetection' }
```
> Un hook definito *all'interno* del sorgente offuscato viene registrato troppo tardi per intercettare le rilevazioni in fase di avvio e, se viene compilato dalla VM, non può essere raggiunto finché il programma non viene eseguito. In entrambi i casi rimane comunque sicuro (un hook mancante non fa nulla e una protezione anti-rientro previene qualsiasi esecuzione incontrollata), ma per una copertura completa registralo in anticipo. Per proteggere comunque la logica di reporting, mantieni l'hook registrato come buffer di una sola riga (`(window.__vmDet = window.__vmDet || []).push(signal)`) e leggi/invia quel buffer dal tuo codice offuscato.
**Rinomina dei campi del segnale (`aliases`).** I valori predefiniti di `source`/`category` sono nomi descrittivi, quindi chiunque strumenti la callback (o legga l'output) può riconoscere la protezione e quale rilevatore è scattato. `aliases` rinomina i campi del segnale con token opachi a tua scelta, applicati all'interno della VM *prima* che il segnale venga emesso, così quei nomi non compaiono mai nell'output né raggiungono la callback. La tua applicazione conosce la propria mappatura e inoltra i token al tuo backend.
Gli alias sono per campo, mantenendo separate le rinomine di chiave e valore: ogni campo accetta una `key` (il nome della proprietà che riceve la callback); i campi stringa `source` e `category` accettano anche una mappa `values`, mentre `score`/`threshold` sono numerici e accettano solo una `key`. I nomi che puoi mappare (qualsiasi altro viene rifiutato in fase di build):
- **chiavi dei campi** — `source`, `category`, `score`, `threshold`
- **valori di `source`** — `headless`, `agent`, `node`, `debugger`, `timing`, `sandbox`, `domain`, `nativeHook`, `integrity`
- **valori di `category`** — `automation`, `debugger`, `sandbox`, `domain`, `tamper`, `integrity````js
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> }
}
```
Questo è elusione delle impronte, non segretezza — la mappatura può comunque essere dedotta tramite test ripetuti — quindi il suo unico vantaggio è non esporre nomi stabili e autoesplicativi. Le voci non impostate mantengono i loro nomi predefiniti.
> Una stringa semplice (`vmDefenseHook: '__vmDetection'`) è accettata come abbreviazione di `{ name: '__vmDetection' }` ma è **deprecata** — preferisci la forma a oggetto.
### `vmDefenseReaction`
Tipo: `object` Predefinito: `{ automation: 'break', debugger: 'decoy', sandbox: 'decoy', domain: 'break', tamper: 'break', integrity: 'break' }`
Configura come reagisce ciascuna categoria di rilevamento. Non **abilita** nulla — le difese stesse vengono attivate da [`vmSelfDefending`](#vmselfdefending), [`vmDebugProtection`](#vmdebugprotection) e [`vmDomainLock`](#vmdomainlock); questa opzione seleziona solo *come* reagisce una difesa abilitata. La **categoria è l'unità di controllo** — ogni rilevatore in una categoria applica la reazione di quella categoria.
Ogni **categoria** raggruppa i rilevatori che osservano un tipo di condizione ostile. Una categoria reagisce solo quando l'opzione che emette i suoi rilevatori è abilitata:
| Categoria | Abilitata da | Reagisce quando |
|---|---|---|
| `automation` | `vmSelfDefending` o `vmDebugProtection` | Il codice viene guidato da software invece che da una persona: un browser headless o automatizzato, un framework di scraping / test, o un agente AI di coding che esegue la pagina passo dopo passo. |
| `debugger` | `vmDebugProtection` o `vmSelfDefending` | Qualcuno ha un debugger o l'ispettore degli strumenti di sviluppo del browser aperto e sta eseguendo il codice passo dopo passo per comprenderlo. |
| `sandbox` | `vmDebugProtection` | Il codice non viene eseguito affatto in un browser reale — è stato trasferito in un ambiente JavaScript emulato o scriptato per essere eseguito e studiato offline. |
| `domain` | `vmDomainLock` | Il codice viene eseguito su un sito che non hai autorizzato: un host non nella tua allow-list di [`vmDomainLock`](#vmdomainlock) (ad esempio, il tuo bundle copiato sul dominio di qualcun altro). |
| `tamper` | `vmSelfDefending` | L'ambiente JavaScript attorno alla VM è stato modificato per osservarla o dirottarla, come i built-in nativi del browser sostituiti con versioni strumentate. |
| `integrity` | `vmSelfDefending` | Il codice del bundle protetto è stato modificato o patchato dopo la generazione. |
Ogni categoria corrisponde a una o più di [`vmSelfDefending`](#vmselfdefending), [`vmDebugProtection`](#vmdebugprotection) e [`vmDomainLock`](#vmdomainlock); non esiste alcuna categoria al di fuori di queste tre opzioni, e un insieme di reazioni per una categoria la cui opzione è disattivata semplicemente non ha effetto.
Le chiavi sono questi sei nomi di categoria, oppure `default` (un fallback per le categorie non specificate). I valori sono:
- `break` — interrompi immediatamente
- `decoy` — continua a eseguire su uno stato avvelenato, producendo silenziosamente risultati errati
- `none` — non fare nulla localmente (solo telemetria)
I predefiniti per categoria sono mostrati sopra; una categoria che non imposti (o che imposti al suo valore predefinito) usa quel predefinito. `default` raggiunge **ogni** categoria, incluse quelle corrette per costruzione (`integrity`, `tamper`), quindi `{ default: 'none' }` è una build genuinamente non invasiva, solo telemetria:```js
vmDefenseReaction: { default: 'none' } // never break — pair with vmDefenseHook
vmDefenseReaction: { automation: 'none', domain: 'break' } // tolerate automation FPs, still break on a bad domain
```
### `browserEnvironment`
Tipo: `object` Predefinito: `{}`
Dichiara fatti sull'ambiente in cui viene servita la tua build di produzione, così che il codice protetto possa vincolarsi ad essi. Ha effetto solo insieme a [`vmSelfDefending`](#vmselfdefending), e solo per i target `browser` / `browser-no-eval` / `service-worker` — viene rifiutato per `node`, `userscript` e `bytenode`.
Attualmente un campo:
- **`transport`** — lo schema con cui la tua produzione serve il bundle: `'http'` o `'https'`. Con `'https'`, la build lega la propria integrità all'essere servita su HTTPS, quindi una copia che un analista estrae e serve su HTTP semplice (una configurazione comune di reverse engineering locale) non funzionerà correttamente. `'http'` o un campo non impostato non aggiunge alcun vincolo.```js
browserEnvironment: { transport: 'https' }
```
> :warning: Una build dichiarata con `transport: 'https'` funziona correttamente **solo** dove viene effettivamente servita su `https:`. Qualsiasi altro schema la corrompe, quindi dichiarala solo quando ogni contesto che carica la tua build di produzione è HTTPS. Ciò esclude: `http://` semplice (incluso `http://localhost` in sviluppo), `file://` (Electron / Cordova / app impacchettate) e incorporamenti `blob:` / `about:` (un bundle eseguito dentro un iframe `about:blank` o `srcdoc`). Un redirect client-side HTTP→HTTPS mostra comunque prima la pagina HTTP, quindi il bundle non deve essere eseguito prima che il redirect sia completato.
### `vmStatefulOpcodes`
Tipo: `boolean` Default: `false`
Rende i significati degli opcode dipendenti dalla posizione nel bytecode. Ogni posizione ha una diversa mappatura opcode-to-handler derivata da un seed, quindi lo stesso numero di opcode esegue operazioni diverse in posizioni diverse.
### `vmCallContextOpcodes`
Tipo: `boolean` Default: `false`
Rende una funzione protetta dipendente dal punto da cui viene chiamata, così non può essere estratta dal codice ed eseguita o analizzata da sola — si comporta correttamente solo quando viene invocata attraverso i suoi veri punti di chiamata nel programma. Questa opzione influisce sulle prestazioni a runtime.
Attualmente sono supportate solo le seguenti costruzioni:
- dichiarazioni di funzione (`function f() {}`);
- espressioni di funzione e arrow function assegnate a una variabile (`const f = () => {}`);
- metodi privati di istanza (`this.#m()`).
In ogni caso la funzione deve essere sempre raggiunta tramite una chiamata diretta (`f()`, `this.#m()`). Se viene memorizzata in un'altra variabile, passata come argomento o comunque usata come valore, viene lasciata non protetta. Le funzioni asincrone sono supportate; i generatori no.
Questa opzione è sperimentale e potrebbe rompere il tuo codice, quindi testa accuratamente l'output prima di usarla.
### `vmStackEncoding`
Tipo: `boolean` Default: `false`
Cripta i valori sullo stack della VM durante l'esecuzione. I valori vengono codificati quando vengono inseriti e decodificati quando vengono estratti, quindi l'ispezione della memoria mostra dati criptati invece dei valori reali.
Questa opzione influisce pesantemente sulle prestazioni.
### `vmCompactDispatcher`
Tipo: `boolean` Default: `false`
Usa un singolo esecutore VM invece di doppi esecutori (sync + generator). Riduce la dimensione del codice offuscato ma aggiunge circa il 20% di overhead prestazionale su codice con molte ricorsioni.
- `false` (default): doppi esecutori — prestazioni ottimali, output più grande
- `true`: esecutore singolo — output più piccolo, leggermente più lento
### `vmRegisterBased`
Tipo: `boolean` Default: `false`
Passa la VM dal bytecode basato su stack predefinito a un modello di esecuzione basato su registri, che migliora le prestazioni a runtime della VM in alcuni casi di circa il 15-20%, ma aumenta leggermente la dimensione del codice offuscato.
Poiché emette un bytecode e un esecutore strutturalmente diversi, conferisce anche alla VM un'impronta più unica rispetto a quella basata su stack predefinita — usala quando vuoi variare la forma della VM così da renderla meno riconoscibile dall'analisi generica.
Sotto il cofano non si tratta di un compilatore nativo basato su registri — il normale compilatore basato su stack genera comunque il bytecode, che una fase di trasformazione separata riscrive poi in forma basata su registri.
Questa opzione è sperimentale — testa che il tuo codice funzioni bene quando `vmRegisterBased` è abilitato.
### `vmStringArrayBytecodeOnly`
Tipo: `boolean` Default: `false`
Quando abilitata, la string array estrarrà **solo** stringhe dai dati del bytecode — nessun'altra stringa nel codice viene trasformata. Questo forza l'abilitazione di `stringArray` anche se non è impostato esplicitamente.
**Perché usarla:** Estrarre tutte le stringhe runtime della VM in una string array è lento. Questa opzione mira solo al contenuto del bytecode per l'estrazione nella string array, migliorando le prestazioni pur proteggendo le costanti del bytecode.
- Quando `vmBytecodeArrayEncoding: false` — vengono estratte le stringhe nei pool di costanti del bytecode (array `c`)
- Quando `vmBytecodeArrayEncoding: true` — vengono estratte le stringhe di bytecode codificate in base64 di livello superiore
- `stringArrayThreshold` controlla comunque quale percentuale di quelle stringhe di bytecode viene estratta
### `vmDomainLock`
Tipo: `string[]` Default: `[]`
##### :warning: Questa opzione non funziona con `target: 'node'`, `target: 'service-worker'` o `target: 'bytenode'`
Limita il codice offuscato a domini e/o sottodomini specifici, ed è molto più difficile da individuare e rimuovere rispetto a `domainLock`.
Se il codice sorgente non viene eseguito sui domini specificati da questa opzione, il browser verrà reindirizzato all'URL passato a [`vmDomainLockRedirectUrl`](#vmdomainlockredirecturl), e ulteriori chiamate protette restituiranno risultati errati anche se il redirect viene soppresso.
##### Più domini e sottodomini
È possibile bloccare il codice su più di un dominio o sottodominio. Ad esempio, per bloccarlo così che il codice venga eseguito solo su **www.example.com** aggiungi `www.example.com`. Per farlo funzionare sul dominio radice inclusi eventuali sottodomini (`example.com`, `sub.example.com`), usa `.example.com`.
### `vmDomainLockRedirectUrl`
Tipo: `string` Default: `about:blank`
##### :warning: Questa opzione non funziona con `target: 'node'`, `target: 'service-worker'` o `target: 'bytenode'`
Consente al browser di essere reindirizzato a un URL passato se il codice sorgente non viene eseguito sui domini specificati da [`vmDomainLock`](#vmdomainlock).
### `strictMode`
Tipo: `boolean | null` Default: `null`
Consente di specificare come l'offuscatore deve trattare il codice riguardo alla modalità strict di JavaScript.
Valori disponibili:
* `null` (default) — rileva automaticamente la modalità strict dal codice. Se il codice ha una direttiva esplicita `'use strict'`, sintassi di moduli ES o metodi di classe, viene trattato come modalità strict. Altrimenti, viene assunta la modalità sloppy.
* `true` — forza il trattamento in modalità strict per tutto il codice, anche senza direttiva esplicita `'use strict'`. Usalo quando il tuo codice verrà eseguito in un contesto di modalità strict (ad es., in moduli ES, bundler o framework moderni).
* `false` — solo gli indicatori espliciti di modalità strict (`'use strict'`, moduli ES, metodi di classe) vengono trattati come strict. L'ereditarietà dello scope genitore si applica comunque secondo la specifica JS.
### `parseHtml`
Tipo: `boolean` Default: `false`
Abilita l'offuscamento di JavaScript all'interno dei tag HTML `<script>`.
Quando abilitata, l'offuscatore:
- Rileva automaticamente se l'input è HTML (controllando la presenza di tag `<!DOCTYPE>`, `<html>`, `<head>`, `<body>` o `<script>`)
- Estrae JavaScript dai tag `<script>` contrassegnati con l'attributo `data-javascript-obfuscator`
- Offusca ogni script contrassegnato singolarmente preservando la struttura HTML
- Inietta il codice offuscato nelle posizioni originali
**Importante:** Solo gli script con l'attributo `data-javascript-obfuscator` vengono offuscati. Ogni script contrassegnato viene offuscato singolarmente e indipendentemente. Ciò significa:
- Il codice all'interno dei tag script contrassegnati **deve essere isolato** — non deve fare riferimento a variabili, funzioni o classi definite in altri tag script contrassegnati
- Gli script non contrassegnati possono comunque accedere ai globali definiti dagli script contrassegnati (tramite dichiarazioni `var` o assegnazioni esplicite a `globalThis`)
- Questo ti dà un controllo esplicito su quali script proteggere
**Offuscati (devono avere l'attributo `data-javascript-obfuscator`):**
- `<script data-javascript-obfuscator>` — script regolari
- `<script type="text/javascript" data-javascript-obfuscator>` — script con tipo esplicito
- Script con qualsiasi attributo aggiuntivo (`id`, `class`, altri `data-*`, ecc.)
**Saltati (lasciati invariati):**
- Script senza attributo `data-javascript-obfuscator`
- `<script type="module">` — moduli ES (anche con l'attributo)
- `<script src="...">` — script esterni (anche con l'attributo)
- Tag script vuoti
**Nota:** Le source map non vengono generate quando `parseHtml` è abilitato, poiché non verrebbero mappate correttamente sull'output HTML.
Esempio:```ts
// 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
```
### `randomIdentifiersPrefix`
Tipo: `boolean` Default: `false`
Aggiunge un prefisso casuale basato su seed (6 caratteri alfanumerici) a tutti gli identificatori globali. Usa questa opzione per evitare collisioni tra bundle offuscati separatamente che vengono caricati nello stesso scope globale — elimina la necessità di scegliere manualmente un `identifiersPrefix` univoco per ogni bundle.
- Il valore casuale deriva dall'opzione `seed` e dall'hash del codice sorgente, quindi build riproducibili con lo stesso seed producono lo stesso prefisso.
- Se combinato con `identifiersPrefix`, i caratteri casuali vengono aggiunti al prefisso fornito dall'utente (es. `myApp` + casuale `aBc123` → `myAppaBc123`).
- Se combinato con `vmObfuscation`, il valore casuale sostituisce il prefisso predefinito `vm` — la casualità garantisce già l'unicità.
## Domande frequenti
### Quali versioni di JavaScript sono supportate?
`es3`, `es5`, `es2015`, `es2016`, `es2017`, `es2018`, `es2019` e parzialmente `es2020`
### Voglio usare una funzionalità descritta nel `README.md` ma non funziona!
Il README sul branch master potrebbe non corrispondere a quello dell'ultima release stabile.
### Perché il comando CLI non funziona?
Prova a eseguire il comando `npm link javascript-obfuscator` oppure installalo globalmente con `npm i -g javascript-obfuscator`
### Versione online?
[obfuscator.io](https://obfuscator.io)
### Supporto JSX?
No. Il supporto JSX non è previsto.
### Come cambiare il tipo di variabili dei nodi inseriti (`var`, `let` o `const`)?
Vedi: [`Tipo di variabili`](#kind-of-variables)
### Perché ho ottenuto un valore `null` invece di un numero `BigInt`?
L'offuscamento di `BigInt` funziona correttamente solo in ambienti che supportano i valori `BigInt`. Vedi [specifica ESTree](https://github.com/estree/estree/blob/master/es2020.md#bigintliteral)
### Ho abilitato l'opzione `renameProperties` e il mio codice si è rotto! Cosa fare?
Prova l'opzione `renamePropertiesMode: 'safe'`; se ancora non funziona, disabilita semplicemente questa opzione.
## Sponsor GitHub
<a href="https://github.com/microsoft" target="_blank"><img src="https://avatars.githubusercontent.com/u/6154722?s=200&v=4"></a>
## Sostenitori
Sostienici con una donazione mensile e aiutaci a continuare le nostre attività. [[Diventa un sostenitore](https://opencollective.com/javascript-obfuscator#backer)]
<a href="https://opencollective.com/javascript-obfuscator/backer/0/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/backer/0/avatar.svg"></a>
<a href="https://opencollective.com/javascript-obfuscator/backer/1/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/backer/1/avatar.svg"></a>
<a href="https://opencollective.com/javascript-obfuscator/backer/2/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/backer/2/avatar.svg"></a>
<a href="https://opencollective.com/javascript-obfuscator/backer/3/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/backer/3/avatar.svg"></a>
<a href="https://opencollective.com/javascript-obfuscator/backer/4/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/backer/4/avatar.svg"></a>
<a href="https://opencollective.com/javascript-obfuscator/backer/5/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/backer/5/avatar.svg"></a>
<a href="https://opencollective.com/javascript-obfuscator/backer/6/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/backer/6/avatar.svg"></a>
<a href="https://opencollective.com/javascript-obfuscator/backer/7/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/backer/7/avatar.svg"></a>
<a href="https://opencollective.com/javascript-obfuscator/backer/8/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/backer/8/avatar.svg"></a>
<a href="https://opencollective.com/javascript-obfuscator/backer/9/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/backer/9/avatar.svg"></a>
<a href="https://opencollective.com/javascript-obfuscator/backer/10/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/backer/10/avatar.svg"></a>
<a href="https://opencollective.com/javascript-obfuscator/backer/11/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/backer/11/avatar.svg"></a>
<a href="https://opencollective.com/javascript-obfuscator/backer/12/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/backer/12/avatar.svg"></a>
<a href="https://opencollective.com/javascript-obfuscator/backer/13/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/backer/13/avatar.svg"></a>
<a href="https://opencollective.com/javascript-obfuscator/backer/14/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/backer/14/avatar.svg"></a>
<a href="https://opencollective.com/javascript-obfuscator/backer/15/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/backer/15/avatar.svg"></a>
<a href="https://opencollective.com/javascript-obfuscator/backer/16/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/backer/16/avatar.svg"></a>
<a href="https://opencollective.com/javascript-obfuscator/backer/17/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/backer/17/avatar.svg"></a>
<a href="https://opencollective.com/javascript-obfuscator/backer/18/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/backer/18/avatar.svg"></a>
<a href="https://opencollective.com/javascript-obfuscator/backer/19/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/backer/19/avatar.svg"></a>
<a href="https://opencollective.com/javascript-obfuscator/backer/20/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/backer/20/avatar.svg"></a>
<a href="https://opencollective.com/javascript-obfuscator/backer/21/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/backer/21/avatar.svg"></a>
<a href="https://opencollective.com/javascript-obfuscator/backer/22/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/backer/22/avatar.svg"></a>
<a href="https://opencollective.com/javascript-obfuscator/backer/23/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/backer/23/avatar.svg"></a>
<a href="https://opencollective.com/javascript-obfuscator/backer/24/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/backer/24/avatar.svg"></a>
<a href="https://opencollective.com/javascript-obfuscator/backer/25/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/backer/25/avatar.svg"></a>
<a href="https://opencollective.com/javascript-obfuscator/backer/26/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/backer/26/avatar.svg"></a>
<a href="https://opencollective.com/javascript-obfuscator/backer/27/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/backer/27/avatar.svg"></a>
<a href="https://opencollective.com/javascript-obfuscator/backer/28/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/backer/28/avatar.svg"></a>
<a href="https://opencollective.com/javascript-obfuscator/backer/29/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/backer/29/avatar.svg"></a>
## Sponsor Open Collective
Diventa uno sponsor e ottieni il tuo logo nel nostro README su Github con un link al tuo sito.
<a href="https://opencollective.com/javascript-obfuscator/sponsor/0/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/sponsor/0/avatar.svg"></a>
<a href="https://opencollective.com/javascript-obfuscator/sponsor/1/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/sponsor/1/avatar.svg"></a>
<a href="https://opencollective.com/javascript-obfuscator/sponsor/2/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/sponsor/2/avatar.svg"></a>
<a href="https://opencollective.com/javascript-obfuscator/sponsor/3/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/sponsor/3/avatar.svg"></a>
<a href="https://opencollective.com/javascript-obfuscator/sponsor/4/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/sponsor/4/avatar.svg"></a>
<a href="https://opencollective.com/javascript-obfuscator/sponsor/5/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/sponsor/5/avatar.svg"></a>
<a href="https://opencollective.com/javascript-obfuscator/sponsor/6/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/sponsor/6/avatar.svg"></a>
<a href="https://opencollective.com/javascript-obfuscator/sponsor/7/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/sponsor/7/avatar.svg"></a>
<a href="https://opencollective.com/javascript-obfuscator/sponsor/8/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/sponsor/8/avatar.svg"></a>
<a href="https://opencollective.com/javascript-obfuscator/sponsor/9/website" target="_blank"><img src="https://opencollective.com/javascript-obfuscator/sponsor/9/avatar.svg"></a>
## Licenza
[](https://app.fossa.io/projects/git%2Bgithub.com%2Fjavascript-obfuscator%2Fjavascript-obfuscator?ref=badge_large)
Copyright (C) 2016-2026 [Timofei Kachalov](http://github.com/sanex3339).
La ridistribuzione e l'uso in forma sorgente e binaria, con o senza
modifiche, sono consentiti a condizione che siano soddisfatti i seguenti requisiti:
* Le ridistribuzioni del codice sorgente devono conservare il copyright
sopra indicato, questo elenco di condizioni e il seguente disclaimer.
* Le ridistribuzioni in forma binaria devono riprodurre il copyright
sopra indicato, questo elenco di condizioni e il seguente disclaimer nella
documentazione e/o in altri materiali forniti con la distribuzione.
QUESTO SOFTWARE È FORNITO DAI TITOLARI DEL COPYRIGHT E DAI CONTRIBUTORI "COSÌ COM'È"
E QUALSIASI GARANZIA ESPRESSA O IMPLICITA, INCLUSI, MA NON LIMITATI A, LE
GARANZIE IMPLICITE DI COMMERCIABILITÀ E IDONEITÀ PER UNO SCOPO PARTICOLARE
SONO DECLINATE. IN NESSUN CASO <TITOLARE DEL COPYRIGHT> SARÀ RESPONSABILE PER
QUALSIASI DANNO DIRETTO, INDIRETTO, INCIDENTALE, SPECIALE, ESEMPLARE O CONSEQUENZIALE
(INCLUSI, MA NON LIMITATI A, ACQUISIZIONE DI BENI O SERVIZI SOSTITUTIVI;
PERDITA DI UTILIZZO, DATI O PROFITTI; O INTERRUZIONE DELL'ATTIVITÀ) QUALUNQUE SIA
LA CAUSA E SU QUALSIASI TEORIA DI RESPONSABILITÀ, SIA CONTRATTUALE, RESPONSABILITÀ
OGGETTIVA O ILLECITO (INCLUSA LA NEGLIGENZA O ALTRO) DERIVANTE IN QUALSIASI MODO DALL'USO DI
QUESTO SOFTWARE, ANCHE SE AVVISATI DELLA POSSIBILITÀ DI TALI DANNI.