From c844f97cfc8200447d49540b5ff127f11c87a589 Mon Sep 17 00:00:00 2001 From: Timofey Kachalov Date: Tue, 6 Jan 2026 23:37:42 +0400 Subject: [PATCH] Ignore transformation of `process.env.*` (#1367) --- .gitignore | 1 + .npmignore | 1 + CHANGELOG.md | 4 ++ CLAUDE.md | 4 +- CODE_OF_CONDUCT.md | 2 +- README.md | 4 +- package.json | 9 +-- .../PreparingTransformersModule.ts | 6 ++ .../obfuscating-guards/ObfuscatingGuard.ts | 1 + .../ObfuscatingGuardsTransformer.ts | 1 + .../ProcessEnvObfuscationGuard.ts | 66 +++++++++++++++++++ .../JavaScriptObfuscator.spec.ts | 18 +++++ .../fixtures/process-env.js | 1 + webpack/utils/WebpackUtils.js | 2 +- webpack/webpack.browser.config.js | 13 ++++ webpack/webpack.node.config.js | 13 ++++ 16 files changed, 134 insertions(+), 12 deletions(-) create mode 100644 src/node-transformers/preparing-transformers/obfuscating-guards/ProcessEnvObfuscationGuard.ts create mode 100644 test/functional-tests/javascript-obfuscator/fixtures/process-env.js diff --git a/.gitignore b/.gitignore index cfe4fd23..ac824298 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ npm-debug.log /test/benchmark/**/** *dockerfile /test*.js +/reproductions diff --git a/.npmignore b/.npmignore index e7fb7148..2157c5a9 100644 --- a/.npmignore +++ b/.npmignore @@ -12,3 +12,4 @@ /test*.js index.ts index.cli.ts +/reproductions \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index f0f9804b..013df569 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ Change Log +v5.2.0 +--- +* Skip obfuscation of `process.env.*` + v5.1.0 --- * Add `version` parameter to the `apiConfig` to use different versions JavaScript Obfuscator Pro via API diff --git a/CLAUDE.md b/CLAUDE.md index 3236bb57..03d0777f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -5,7 +5,7 @@ **JavaScript Obfuscator** is a powerful, enterprise-grade code obfuscation tool for JavaScript and Node.js applications. It transforms readable JavaScript code into a protected, difficult-to-understand format while maintaining full functionality. The project is widely used for protecting intellectual property and preventing reverse engineering. - **Version**: 5.0.0 -- **Author**: Timofey Kachalov (@sanex3339) +- **Author**: Timofei Kachalov (@sanex3339) - **License**: BSD-2-Clause - **Repository**: https://github.com/javascript-obfuscator/javascript-obfuscator - **Homepage**: https://obfuscator.io/ @@ -1429,7 +1429,7 @@ Use [grunt-contrib-obfuscator](https://github.com/javascript-obfuscator/grunt-co **BSD-2-Clause License** -Copyright (C) 2016-2024 Timofey Kachalov +Copyright (C) 2016-2026 Timofei Kachalov See `LICENSE.BSD` for full license text. diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index c2a51b85..14aa477f 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -34,7 +34,7 @@ This Code of Conduct applies both within project spaces and in public spaces whe ## Enforcement -Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at sanex3339@yandex.ru. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at support@obfuscator.io. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. diff --git a/README.md b/README.md index 31138b95..8bd9ebe6 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ #### You can support this project by donating: @@ -2101,7 +2101,7 @@ Become a sponsor and get your logo on our README on Github with a link to your s ## License [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fjavascript-obfuscator%2Fjavascript-obfuscator.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fjavascript-obfuscator%2Fjavascript-obfuscator?ref=badge_large) -Copyright (C) 2016-2024 [Timofey Kachalov](http://github.com/sanex3339). +Copyright (C) 2016-2026 [Timofei Kachalov](http://github.com/sanex3339). Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/package.json b/package.json index ba8f9d0f..7bb02fa5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "javascript-obfuscator", - "version": "5.1.0", + "version": "5.2.0", "description": "JavaScript obfuscator", "keywords": [ "obfuscator", @@ -129,12 +129,9 @@ "prepare": "husky install" }, "author": { - "name": "Timofey Kachalov" + "name": "Timofei Kachalov" }, - "contributors": [ - "Timofey Kachalov (https://github.com/sanex3339)", - "Dmitry Zamotkin (https://github.com/zamotkin)" - ], + "contributors": ["Timofei Kachalov (https://github.com/sanex3339)", "Dmitry Zamotkin (https://github.com/zamotkin)"], "license": "BSD-2-Clause", "packageManager": "yarn@1.22.21+sha512.ca75da26c00327d26267ce33536e5790f18ebd53266796fbb664d2a4a5116308042dd8ee7003b276a20eace7d3c5561c3577bdd71bcb67071187af124779620a" } diff --git a/src/container/modules/node-transformers/PreparingTransformersModule.ts b/src/container/modules/node-transformers/PreparingTransformersModule.ts index da19c7a6..296b632f 100644 --- a/src/container/modules/node-transformers/PreparingTransformersModule.ts +++ b/src/container/modules/node-transformers/PreparingTransformersModule.ts @@ -15,6 +15,7 @@ import { EvalCallExpressionTransformer } from '../../../node-transformers/prepar import { ForceTransformStringObfuscatingGuard } from '../../../node-transformers/preparing-transformers/obfuscating-guards/ForceTransformStringObfuscatingGuard'; import { IgnoredImportObfuscatingGuard } from '../../../node-transformers/preparing-transformers/obfuscating-guards/IgnoredImportObfuscatingGuard'; import { ImportMetaObfuscationGuard } from '../../../node-transformers/preparing-transformers/obfuscating-guards/ImportMetaObfuscationGuard'; +import { ProcessEnvObfuscationGuard } from '../../../node-transformers/preparing-transformers/obfuscating-guards/ProcessEnvObfuscationGuard'; import { MetadataTransformer } from '../../../node-transformers/preparing-transformers/MetadataTransformer'; import { ObfuscatingGuardsTransformer } from '../../../node-transformers/preparing-transformers/ObfuscatingGuardsTransformer'; import { ParentificationTransformer } from '../../../node-transformers/preparing-transformers/ParentificationTransformer'; @@ -73,6 +74,11 @@ export const preparingTransformersModule: interfaces.ContainerModule = new Conta .inSingletonScope() .whenTargetNamed(ObfuscatingGuard.ImportMetaObfuscationGuard); + bind(ServiceIdentifiers.INodeGuard) + .to(ProcessEnvObfuscationGuard) + .inSingletonScope() + .whenTargetNamed(ObfuscatingGuard.ProcessEnvObfuscationGuard); + bind(ServiceIdentifiers.INodeGuard) .to(ReservedStringObfuscatingGuard) .inSingletonScope() diff --git a/src/enums/node-transformers/preparing-transformers/obfuscating-guards/ObfuscatingGuard.ts b/src/enums/node-transformers/preparing-transformers/obfuscating-guards/ObfuscatingGuard.ts index 3da24345..50dd66c8 100644 --- a/src/enums/node-transformers/preparing-transformers/obfuscating-guards/ObfuscatingGuard.ts +++ b/src/enums/node-transformers/preparing-transformers/obfuscating-guards/ObfuscatingGuard.ts @@ -4,5 +4,6 @@ export enum ObfuscatingGuard { ForceTransformStringObfuscatingGuard = 'ForceTransformStringObfuscatingGuard', IgnoredImportObfuscatingGuard = 'IgnoredImportObfuscatingGuard', ImportMetaObfuscationGuard = 'ImportMetaObfuscationGuard', + ProcessEnvObfuscationGuard = 'ProcessEnvObfuscationGuard', ReservedStringObfuscatingGuard = 'ReservedStringObfuscatingGuard' } diff --git a/src/node-transformers/preparing-transformers/ObfuscatingGuardsTransformer.ts b/src/node-transformers/preparing-transformers/ObfuscatingGuardsTransformer.ts index c05f019b..8d10290c 100644 --- a/src/node-transformers/preparing-transformers/ObfuscatingGuardsTransformer.ts +++ b/src/node-transformers/preparing-transformers/ObfuscatingGuardsTransformer.ts @@ -33,6 +33,7 @@ export class ObfuscatingGuardsTransformer extends AbstractNodeTransformer { ObfuscatingGuard.ForceTransformStringObfuscatingGuard, ObfuscatingGuard.IgnoredImportObfuscatingGuard, ObfuscatingGuard.ImportMetaObfuscationGuard, + ObfuscatingGuard.ProcessEnvObfuscationGuard, ObfuscatingGuard.ReservedStringObfuscatingGuard ]; diff --git a/src/node-transformers/preparing-transformers/obfuscating-guards/ProcessEnvObfuscationGuard.ts b/src/node-transformers/preparing-transformers/obfuscating-guards/ProcessEnvObfuscationGuard.ts new file mode 100644 index 00000000..efbd23e1 --- /dev/null +++ b/src/node-transformers/preparing-transformers/obfuscating-guards/ProcessEnvObfuscationGuard.ts @@ -0,0 +1,66 @@ +import { injectable } from 'inversify'; + +import * as ESTree from 'estree'; + +import { IObfuscatingGuard } from '../../../interfaces/node-transformers/preparing-transformers/obfuscating-guards/IObfuscatingGuard'; + +import { ObfuscatingGuardResult } from '../../../enums/node/ObfuscatingGuardResult'; + +import { NodeGuards } from '../../../node/NodeGuards'; + +@injectable() +export class ProcessEnvObfuscationGuard implements IObfuscatingGuard { + /** + * @param {Node} node + * @return {boolean} + * @private + */ + private static isProcessEnvMemberExpression(node: ESTree.Node): boolean { + if (!NodeGuards.isMemberExpressionNode(node)) { + return false; + } + + return ( + NodeGuards.isIdentifierNode(node.object) && + node.object.name === 'process' && + NodeGuards.isIdentifierNode(node.property) && + node.property.name === 'env' && + !node.computed + ); + } + + /** + * @param {Node} node + * @return {boolean} + * @private + */ + private static isPartOfProcessEnvChain(node: ESTree.Node): boolean { + if (ProcessEnvObfuscationGuard.isProcessEnvMemberExpression(node)) { + return true; + } + + const parentNode = node.parentNode; + + if (parentNode && NodeGuards.isMemberExpressionNode(parentNode)) { + if (ProcessEnvObfuscationGuard.isProcessEnvMemberExpression(parentNode.object)) { + return true; + } + + if (ProcessEnvObfuscationGuard.isProcessEnvMemberExpression(parentNode)) { + return true; + } + } + + return false; + } + + /** + * @param {Node} node + * @returns {ObfuscatingGuardResult} + */ + public check(node: ESTree.Node): ObfuscatingGuardResult { + return ProcessEnvObfuscationGuard.isPartOfProcessEnvChain(node) + ? ObfuscatingGuardResult.Ignore + : ObfuscatingGuardResult.Transform; + } +} diff --git a/test/functional-tests/javascript-obfuscator/JavaScriptObfuscator.spec.ts b/test/functional-tests/javascript-obfuscator/JavaScriptObfuscator.spec.ts index 6a12c7ab..4955b44d 100644 --- a/test/functional-tests/javascript-obfuscator/JavaScriptObfuscator.spec.ts +++ b/test/functional-tests/javascript-obfuscator/JavaScriptObfuscator.spec.ts @@ -721,6 +721,24 @@ describe('JavaScriptObfuscator', () => { }); }); + describe('process.env.* support', () => { + const regExp: RegExp = /console\['log']\(process\.env\.FOO\);/; + + let obfuscatedCode: string; + + beforeEach(() => { + const code: string = readFileAsString(__dirname + '/fixtures/process-env.js'); + + obfuscatedCode = JavaScriptObfuscator.obfuscate(code, { + ...NO_ADDITIONAL_NODES_PRESET + }).getObfuscatedCode(); + }); + + it('should not obfuscate `process.env.*`', () => { + assert.match(obfuscatedCode, regExp); + }); + }); + /** * https://github.com/javascript-obfuscator/javascript-obfuscator/issues/710 */ diff --git a/test/functional-tests/javascript-obfuscator/fixtures/process-env.js b/test/functional-tests/javascript-obfuscator/fixtures/process-env.js new file mode 100644 index 00000000..d375f0d1 --- /dev/null +++ b/test/functional-tests/javascript-obfuscator/fixtures/process-env.js @@ -0,0 +1 @@ +console.log(process.env.FOO); diff --git a/webpack/utils/WebpackUtils.js b/webpack/utils/WebpackUtils.js index 572e4105..81192350 100644 --- a/webpack/utils/WebpackUtils.js +++ b/webpack/utils/WebpackUtils.js @@ -1,6 +1,6 @@ const fs = require('fs'); -const copyright = 'Copyright (C) 2016-2024 Timofey Kachalov '; +const copyright = 'Copyright (C) 2016-2026 Timofei Kachalov '; const sourceMapSupportRequire = 'require("source-map-support").install();'; class WebpackUtils { diff --git a/webpack/webpack.browser.config.js b/webpack/webpack.browser.config.js index 1a7ed3fb..f6df3bfb 100644 --- a/webpack/webpack.browser.config.js +++ b/webpack/webpack.browser.config.js @@ -1,6 +1,7 @@ 'use strict'; const webpack = require('webpack'); +const TerserPlugin = require('terser-webpack-plugin'); const packageJson = require('pjson'); const WebpackUtils = require('./utils/WebpackUtils').WebpackUtils; @@ -41,6 +42,18 @@ module.exports = { process: ['process'] }) ], + optimization: { + minimizer: [ + new TerserPlugin({ + extractComments: false, + terserOptions: { + format: { + comments: /^!/ // Keep comments starting with ! + } + } + }) + ] + }, output: { libraryTarget: 'umd', library: 'JavaScriptObfuscator', diff --git a/webpack/webpack.node.config.js b/webpack/webpack.node.config.js index 5761bad6..3da2d2da 100644 --- a/webpack/webpack.node.config.js +++ b/webpack/webpack.node.config.js @@ -4,6 +4,7 @@ const path = require('path'); const nodeExternals = require('webpack-node-externals'); const webpack = require('webpack'); +const TerserPlugin = require('terser-webpack-plugin'); const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); const ForkTsCheckerNotifierWebpackPlugin = require('fork-ts-checker-notifier-webpack-plugin'); const ESLintPlugin = require('eslint-webpack-plugin'); @@ -70,6 +71,18 @@ module.exports = { skipFirstNotification: true }) ], + optimization: { + minimizer: [ + new TerserPlugin({ + extractComments: false, + terserOptions: { + format: { + comments: /^!/ // Keep comments starting with ! + } + } + }) + ] + }, output: { libraryTarget: 'commonjs2' },