> ## Documentation Index
> Fetch the complete documentation index at: https://docs.js-confuser.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Tamper Protection

> Tamper Protection safeguards the runtime behavior from being altered by JavaScript pitfalls.

**⚠️ Tamper Protection requires eval and ran in a non-strict mode environment!**

- **This can break your code.**
- **Due to the security concerns of arbitrary code execution, you must enable this yourself.**


* Option name: `"lock.tamperProtection"`

* Option values: `true/false/Function`

<Card title="Requires Non-Strict Mode" type="warning">
  The obfuscated code will not work properly in Strict Mode.
  You can use the [Pack](./pack) option to bypass Strict Mode constraints.
</Card>

<Card title="Requires Eval" type="warning">
  The obfuscated code will contain unsafe eval expressions.
  The code will not work properly in [environments that have disabled eval](https://developer.mozilla.org/en-US/Web/HTTP/Headers/Content-Security-Policy/script-src#unsafe_eval_expressions).
</Card>

***

### Input / Output

This example showcases how `Tamper Protection` transforms the code. Try it out by changing the input code and see changes apply in real-time.

```js title="Input.js" lines interactive-mode="obfuscate" theme={null}
// Input.js
function onTamperDetected() {
  throw new Error('Tampering detected!');
}

fetch('https://jsonplaceholder.typicode.com/users')
  .then((response) => response.json())
  .then((data) => {
    console.log(data); // Array of users with names, usernames, and emails
  });

// Output.js
var OwC2TMP = DprDtyN();
function DprDtyN() {
  var OwC2TMP = !1;
  eval('OwC2TMP' + ' = true');
  if (!OwC2TMP) {
    lG8lOFt();
    return {};
  }
  const DprDtyN = eval('this');
  return DprDtyN;
}
function CTBxqb(DprDtyN) {
  switch (DprDtyN) {
    case '_ddqLa':
      return OwC2TMP.fetch;
    case 'n80sCw5':
      return OwC2TMP.ijQHZd;
    case 'gVVA59':
      return OwC2TMP.Object;
    case 'uw3kiq':
      return OwC2TMP.F62Lbae;
    case 'k4obAl':
      return OwC2TMP.nUVJmGR;
    case 'ESzasGT':
      return OwC2TMP.BvLsIb;
    case 'dOdNV5':
      return OwC2TMP.MWXJYC;
    case 'DKzduJ0':
      return OwC2TMP.hbCba7T;
    case 'rsj7xR':
      return OwC2TMP.G6uO7b;
    case 'ittybgG':
      return OwC2TMP.cOtxdi;
    case 'aegLcBL':
      return OwC2TMP.KZot4U;
    case 'Mlu316f':
      return OwC2TMP.zjZwngz;
    case 'TN2dHY':
      return OwC2TMP.P_4ucsg;
    case 'bcFe2m':
      return OwC2TMP.oeGHBm6;
    case 'nHf92io':
      return OwC2TMP.L8xuwcN;
    case 'qSqc6yH':
      return OwC2TMP.EHCN5sa;
    case 'O5uaSP':
      return OwC2TMP.yXI6GZf;
    case 'RgiO3rf':
      return OwC2TMP.GVGwjV;
    case 'Llvyd8w':
      return OwC2TMP.OObJNw;
    case 'gV8C5B':
      return OwC2TMP.K89Qjjj;
    case 'gAitmLo':
      return OwC2TMP.dFVId6;
    case 'F3ZB0x':
      return OwC2TMP.YCkUvH;
    case 'H2c3sf':
      return OwC2TMP.fA2LFt;
    case 'DVZ80M':
      return OwC2TMP.N0QAzFM;
    case 'TxxCnK':
      return OwC2TMP._dZgpuo;
    case 'wSKInc':
      return OwC2TMP.G9xNJ2O;
    case 'w9ZLKcj':
      return OwC2TMP.console;
    case 'gKRWmWC':
      return OwC2TMP.ppd9BE;
    case 'jy8OxT6':
      return OwC2TMP.Fsv8Jn0;
    case 'KhfHB1':
      return OwC2TMP.uZ7GnP;
    case '9p7JZNV':
      return OwC2TMP.kBsL6cY;
    case 'gZhGqkx':
      return OwC2TMP.xb72F1W;
    case 'HiW4371':
      return OwC2TMP.djmQT_;
    case 'cwGrXaF':
      return OwC2TMP.V5kBAvl;
    case 'f5PBQc':
      return OwC2TMP.NjLukC;
    case 'pzcetk':
      return OwC2TMP.AAh_8Jc;
    case 'mykkU0':
      return OwC2TMP.bbyUGcw;
    case 'DuCgOl':
      return OwC2TMP.PRxPU7;
    case 'XAf2uM':
      return OwC2TMP.iTeV3n;
    case 'dtjEKH':
      return OwC2TMP.whkNfE;
    case '_i9Do4':
      return OwC2TMP.Error;
    case '58pWu4':
      return OwC2TMP.DvFX7iZ;
  }
}
var L7j0jSR = !1;
function lG8lOFt() {
  if (L7j0jSR) return;
  L7j0jSR = !0;
  _Onsic();
}
function zRcUvK() {
  function OwC2TMP(OwC2TMP, DprDtyN) {
    const L7j0jSR = OwC2TMP.length,
      zRcUvK = DprDtyN.length;
    let _Onsic = 0;
    if (zRcUvK > L7j0jSR) {
      return -1;
    }
    for (let fPmo3Zl = 0; fPmo3Zl <= L7j0jSR - zRcUvK; fPmo3Zl++)
      for (let CTBxqb = 0; CTBxqb < zRcUvK; CTBxqb++)
        if (OwC2TMP[fPmo3Zl + CTBxqb] === DprDtyN[CTBxqb]) {
          _Onsic++;
          if (_Onsic === zRcUvK) {
            return fPmo3Zl;
          }
        } else {
          _Onsic = 0;
          break;
        }
    return -1;
  }
  function DprDtyN(DprDtyN) {
    if (
      OwC2TMP('' + DprDtyN, '{ [native code] }') === -1 ||
      typeof CTBxqb('gVVA59').getOwnPropertyDescriptor(DprDtyN, 'toString') !==
        'undefined'
    ) {
      lG8lOFt();
      return;
    }
    return DprDtyN;
  }
  var L7j0jSR = arguments;
  if (L7j0jSR.length === 1) {
    return DprDtyN(L7j0jSR[0]);
  } else if (L7j0jSR.length === 2) {
    var zRcUvK = L7j0jSR[0],
      _Onsic = L7j0jSR[1],
      fPmo3Zl = zRcUvK[_Onsic];
    fPmo3Zl = DprDtyN(fPmo3Zl);
    return fPmo3Zl.bind(zRcUvK);
  }
}
(function () {
  function OwC2TMP() {
    try {
      var OwC2TMP = [];
      delete OwC2TMP.length;
    } catch (e) {
      return !0;
    }
    return !1;
  }
  if (OwC2TMP()) {
    lG8lOFt();
    zRcUvK = void 0;
  }
})();
function _Onsic() {
  throw new (CTBxqb('_i9Do4'))('Tampering detected!');
}
zRcUvK(CTBxqb('_ddqLa'))('https://jsonplaceholder.typicode.com/users')
  .then((OwC2TMP) => {
    return OwC2TMP.json();
  })
  .then((OwC2TMP) => {
    zRcUvK(CTBxqb('w9ZLKcj'), 'log')(OwC2TMP);
  });
```

***

### Improves Global Concealing

Tamper Protection with `Global Concealing` can detect at runtime if certain global functions have been monkey-patched. The following code exemplifies this:

### Native function check

```js lines theme={null}
var _fetch = fetch;
fetch = (...args)=>{
  console.log("Fetch request intercepted!", ...args)
  return _fetch(...args)
}
```

This monkey-patch can be detected by inspecting the `fetch.toString()` value:

```js lines theme={null}
// Untampered
fetch.toString() // "function fetch() { [native code] }"

// Tampered
fetch.toString()  // "(...args)=>{\n  console.log("Fetch request intercepted!", ...args)\n  return _fetch(...args)\n}"
```

Certain global functions are checked before each invocation to ensure that (1) the arguments cannot be intercepted and (2) their behavior cannot be altered.

#### Stealthy global

A direct `eval` invocation can access the local scope, only if it has not been redefined.

```js lines theme={null}
let root = {};
eval("root=this"); // Window {window: ...}
```

This method securely obtains the real global object for both the browser and NodeJS. Properties on the global object can still be changed however.

***

### Disallows Strict Mode

Tamper Protection requires the script to run in non-strict mode. Detection of the script in Strict Mode will be considered tampering. You can control the tampering response using the `lock.countermeasures` option.

***

### Custom Implementation

#### `options.lock.tamperProtection(fnName)`

Control which functions are changed. Returns a `boolean`.

| Parameter | Type     | Description                                                 |
| --------- | -------- | ----------------------------------------------------------- |
| `fnName`  | `string` | The function name proposed receive native check protection. |

***

### Usage Example

The provided code example will obfuscate the file `input.js` and write the output to a file named `output.js`.

```js title="Usage Example" lines theme={null}
import JSConfuser from "js-confuser";
import {readFileSync, writeFileSync} from "fs";

// Read input code
const sourceCode = readFileSync("input.js", "utf8");
const options = {
  target: 'browser',
  lock: {
    tamperProtection: true,
    countermeasures: 'onTamperDetected',
  },
  globalConcealing: true,
};

JSConfuser.obfuscate(sourceCode, options).then((result)=>{
  // Write output code
  writeFileSync("output.js", result.code);
}).catch(err=>{
  // Error occurred
  console.error(err);  
});
```

***

#### Enabled In

* [High Preset](/presets/high): No
* [Medium Preset](/presets/medium): No
* [Low Preset](/presets/low): No

***

#### See Also

* [Countermeasures](/options/countermeasures)
