UNPKG

js-confuser

Version:

JavaScript Obfuscation Tool.

260 lines (237 loc) 6.34 kB
import { ok } from "assert"; import { ObfuscateOptions } from "./options"; import presets from "./presets"; const validProperties = new Set([ "preset", "target", "compact", "hexadecimalNumbers", "minify", "renameVariables", "renameGlobals", "renameLabels", "identifierGenerator", "controlFlowFlattening", "globalConcealing", "stringCompression", "stringConcealing", "stringEncoding", "stringSplitting", "duplicateLiteralsRemoval", "dispatcher", "rgf", "objectExtraction", "flatten", "deadCode", "calculator", "lock", "movedDeclarations", "opaquePredicates", "shuffle", "variableMasking", "verbose", "globalVariables", "debugComments", "preserveFunctionLength", "astScrambler", "customStringEncodings", "functionOutlining", "pack", ]); const validLockProperties = new Set([ "selfDefending", "antiDebug", "tamperProtection", "startDate", "endDate", "domainLock", "integrity", "countermeasures", "customLocks", ]); export function validateOptions(options: ObfuscateOptions) { if (!options || Object.keys(options).length <= 1) { /** * Give a welcoming introduction to those who skipped the documentation. */ var line = `You provided zero obfuscation options. By default everything is disabled.\nYou can use a preset with:\n\n> {target: '${ options.target || "node" }', preset: 'high' | 'medium' | 'low'}.\n\n\nView all settings here:\nhttps://github.com/MichaelXF/js-confuser#options`; throw new Error( `\n\n` + line .split("\n") .map((x) => `\t${x}`) .join("\n") + `\n\n` ); } ok(options, "options cannot be null"); ok( options.target, "Missing options.target option (required, must one the following: 'browser' or 'node')" ); ok( ["browser", "node"].includes(options.target), `'${options.target}' is not a valid target mode` ); Object.keys(options).forEach((key) => { if (!validProperties.has(key)) { throw new TypeError("Invalid option: '" + key + "'"); } }); if (options.lock) { ok(typeof options.lock === "object", "options.lock must be an object"); Object.keys(options.lock).forEach((key) => { if (!validLockProperties.has(key)) { throw new TypeError("Invalid lock option: '" + key + "'"); } }); // Validate domain-lock option if ( options.lock.domainLock && typeof options.lock.domainLock !== "undefined" ) { ok(Array.isArray(options.lock.domainLock), "domainLock must be an array"); } // Validate start-date option if ( typeof options.lock.startDate !== "undefined" && options.lock.startDate ) { ok( typeof options.lock.startDate === "number" || options.lock.startDate instanceof Date, "startDate must be Date object or number" ); } // Validate end-date option if (typeof options.lock.endDate !== "undefined" && options.lock.endDate) { ok( typeof options.lock.endDate === "number" || options.lock.endDate instanceof Date, "endDate must be Date object or number" ); } } if (options.preset) { if (!presets[options.preset]) { throw new TypeError("Unknown preset of '" + options.preset + "'"); } } } /** * Sets the default values and validates the configuration. */ export function applyDefaultsToOptions( options: ObfuscateOptions ): ObfuscateOptions { if (options.preset) { // Clone and allow overriding options = Object.assign({}, presets[options.preset], options); } if (!options.hasOwnProperty("compact")) { options.compact = true; // Compact is on by default } if (!options.hasOwnProperty("renameGlobals")) { options.renameGlobals = true; // RenameGlobals is on by default } if (!options.hasOwnProperty("preserveFunctionLength")) { options.preserveFunctionLength = true; // preserveFunctionLength is on by default } if (!options.hasOwnProperty("renameLabels")) { options.renameLabels = true; // RenameLabels is on by default } if (options.lock) { ok(typeof options.lock === "object", "options.lock must be an object"); if (options.lock.selfDefending) { options.compact = true; // self defending forcibly enables this } if (!options.lock.customLocks) { options.lock.customLocks = []; } // Convert 'startDate' and 'endDate' to Dates if (typeof options.lock.startDate === "number") { options.lock.startDate = new Date(options.lock.startDate); } if (typeof options.lock.endDate === "number") { options.lock.endDate = new Date(options.lock.endDate); } } // options.globalVariables outlines generic globals that should be present in the execution context if (!options.hasOwnProperty("globalVariables")) { options.globalVariables = new Set([]); if (options.target == "browser") { // browser [ "window", "document", "postMessage", "alert", "confirm", "location", ].forEach((x) => options.globalVariables.add(x)); } else { // node [ "global", "Buffer", "require", "process", "exports", "module", "__dirname", "__filename", ].forEach((x) => options.globalVariables.add(x)); } [ "globalThis", "console", "parseInt", "parseFloat", "Math", "JSON", "RegExp", "Promise", "String", "Boolean", "Function", "Object", "Array", "Proxy", "Error", "TypeError", "ReferenceError", "RangeError", "EvalError", "setTimeout", "clearTimeout", "setInterval", "clearInterval", "setImmediate", "clearImmediate", "queueMicrotask", "isNaN", "isFinite", "Set", "Map", "WeakSet", "WeakMap", "Symbol", "TextDecoder", "TextEncoder", "Uint8Array", "Uint16Array", "Uint32Array", "Int8Array", "Int16Array", "Int32Array", "ArrayBuffer", "btoa", "atob", "unescape", "encodeURIComponent", ].forEach((x) => options.globalVariables.add(x)); } return options; }