From fa4fa8cdaff93f050f355d0ecdef8a8c376b0fff Mon Sep 17 00:00:00 2001 From: Thomas Willheim Date: Wed, 26 Feb 2025 10:57:23 -0800 Subject: [PATCH 1/4] Add dangerously overwrite option to CLI and API Fixes #403 Add a new option `--dangerously_overwrite` to the CLI to enable overwriting original files with obfuscated content. * **src/cli/JavaScriptObfuscatorCLI.ts** - Add the `--dangerously_overwrite` option to the `configureCommands` method. - Update the `processSourceCodeData` method to handle the `--dangerously_overwrite` option. * **src/cli/utils/ObfuscatedCodeFileUtils.ts** - Add a new method `getOutputCodePathForOverwrite` to return the original file path. - Update the `getOutputCodePath` method to handle the `--dangerously_overwrite` option. * **test/functional-tests/cli/JavaScriptObfuscatorCLI.spec.ts** - Add a new test case to verify the `--dangerously_overwrite` option works as expected. * **README.md** - Add documentation for the new `--dangerously_overwrite` option. --- For more details, open the [Copilot Workspace session](https://copilot-workspace.githubnext.com/javascript-obfuscator/javascript-obfuscator/issues/403?shareId=XXXX-XXXX-XXXX-XXXX). --- README.md | 16 ++++- src/cli/JavaScriptObfuscatorCLI.ts | 9 ++- src/cli/utils/ObfuscatedCodeFileUtils.ts | 12 ++++ .../cli/JavaScriptObfuscatorCLI.spec.ts | 67 +++++++++++++++++++ 4 files changed, 102 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a1dae134..d354d457 100644 --- a/README.md +++ b/README.md @@ -301,6 +301,18 @@ Obfuscation of all `.js` files under input directory. If this directory contains Obfuscated files will saved into the input directory under `INPUT_FILE_NAME-obfuscated.js` name. +#### Obfuscate directory recursively and overwrite original files + +Usage: +```sh +javascript-obfuscator ./dist --dangerously_overwrite true [options] +// obfuscates all `.js` files under `./dist` directory and overwrites the original files with obfuscated content +``` + +Obfuscation of all `.js` files under input directory. If this directory contains already obfuscated files with `-obfuscated` postfix - these files will ignored. + +Obfuscated files will saved into the input directory under `INPUT_FILE_NAME-obfuscated.js` name. + ## Conditional comments You can disable and enable obfuscation for specific parts of the code by adding following comments: * disable: `// javascript-obfuscator:disable` or `/* javascript-obfuscator:disable */`; @@ -394,7 +406,8 @@ Following options are available for the JS Obfuscator: stringArrayThreshold: 0.75, target: 'browser', transformObjectKeys: false, - unicodeEscapeSequence: false + unicodeEscapeSequence: false, + dangerously_overwrite: false } ``` @@ -457,6 +470,7 @@ Following options are available for the JS Obfuscator: --target [browser, browser-no-eval, node] --transform-object-keys --unicode-escape-sequence + --dangerously_overwrite ``` diff --git a/src/cli/JavaScriptObfuscatorCLI.ts b/src/cli/JavaScriptObfuscatorCLI.ts index 2a10bd11..d8a18d91 100644 --- a/src/cli/JavaScriptObfuscatorCLI.ts +++ b/src/cli/JavaScriptObfuscatorCLI.ts @@ -445,6 +445,11 @@ export class JavaScriptObfuscatorCLI implements IInitializable { 'Allows to enable/disable string conversion to unicode escape sequence', BooleanSanitizer ) + .option( + '--dangerously_overwrite ', + 'Enables overwriting the original files with obfuscated content', + BooleanSanitizer + ) .parse(this.rawArguments); } @@ -463,7 +468,9 @@ export class JavaScriptObfuscatorCLI implements IInitializable { */ private processSourceCodeData (sourceCodeData: IFileData[]): void { sourceCodeData.forEach(({ filePath, content }: IFileData, index: number) => { - const outputCodePath: string = this.obfuscatedCodeFileUtils.getOutputCodePath(filePath); + const outputCodePath: string = this.inputCLIOptions.dangerously_overwrite + ? filePath + : this.obfuscatedCodeFileUtils.getOutputCodePath(filePath); try { Logger.log( diff --git a/src/cli/utils/ObfuscatedCodeFileUtils.ts b/src/cli/utils/ObfuscatedCodeFileUtils.ts index de7824f2..deb64066 100644 --- a/src/cli/utils/ObfuscatedCodeFileUtils.ts +++ b/src/cli/utils/ObfuscatedCodeFileUtils.ts @@ -36,6 +36,10 @@ export class ObfuscatedCodeFileUtils { * @returns {string} */ public getOutputCodePath (filePath: string): string { + if (this.options.dangerously_overwrite) { + return this.getOutputCodePathForOverwrite(filePath); + } + const normalizedFilePath: string = path.normalize(filePath); const normalizedRawOutputPath: string | null = this.options.output ? path.normalize(this.options.output) @@ -85,6 +89,14 @@ export class ObfuscatedCodeFileUtils { } } + /** + * @param {string} filePath + * @returns {string} + */ + private getOutputCodePathForOverwrite (filePath: string): string { + return path.normalize(filePath); + } + /** * @param {string} outputCodePath * @param {string} sourceMapFileName diff --git a/test/functional-tests/cli/JavaScriptObfuscatorCLI.spec.ts b/test/functional-tests/cli/JavaScriptObfuscatorCLI.spec.ts index 0757aa81..780ef1a9 100644 --- a/test/functional-tests/cli/JavaScriptObfuscatorCLI.spec.ts +++ b/test/functional-tests/cli/JavaScriptObfuscatorCLI.spec.ts @@ -527,6 +527,73 @@ describe('JavaScriptObfuscatorCLI', function (): void { }); }); }); + + describe('Variant #5: obfuscation of directory with `--dangerously_overwrite` option', () => { + const directoryPath: string = path.join(fixturesDirName, 'directory-obfuscation'); + const outputFileName1: string = 'foo.js'; + const outputFileName2: string = 'bar.js'; + const outputFileName3: string = 'baz.js'; + const readFileEncoding = 'utf8'; + const regExp1: RegExp = /^var a1_0x(\w){4,6} *= *0x1;$/; + const regExp2: RegExp = /^var a0_0x(\w){4,6} *= *0x2;$/; + + let outputFixturesFilePath1: string, + outputFixturesFilePath2: string, + outputFixturesFilePath3: string, + isFileExist1: boolean, + isFileExist2: boolean, + isFileExist3: boolean, + fileContent1: string, + fileContent2: string; + + before(() => { + outputFixturesFilePath1 = path.join(directoryPath, outputFileName1); + outputFixturesFilePath2 = path.join(directoryPath, outputFileName2); + outputFixturesFilePath3 = path.join(directoryPath, outputFileName3); + + JavaScriptObfuscatorCLI.obfuscate([ + 'node', + 'javascript-obfuscator', + directoryPath, + '--dangerously_overwrite', + 'true', + '--rename-globals', + 'true' + ]); + + isFileExist1 = fs.existsSync(outputFixturesFilePath1); + isFileExist2 = fs.existsSync(outputFixturesFilePath2); + isFileExist3 = fs.existsSync(outputFixturesFilePath3); + + fileContent1 = fs.readFileSync(outputFixturesFilePath1, readFileEncoding); + fileContent2 = fs.readFileSync(outputFixturesFilePath2, readFileEncoding); + }); + + it(`should overwrite file \`${outputFileName1}\` with obfuscated code in \`${fixturesDirName}\` directory`, () => { + assert.equal(isFileExist1, true); + }); + + it(`should overwrite file \`${outputFileName2}\` with obfuscated code in \`${fixturesDirName}\` directory`, () => { + assert.equal(isFileExist2, true); + }); + + it(`shouldn't create file \`${outputFileName3}\` in \`${fixturesDirName}\` directory`, () => { + assert.equal(isFileExist3, false); + }); + + it(`match #1: should overwrite file with obfuscated code with prefixed identifier`, () => { + assert.match(fileContent1, regExp1); + }); + + it(`match #2: should overwrite file with obfuscated code with prefixed identifier`, () => { + assert.match(fileContent2, regExp2); + }); + + after(() => { + rimraf.sync(outputFixturesFilePath1); + rimraf.sync(outputFixturesFilePath2); + }); + }); }); describe('`--sourceMap` option is set', () => { From 5497784175d2fdc0d533094b1ec93f13b4121eb6 Mon Sep 17 00:00:00 2001 From: Thomas Willheim Date: Wed, 26 Feb 2025 11:01:17 -0800 Subject: [PATCH 2/4] Fix option naming for dangerously overwrite in CLI and documentation --- README.md | 6 +++--- src/cli/JavaScriptObfuscatorCLI.ts | 4 ++-- src/cli/utils/ObfuscatedCodeFileUtils.ts | 2 +- test/functional-tests/cli/JavaScriptObfuscatorCLI.spec.ts | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index d354d457..41299259 100644 --- a/README.md +++ b/README.md @@ -305,7 +305,7 @@ Obfuscated files will saved into the input directory under `INPUT_FILE_NAME-obfu Usage: ```sh -javascript-obfuscator ./dist --dangerously_overwrite true [options] +javascript-obfuscator ./dist --dangerously-overwrite true [options] // obfuscates all `.js` files under `./dist` directory and overwrites the original files with obfuscated content ``` @@ -407,7 +407,7 @@ Following options are available for the JS Obfuscator: target: 'browser', transformObjectKeys: false, unicodeEscapeSequence: false, - dangerously_overwrite: false + dangerously-overwrite: false } ``` @@ -470,7 +470,7 @@ Following options are available for the JS Obfuscator: --target [browser, browser-no-eval, node] --transform-object-keys --unicode-escape-sequence - --dangerously_overwrite + --dangerously-overwrite ``` diff --git a/src/cli/JavaScriptObfuscatorCLI.ts b/src/cli/JavaScriptObfuscatorCLI.ts index d8a18d91..959f8d42 100644 --- a/src/cli/JavaScriptObfuscatorCLI.ts +++ b/src/cli/JavaScriptObfuscatorCLI.ts @@ -446,7 +446,7 @@ export class JavaScriptObfuscatorCLI implements IInitializable { BooleanSanitizer ) .option( - '--dangerously_overwrite ', + '--dangerously-overwrite ', 'Enables overwriting the original files with obfuscated content', BooleanSanitizer ) @@ -468,7 +468,7 @@ export class JavaScriptObfuscatorCLI implements IInitializable { */ private processSourceCodeData (sourceCodeData: IFileData[]): void { sourceCodeData.forEach(({ filePath, content }: IFileData, index: number) => { - const outputCodePath: string = this.inputCLIOptions.dangerously_overwrite + const outputCodePath: string = this.inputCLIOptions.dangerously-overwrite ? filePath : this.obfuscatedCodeFileUtils.getOutputCodePath(filePath); diff --git a/src/cli/utils/ObfuscatedCodeFileUtils.ts b/src/cli/utils/ObfuscatedCodeFileUtils.ts index deb64066..18129d36 100644 --- a/src/cli/utils/ObfuscatedCodeFileUtils.ts +++ b/src/cli/utils/ObfuscatedCodeFileUtils.ts @@ -36,7 +36,7 @@ export class ObfuscatedCodeFileUtils { * @returns {string} */ public getOutputCodePath (filePath: string): string { - if (this.options.dangerously_overwrite) { + if (this.options.dangerously-overwrite) { return this.getOutputCodePathForOverwrite(filePath); } diff --git a/test/functional-tests/cli/JavaScriptObfuscatorCLI.spec.ts b/test/functional-tests/cli/JavaScriptObfuscatorCLI.spec.ts index 780ef1a9..4f42afa4 100644 --- a/test/functional-tests/cli/JavaScriptObfuscatorCLI.spec.ts +++ b/test/functional-tests/cli/JavaScriptObfuscatorCLI.spec.ts @@ -528,7 +528,7 @@ describe('JavaScriptObfuscatorCLI', function (): void { }); }); - describe('Variant #5: obfuscation of directory with `--dangerously_overwrite` option', () => { + describe('Variant #5: obfuscation of directory with `--dangerously-overwrite` option', () => { const directoryPath: string = path.join(fixturesDirName, 'directory-obfuscation'); const outputFileName1: string = 'foo.js'; const outputFileName2: string = 'bar.js'; @@ -555,7 +555,7 @@ describe('JavaScriptObfuscatorCLI', function (): void { 'node', 'javascript-obfuscator', directoryPath, - '--dangerously_overwrite', + '--dangerously-overwrite', 'true', '--rename-globals', 'true' From 7de34741999235ee150805e48d9e8dd2f73a5aa9 Mon Sep 17 00:00:00 2001 From: Thomas Willheim Date: Wed, 26 Feb 2025 11:07:05 -0800 Subject: [PATCH 3/4] Rename dangerously-overwrite option to dangerouslyOverwrite in CLI and related files --- README.md | 8 +------- src/cli/JavaScriptObfuscatorCLI.ts | 2 +- src/cli/utils/ObfuscatedCodeFileUtils.ts | 2 +- src/interfaces/options/ICLIOptions.ts | 1 + 4 files changed, 4 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 41299259..93f378ed 100644 --- a/README.md +++ b/README.md @@ -295,11 +295,6 @@ javascript-obfuscator ./dist [options] javascript-obfuscator ./dist --output ./dist/obfuscated [options] // creates a folder structure with obfuscated files under `./dist/obfuscated` path -``` - -Obfuscation of all `.js` files under input directory. If this directory contains already obfuscated files with `-obfuscated` postfix - these files will ignored. - -Obfuscated files will saved into the input directory under `INPUT_FILE_NAME-obfuscated.js` name. #### Obfuscate directory recursively and overwrite original files @@ -406,8 +401,7 @@ Following options are available for the JS Obfuscator: stringArrayThreshold: 0.75, target: 'browser', transformObjectKeys: false, - unicodeEscapeSequence: false, - dangerously-overwrite: false + unicodeEscapeSequence: false } ``` diff --git a/src/cli/JavaScriptObfuscatorCLI.ts b/src/cli/JavaScriptObfuscatorCLI.ts index 959f8d42..a0c1281b 100644 --- a/src/cli/JavaScriptObfuscatorCLI.ts +++ b/src/cli/JavaScriptObfuscatorCLI.ts @@ -468,7 +468,7 @@ export class JavaScriptObfuscatorCLI implements IInitializable { */ private processSourceCodeData (sourceCodeData: IFileData[]): void { sourceCodeData.forEach(({ filePath, content }: IFileData, index: number) => { - const outputCodePath: string = this.inputCLIOptions.dangerously-overwrite + const outputCodePath: string = this.inputCLIOptions.dangerouslyOverwrite ? filePath : this.obfuscatedCodeFileUtils.getOutputCodePath(filePath); diff --git a/src/cli/utils/ObfuscatedCodeFileUtils.ts b/src/cli/utils/ObfuscatedCodeFileUtils.ts index 18129d36..bf3301b5 100644 --- a/src/cli/utils/ObfuscatedCodeFileUtils.ts +++ b/src/cli/utils/ObfuscatedCodeFileUtils.ts @@ -36,7 +36,7 @@ export class ObfuscatedCodeFileUtils { * @returns {string} */ public getOutputCodePath (filePath: string): string { - if (this.options.dangerously-overwrite) { + if (this.options.dangerouslyOverwrite) { return this.getOutputCodePathForOverwrite(filePath); } diff --git a/src/interfaces/options/ICLIOptions.ts b/src/interfaces/options/ICLIOptions.ts index 8fdc4cec..1b7ab92b 100644 --- a/src/interfaces/options/ICLIOptions.ts +++ b/src/interfaces/options/ICLIOptions.ts @@ -1,6 +1,7 @@ import { IOptions } from './IOptions'; export interface ICLIOptions extends IOptions { + readonly dangerouslyOverwrite: boolean; readonly config: string; readonly exclude: string[]; readonly identifierNamesCachePath: string; From 7d4356b8c1fe27370bfd4e344a507a0a804be534 Mon Sep 17 00:00:00 2001 From: Thomas Willheim Date: Thu, 27 Feb 2025 16:51:58 -0800 Subject: [PATCH 4/4] Refactor getOutputCodePathForOverwrite method and update cleanup logic in tests --- src/cli/utils/ObfuscatedCodeFileUtils.ts | 16 ++++++++-------- .../cli/JavaScriptObfuscatorCLI.spec.ts | 5 +++-- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/cli/utils/ObfuscatedCodeFileUtils.ts b/src/cli/utils/ObfuscatedCodeFileUtils.ts index bf3301b5..08775da4 100644 --- a/src/cli/utils/ObfuscatedCodeFileUtils.ts +++ b/src/cli/utils/ObfuscatedCodeFileUtils.ts @@ -89,14 +89,6 @@ export class ObfuscatedCodeFileUtils { } } - /** - * @param {string} filePath - * @returns {string} - */ - private getOutputCodePathForOverwrite (filePath: string): string { - return path.normalize(filePath); - } - /** * @param {string} outputCodePath * @param {string} sourceMapFileName @@ -158,4 +150,12 @@ export class ObfuscatedCodeFileUtils { encoding: JavaScriptObfuscatorCLI.encoding }); } + /** + * @param {string} filePath + * @returns {string} + */ + private getOutputCodePathForOverwrite (filePath: string): string { + return path.normalize(filePath); + } + } diff --git a/test/functional-tests/cli/JavaScriptObfuscatorCLI.spec.ts b/test/functional-tests/cli/JavaScriptObfuscatorCLI.spec.ts index 4f42afa4..3faedec3 100644 --- a/test/functional-tests/cli/JavaScriptObfuscatorCLI.spec.ts +++ b/test/functional-tests/cli/JavaScriptObfuscatorCLI.spec.ts @@ -590,8 +590,9 @@ describe('JavaScriptObfuscatorCLI', function (): void { }); after(() => { - rimraf.sync(outputFixturesFilePath1); - rimraf.sync(outputFixturesFilePath2); + // instead recreate foo and bar files exactly as they were instead of deleting them + fs.writeFileSync(outputFixturesFilePath1, 'var foo = 1;'); + fs.writeFileSync(outputFixturesFilePath2, 'var bar = 2;'); }); }); });