Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
Change Log

v2.11.0
---
* Added option `renamePropertiesMode` to switch between new `safe` and old `unsafe` modes of `renameProperties` option. Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/878
* `renameProperties` option now works in `safe` way by default

v2.10.7
---
* Fixed CVE-2019-18413. Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/880
Expand Down
17 changes: 15 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,7 @@ Following options are available for the JS Obfuscator:
optionsPreset: 'default',
renameGlobals: false,
renameProperties: false,
renamePropertiesMode: 'safe',
reservedNames: [],
reservedStrings: [],
rotateStringArray: true,
Expand Down Expand Up @@ -429,6 +430,7 @@ Following options are available for the JS Obfuscator:
--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)
--rotate-string-array <boolean>
Expand Down Expand Up @@ -785,10 +787,12 @@ Enables obfuscation of global variable and function names **with declaration**.
### `renameProperties`
Type: `boolean` Default: `false`

##### :warning: this option **WILL** break your code in most cases. Enable it only if you know what it does!
##### :warning: this option **MAY** break your code. Enable it only if you know what it does!

Enables renaming of property names. All built-in DOM properties and properties in core JavaScript classes will be ignored.

To switch between `safe` and `unsafe` modes of this option use [`renamePropertiesMode`](#renamepropertiesmode) option.

To set format of renamed property names use [`identifierNamesGenerator`](#identifiernamesgenerator) option.

To control which properties will be renamed use [`reservedNames`](#reservednames) option.
Expand Down Expand Up @@ -821,6 +825,15 @@ Example:
}());
```

### `renamePropertiesMode`
Type: `string` Default: `safe`

##### :warning: Even in `safe` mode, [`renameProperties`](#renameproperties) option **MAY** break your code.

Specifies `renameProperties` option mode:
* `safe` - default behaviour after `2.11.0` release. Trying to rename properties in a more safe way to prevent runtime errors. With this mode some properties will be excluded from renaming.
* `unsafe` - default behaviour before `2.11.0` release. Renames properties in an unsafe way without any restrictions.

### `reservedNames`
Type: `string[]` Default: `[]`

Expand Down Expand Up @@ -1447,7 +1460,7 @@ See: [`Kind of variables`](#kind-of-variables)

### I enabled `renameProperties` option, and my code broke! What to do?

Just disable this option.
Try `renamePropertiesMode: 'safe'` option, if it still doesn't work, just disable this option.

## Backers

Expand Down
2 changes: 1 addition & 1 deletion dist/index.browser.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/index.cli.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/index.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "javascript-obfuscator",
"version": "2.10.7",
"version": "2.11.0",
"description": "JavaScript obfuscator",
"keywords": [
"obfuscator",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
import * as estraverse from 'estraverse';
import * as ESTree from 'estree';

import { TStringLiteralNode } from '../../types/node/TStringLiteralNode';

import { IOptions } from '../../interfaces/options/IOptions';
import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
import { IStringArrayStorage } from '../../interfaces/storages/string-array-transformers/IStringArrayStorage';
Expand Down Expand Up @@ -107,9 +109,9 @@ export class StringArrayStorageAnalyzer implements IStringArrayStorageAnalyzer {
}

/**
* @param {(SimpleLiteral & {value: string}) | (RegExpLiteral & {value: string})} literalNode
* @param {TStringLiteralNode} literalNode
*/
public addItemDataForLiteralNode (literalNode: ESTree.Literal & {value: string}): void {
public addItemDataForLiteralNode (literalNode: TStringLiteralNode): void {
this.stringArrayStorageData.set(
literalNode,
this.stringArrayStorage.getOrThrow(literalNode.value)
Expand All @@ -125,10 +127,10 @@ export class StringArrayStorageAnalyzer implements IStringArrayStorageAnalyzer {
}

/**
* @param {(SimpleLiteral & {value: string})} literalNode
* @param {TStringLiteralNode} literalNode
* @returns {boolean}
*/
private shouldAddValueToStringArray (literalNode: ESTree.Literal & {value: string}): boolean {
private shouldAddValueToStringArray (literalNode: TStringLiteralNode): boolean {
const isForceTransformNode: boolean = NodeMetadata.isForceTransformNode(literalNode);

if (isForceTransformNode) {
Expand Down
11 changes: 9 additions & 2 deletions src/cli/JavaScriptObfuscatorCLI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ import { IdentifierNamesGenerator } from '../enums/generators/identifier-names-g
import { LoggingPrefix } from '../enums/logger/LoggingPrefix';
import { ObfuscationTarget } from '../enums/ObfuscationTarget';
import { OptionsPreset } from '../enums/options/presets/OptionsPreset';
import { RenamePropertiesMode } from '../enums/node-transformers/rename-properties-transformers/RenamePropertiesMode';
import { SourceMapMode } from '../enums/source-map/SourceMapMode';
import { StringArrayEncoding } from '../enums/node-transformers/string-array-transformers/StringArrayEncoding';
import { StringArrayIndexesType } from '../enums/node-transformers/string-array-transformers/StringArrayIndexesType';
import { StringArrayWrappersType } from '../enums/node-transformers/string-array-transformers/StringArrayWrappersType';

import { DEFAULT_PRESET } from '../options/presets/Default';
Expand All @@ -30,7 +32,6 @@ import { Logger } from '../logger/Logger';
import { ObfuscatedCodeWriter } from './utils/ObfuscatedCodeWriter';
import { SourceCodeReader } from './utils/SourceCodeReader';
import { Utils } from '../utils/Utils';
import { StringArrayIndexesType } from '../enums/node-transformers/string-array-transformers/StringArrayIndexesType';

export class JavaScriptObfuscatorCLI implements IInitializable {
/**
Expand Down Expand Up @@ -285,9 +286,15 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
BooleanSanitizer
)
.option(
'--rename-properties <boolean>', 'UNSAFE: Enables renaming of property names. This probably WILL break your code',
'--rename-properties <boolean>', 'UNSAFE: Enables renaming of property names. This probably MAY break your code',
BooleanSanitizer
)
.option(
'--rename-properties-mode <boolean>',
'Specify `--rename-properties` option mode. ' +
`Values: ${CLIUtils.stringifyOptionAvailableValues(RenamePropertiesMode)}. ` +
`Default: ${RenamePropertiesMode.Safe}`
)
.option(
'--rotate-string-array <boolean>', 'Enable rotation of string array values during obfuscation',
BooleanSanitizer
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Utils } from '../../../utils/Utils';

export const RenamePropertiesMode: Readonly<{
Safe: 'safe';
Unsafe: 'unsafe';
}> = Utils.makeEnum({
Safe: 'safe',
Unsafe: 'unsafe'
});
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import * as ESTree from 'estree';

import { TStringLiteralNode } from '../../../types/node/TStringLiteralNode';

import { IAnalyzer } from '../IAnalyzer';
import { IStringArrayStorageItemData } from '../../storages/string-array-transformers/IStringArrayStorageItem';

Expand All @@ -16,9 +18,9 @@ export interface IStringArrayStorageAnalyzer extends IAnalyzer<[ESTree.Program],
analyzeLiteralNode (literalNode: ESTree.Literal, parentNode: ESTree.Node): void;

/**
* @param {(SimpleLiteral & {value: string}) | (RegExpLiteral & {value: string})} literalNode
* @param {TStringLiteralNode} stringLiteralNode
*/
addItemDataForLiteralNode (literalNode: ESTree.Literal & {value: string}): void;
addItemDataForLiteralNode (stringLiteralNode: TStringLiteralNode): void;

/**
* @param {Literal} literalNode
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import * as ESTree from 'estree';

export interface IRenamePropertiesReplacer {
/**
* @param {string} propertyName
*/
excludePropertyName (propertyName: string): void;

/**
* @param {ESTree.Identifier | ESTree.Literal} node
* @returns {ESTree.Identifier | ESTree.Literal}
Expand Down
2 changes: 2 additions & 0 deletions src/interfaces/options/IOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { TOptionsPreset } from '../../types/options/TOptionsPreset';
import { TStringArrayIndexesType } from '../../types/options/TStringArrayIndexesType';
import { TStringArrayEncoding } from '../../types/options/TStringArrayEncoding';
import { TStringArrayWrappersType } from '../../types/options/TStringArrayWrappersType';
import { TRenamePropertiesMode } from '../../types/options/TRenamePropertiesMode';
import { TTypeFromEnum } from '../../types/utils/TTypeFromEnum';

import { IdentifierNamesGenerator } from '../../enums/generators/identifier-names-generators/IdentifierNamesGenerator';
Expand Down Expand Up @@ -29,6 +30,7 @@ export interface IOptions {
readonly optionsPreset: TOptionsPreset;
readonly renameGlobals: boolean;
readonly renameProperties: boolean;
readonly renamePropertiesMode: TRenamePropertiesMode;
readonly reservedNames: string[];
readonly reservedStrings: string[];
readonly rotateStringArray: boolean;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { inject, injectable, } from 'inversify';
import { inject, injectable} from 'inversify';
import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';

import * as ESTree from 'estree';
Expand All @@ -12,6 +12,8 @@ import { NodeTransformationStage } from '../../enums/node-transformers/NodeTrans

import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
import { NodeGuards } from '../../node/NodeGuards';
import { NodeLiteralUtils } from '../../node/NodeLiteralUtils';
import { RenamePropertiesMode } from '../../enums/node-transformers/rename-properties-transformers/RenamePropertiesMode';

@injectable()
export class RenamePropertiesTransformer extends AbstractNodeTransformer {
Expand Down Expand Up @@ -59,6 +61,15 @@ export class RenamePropertiesTransformer extends AbstractNodeTransformer {
*/
public getVisitor (nodeTransformationStage: NodeTransformationStage): IVisitor | null {
switch (nodeTransformationStage) {
case NodeTransformationStage.Preparing:
return {
enter: (node: ESTree.Node, parentNode: ESTree.Node | null): void => {
if (parentNode) {
this.prepareNode(node, parentNode);
}
}
};

case NodeTransformationStage.RenameProperties:
return {
enter: (node: ESTree.Node, parentNode: ESTree.Node | null): ESTree.Node | undefined => {
Expand All @@ -73,6 +84,19 @@ export class RenamePropertiesTransformer extends AbstractNodeTransformer {
}
}

/**
* @param {Node} node
* @param {Node} parentNode
*/
public prepareNode (
node: ESTree.Node,
parentNode: ESTree.Node
): void {
if (this.options.renamePropertiesMode === RenamePropertiesMode.Safe) {
this.analyzeAutoExcludedPropertyNames(node, parentNode);
}
}

/**
* @param {Node} node
* @param {NodeGuards} parentNode
Expand Down Expand Up @@ -136,4 +160,27 @@ export class RenamePropertiesTransformer extends AbstractNodeTransformer {

return methodDefinitionNode;
}

/**
* @param {Node} node
* @param {Node} parentNode
*/
private analyzeAutoExcludedPropertyNames (
node: ESTree.Node,
parentNode: ESTree.Node
): void {
if (!NodeGuards.isLiteralNode(node) || !NodeLiteralUtils.isStringLiteralNode(node)) {
return;
}

if (
(NodeGuards.isPropertyNode(parentNode) && parentNode.key === node)
|| NodeGuards.isMemberExpressionNode(parentNode) && parentNode.property === node
|| NodeGuards.isMethodDefinitionNode(parentNode) && parentNode.key === node
) {
return;
}

this.renamePropertiesReplacer.excludePropertyName(node.value);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ export class RenamePropertiesReplacer implements IRenamePropertiesReplacer {
*/
private readonly identifierNamesGenerator: IIdentifierNamesGenerator;

/**
* @type {Set<string>}
*/
private readonly excludedPropertyNames: Set<string> = new Set();

/**
* @type {Map<string, string>}
* @private
Expand All @@ -57,6 +62,13 @@ export class RenamePropertiesReplacer implements IRenamePropertiesReplacer {
this.options = options;
}

/**
* @param {string} propertyName
*/
public excludePropertyName (propertyName: string): void {
this.excludedPropertyNames.add(propertyName);
}

/**
* @param {ESTree.Identifier | ESTree.Literal} node
* @returns {ESTree.Identifier | ESTree.Literal}
Expand Down Expand Up @@ -104,10 +116,19 @@ export class RenamePropertiesReplacer implements IRenamePropertiesReplacer {
* @returns {boolean}
*/
private isReservedName (name: string): boolean {
return this.isReservedOptionName(name)
return this.isExcludedName(name)
|| this.isReservedOptionName(name)
|| this.isReservedDomPropertyName(name);
}

/**
* @param {string} name
* @returns {boolean}
*/
private isExcludedName (name: string): boolean {
return this.excludedPropertyNames.has(name);
}

/**
* @param {string} name
* @returns {boolean}
Expand Down
Loading