Identifiers Renaming

Potency Medium
Resilience High
Cost None
Tags: rename, identifiers, minification, optimization

Description

Identifiers Renaming replaces identifier names with randomly generated names that are shorter and meaningless. The original identifier names hold meaning which is unnecessary for the JavaScript engine to run the program.

Identifier names inside HTML script tags, HTML event attributes, and eval-like function arguments (excluding Function contructor) are also renamed (these are arguments that are provided as a string and will be executed as code).

Code Annotation Example

// @jscrambler define identifiersRenaming {includeList: [var1,var2], namePrefix: prefix} as ir
// @jscrambler enable ir

Note: This transformation cannot be disabled using annotations if enabled in the protection configuration.

Examples

The following code instantiates functions and variables and performs an eval of the code

function addNumbers() {
  function sum(number1, number2) {
    return number1 + number2;
  }

  var someNumber = 123;
  var anotherNumber = 45;
  return eval("sum(someNumber, anotherNumber)");
}

It will be renamed to the following (on SAFEST mode)

function addNumbers() {
  function c(d, e) {
      return d + e;
  }
  var a = 123;
  var b = 45;
  return eval("c(a,b);");
}

The following HTML code

<html>
<body>
  <script>
    function submitResult() {
      var action = 'submit';
      apiCall(action);
    }
  </script>
  <button onclick="submitResult()">Submit</button>
</body>
</html>

Will be renamed to (on UNSAFE mode)

<html>
<body>
  <script>
    function l() {
      var n = 'submit';
      m(n);
    }
  </script>
  <button onclick="l();">Submit</button>
</body>
</html>

SAFEST mode

Identifiers Renaming on SAFEST mode only renames local identifier names.

Consider the following example:

var definedVar = 1;
function definedFn (localParam) {
   window.alert(localParam);
}
definedFn(definedVar);
notDefinedFn(notDefinedVar);

After applying the transformation with the SAFEST setting on, this is the result:

var definedVar = 1;
function definedFn(a) {
   window.alert(a);
}
definedFn(definedVar);
notDefinedFn(notDefinedVar);

UNSAFE mode

Identifiers Renaming on UNSAFE mode renames both local and public identifier names, unless they are either:

  • Included in the Exclude List defined by the user;
  • Numeric keys used to access object fields, or;
  • Browser/Node.js reserved keywords or names.

Consider the following example:

var definedVar = 1;
function definedFn (localParam) {
  var b = {
    0: localParam,
    zero: 'changed'
  }
  window.alert(b[0]);
  window.alert(b['zero']);
}
definedFn(definedVar);
notDefinedFn(notDefinedVar);

After applying the transformation with the UNSAFE mode on, this is the resulting code:

var d = 1;
function e(n) {
  var q = {
    0: n,
    'p': 'changed'
  }
  window.alert(q[0]);
  window.alert(q['p']);
}
e(d);
c(m);

Exclude List

The Exclude List is a list of names defined by the user that are not renamed.

Wildcards are allowed and represent a non-greedy matcher like .*?. For instance, to ignore importantFn, secretVariable and any name that begins with a single underscore and ends with another single underscore the Exclude List would look like the following

"options": {
  "excludeList": [
    "importantFn",
    "secretVariable",
    "_*_"
  ]
}

Include List

The Include List is a list of names defined by the user that will be forcibly renamed (even if the name is not safe to rename).

Consider the following code

var definedVar = 1;
function definedFn (localParam) {
   window.alert(localParam);
}
definedFn(definedVar);
notDefinedFn(notDefinedVar);

If you want to rename public identifier names, which are not renamed by Identifiers Renaming on SAFEST mode, such as definedVar and definedFn, add them to the Include List like the following

"options": {
  "mode": "SAFEST"
  "includeList": [
    "definedVar",
    "definedFn"
  ]
}

Applying the Include List and transforming the code will output the following code

var d = 1;
function e(a) {
   window.alert(a);
}
e(d);
notDefinedFn(notDefinedVar);

The Include List supports the same Wildcard behavior as the Exclude List.

Symbol Table

Jscrambler can import symbol tables to ensure certain global variables and object properties have specific names. These symbol tables can be passed using the --input-symbol-table <file> option, or with the inputSymbolTable option in the configuration file.

These files follow the schema used by uglifyjs@^3:

{
  "vars": {
    "props": {
      "$globalName": "transformedName"
    }
  },
  "props": {
    "props": {
      "$propertyName": "transformedName"
    }
  }
}

Similarly, the resulting symbol table can be obtained using the --output-symbol-table <protectionId> option.

There is currently no way to specify an input or output symbol table using the web app.

Collisions between Include List and Exclude List

Jscrambler has rules to deal with name collisions between the Include List and Exclude List.

The following are examples of name collisions

  • _draw and _draw
  • _draw and _*
  • _draw and *

Names without wildcards like _draw prevail over names with wildcards like _*:

  • if you add _draw to the Include List and _* to Exclude List ANY occurrence of _draw will be renamed;
  • if you add _draw to the Exclude List and _* to Include List NO occurrence of _draw will be renamed;
  • also if _draw is added to both lists then NO occurrence of _draw will be renamed. Exclude List prevails;

Option Types

Name Required Default Value Description
mode No SAFEST Transformation Modes
includeList No N/A List of names defined by the user that must be forcibly renamed.
excludeList No N/A List of names defined by the user that mustn't be renamed.
namePrefix No N/A Adds a prefix to all identifier names.

Mode

Name Description
SAFEST Only renames local identifiers
UNSAFE Renames local and public identifiers.

Browser Compatibility

Browser Compatible Versions Tested Versions Notes
Chrome 80+ 80+
Firefox 90+ 90+
Internet Explorer 8+ 8+
Microsoft Edge 116+ 116+
Safari 13.1+ 13.1+

API Parameters

Example:

{
  "keys": {
    "accessKey": "XXXXXX",
    "secretKey": "YYYYYY"
  },
  "applicationId": "ZZZZZZ",
  "params": [
    {
      "name": "identifiersRenaming",
      "options": {
        "mode": "SAFEST",
        "includeList": [
          "VALUE1",
          "VALUE2"
        ],
        "excludeList": [
          "VALUE1",
          "VALUE2"
        ],
        "namePrefix": "VALUE"
      }
    }
  ]
}