@nodesecure/js-x-ray 5.1.0 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2021 NodeSecure
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2021 NodeSecure
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,8 +1,13 @@
1
- # js-x-ray
2
- ![version](https://img.shields.io/badge/dynamic/json.svg?url=https://raw.githubusercontent.com/NodeSecure/js-x-ray/master/package.json&query=$.version&label=Version)
3
- [![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://github.com/NodeSecure/js-x-ray/commit-activity)
4
- [![mit](https://img.shields.io/github/license/Naereen/StrapDown.js.svg)](https://github.com/NodeSecure/js-x-ray/blob/master/LICENSE)
5
- ![build](https://img.shields.io/github/workflow/status/NodeSecure/js-x-ray/Node.js%20CI)
1
+ <p align="center">
2
+ <h1 align="center">JS-X-RAY</h1>
3
+ </p>
4
+
5
+ ![version](https://img.shields.io/badge/dynamic/json.svg?style=for-the-badge&url=https://raw.githubusercontent.com/NodeSecure/js-x-ray/master/package.json&query=$.version&label=Version)
6
+ [![mit](https://img.shields.io/github/license/Naereen/StrapDown.js.svg?style=for-the-badge)](https://github.com/NodeSecure/js-x-ray/blob/master/LICENSE)
7
+ [![OpenSSF
8
+ Scorecard](https://api.securityscorecards.dev/projects/github.com/NodeSecure/js-x-ray/badge?style=for-the-badge)](https://api.securityscorecards.dev/projects/github.com/NodeSecure/js-x-ray)
9
+ ![build](https://img.shields.io/github/actions/workflow/status/NodeSecure/js-x-ray/node.js.yml?style=for-the-badge)
10
+ ![coverage](https://img.shields.io/codecov/c/github/NodeSecure/js-x-ray?style=for-the-badge)
6
11
 
7
12
  JavaScript AST analysis. This package has been created to export the [Node-Secure](https://github.com/ES-Community/nsecure) AST Analysis to enable better code evolution and allow better access to developers and researchers.
8
13
 
@@ -80,9 +85,9 @@ type WarningName = "parsing-error"
80
85
  | "encoded-literal"
81
86
  | "unsafe-regex"
82
87
  | "unsafe-stmt"
83
- | "unsafe-assign"
84
88
  | "short-identifiers"
85
89
  | "suspicious-literal"
90
+ | "suspicious-file"
86
91
  | "obfuscated-code"
87
92
  | "weak-crypto"
88
93
  | "unsafe-import";
@@ -115,10 +120,10 @@ This section describe all the possible warnings returned by JSXRay. Click on the
115
120
  | [unsafe-import](./docs/unsafe-import.md) | ❌ | Unable to follow an import (require, require.resolve) statement/expr. |
116
121
  | [unsafe-regex](./docs/unsafe-regex.md) | ❌ | A RegEx as been detected as unsafe and may be used for a ReDoS Attack. |
117
122
  | [unsafe-stmt](./docs//unsafe-stmt.md) | ❌ | Usage of dangerous statement like `eval()` or `Function("")`. |
118
- | [unsafe-assign](./docs/unsafe-assign.md) | ❌ | Assignment of a protected global like `process` or `require`. |
119
123
  | [encoded-literal](./docs/encoded-literal.md) | ❌ | An encoded literal has been detected (it can be an hexa value, unicode sequence or a base64 string) |
120
124
  | [short-identifiers](./docs/short-identifiers.md) | ❌ | This mean that all identifiers has an average length below 1.5. |
121
125
  | [suspicious-literal](./docs/suspicious-literal.md) | ❌ | A suspicious literal has been found in the source code. |
126
+ | [suspicious-file](./docs/suspicious-file.md) | ✔️ | A suspicious file with more than ten encoded-literal in it |
122
127
  | [obfuscated-code](./docs/obfuscated-code.md) | ✔️ | There's a very high probability that the code is obfuscated. |
123
128
  | [weak-crypto](./docs/weak-crypto.md) | ✔️ | The code probably contains a weak crypto algorithm (md5, sha1...) |
124
129
 
@@ -178,7 +183,7 @@ export type ReportOnFile = {
178
183
  ## Contributors ✨
179
184
 
180
185
  <!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
181
- [![All Contributors](https://img.shields.io/badge/all_contributors-8-orange.svg?style=flat-square)](#contributors-)
186
+ [![All Contributors](https://img.shields.io/badge/all_contributors-10-orange.svg?style=flat-square)](#contributors-)
182
187
  <!-- ALL-CONTRIBUTORS-BADGE:END -->
183
188
 
184
189
  Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
@@ -187,18 +192,22 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
187
192
  <!-- prettier-ignore-start -->
188
193
  <!-- markdownlint-disable -->
189
194
  <table>
190
- <tr>
191
- <td align="center"><a href="https://www.linkedin.com/in/thomas-gentilhomme/"><img src="https://avatars.githubusercontent.com/u/4438263?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Gentilhomme</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=fraxken" title="Code">💻</a> <a href="https://github.com/NodeSecure/js-x-ray/commits?author=fraxken" title="Documentation">📖</a> <a href="https://github.com/NodeSecure/js-x-ray/pulls?q=is%3Apr+reviewed-by%3Afraxken" title="Reviewed Pull Requests">👀</a> <a href="#security-fraxken" title="Security">🛡️</a> <a href="https://github.com/NodeSecure/js-x-ray/issues?q=author%3Afraxken" title="Bug reports">🐛</a></td>
192
- <td align="center"><a href="https://github.com/Rossb0b"><img src="https://avatars.githubusercontent.com/u/39910164?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Nicolas Hallaert</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=Rossb0b" title="Documentation">📖</a></td>
193
- <td align="center"><a href="https://github.com/antoine-coulon"><img src="https://avatars.githubusercontent.com/u/43391199?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Antoine</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=antoine-coulon" title="Code">💻</a></td>
194
- <td align="center"><a href="https://github.com/Mathieuka"><img src="https://avatars.githubusercontent.com/u/34446722?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mathieu</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=Mathieuka" title="Code">💻</a></td>
195
- <td align="center"><a href="https://github.com/Kawacrepe"><img src="https://avatars.githubusercontent.com/u/40260517?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Vincent Dhennin</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=Kawacrepe" title="Code">💻</a> <a href="https://github.com/NodeSecure/js-x-ray/commits?author=Kawacrepe" title="Tests">⚠️</a></td>
196
- <td align="center"><a href="http://tonygo.dev"><img src="https://avatars.githubusercontent.com/u/22824417?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Tony Gorez</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=tony-go" title="Code">💻</a> <a href="https://github.com/NodeSecure/js-x-ray/commits?author=tony-go" title="Documentation">📖</a> <a href="https://github.com/NodeSecure/js-x-ray/commits?author=tony-go" title="Tests">⚠️</a></td>
197
- <td align="center"><a href="https://github.com/PierreDemailly"><img src="https://avatars.githubusercontent.com/u/39910767?v=4?s=100" width="100px;" alt=""/><br /><sub><b>PierreD</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=PierreDemailly" title="Tests">⚠️</a></td>
198
- </tr>
199
- <tr>
200
- <td align="center"><a href="https://www.linkedin.com/in/franck-hallaert/"><img src="https://avatars.githubusercontent.com/u/110826655?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Franck Hallaert</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=Aekk0" title="Code">💻</a></td>
201
- </tr>
195
+ <tbody>
196
+ <tr>
197
+ <td align="center"><a href="https://www.linkedin.com/in/thomas-gentilhomme/"><img src="https://avatars.githubusercontent.com/u/4438263?v=4?s=100" width="100px;" alt="Gentilhomme"/><br /><sub><b>Gentilhomme</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=fraxken" title="Code">💻</a> <a href="https://github.com/NodeSecure/js-x-ray/commits?author=fraxken" title="Documentation">📖</a> <a href="https://github.com/NodeSecure/js-x-ray/pulls?q=is%3Apr+reviewed-by%3Afraxken" title="Reviewed Pull Requests">👀</a> <a href="#security-fraxken" title="Security">🛡️</a> <a href="https://github.com/NodeSecure/js-x-ray/issues?q=author%3Afraxken" title="Bug reports">🐛</a></td>
198
+ <td align="center"><a href="https://github.com/Rossb0b"><img src="https://avatars.githubusercontent.com/u/39910164?v=4?s=100" width="100px;" alt="Nicolas Hallaert"/><br /><sub><b>Nicolas Hallaert</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=Rossb0b" title="Documentation">📖</a></td>
199
+ <td align="center"><a href="https://github.com/antoine-coulon"><img src="https://avatars.githubusercontent.com/u/43391199?v=4?s=100" width="100px;" alt="Antoine"/><br /><sub><b>Antoine</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=antoine-coulon" title="Code">💻</a></td>
200
+ <td align="center"><a href="https://github.com/Mathieuka"><img src="https://avatars.githubusercontent.com/u/34446722?v=4?s=100" width="100px;" alt="Mathieu"/><br /><sub><b>Mathieu</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=Mathieuka" title="Code">💻</a></td>
201
+ <td align="center"><a href="https://github.com/Kawacrepe"><img src="https://avatars.githubusercontent.com/u/40260517?v=4?s=100" width="100px;" alt="Vincent Dhennin"/><br /><sub><b>Vincent Dhennin</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=Kawacrepe" title="Code">💻</a> <a href="https://github.com/NodeSecure/js-x-ray/commits?author=Kawacrepe" title="Tests">⚠️</a></td>
202
+ <td align="center"><a href="http://tonygo.dev"><img src="https://avatars.githubusercontent.com/u/22824417?v=4?s=100" width="100px;" alt="Tony Gorez"/><br /><sub><b>Tony Gorez</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=tony-go" title="Code">💻</a> <a href="https://github.com/NodeSecure/js-x-ray/commits?author=tony-go" title="Documentation">📖</a> <a href="https://github.com/NodeSecure/js-x-ray/commits?author=tony-go" title="Tests">⚠️</a></td>
203
+ <td align="center"><a href="https://github.com/PierreDemailly"><img src="https://avatars.githubusercontent.com/u/39910767?v=4?s=100" width="100px;" alt="PierreD"/><br /><sub><b>PierreD</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=PierreDemailly" title="Tests">⚠️</a></td>
204
+ </tr>
205
+ <tr>
206
+ <td align="center"><a href="https://www.linkedin.com/in/franck-hallaert/"><img src="https://avatars.githubusercontent.com/u/110826655?v=4?s=100" width="100px;" alt="Franck Hallaert"/><br /><sub><b>Franck Hallaert</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=Aekk0" title="Code">💻</a></td>
207
+ <td align="center"><a href="https://maji.kiwi"><img src="https://avatars.githubusercontent.com/u/33150916?v=4?s=100" width="100px;" alt="Maji"/><br /><sub><b>Maji</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=M4gie" title="Code">💻</a></td>
208
+ <td align="center"><a href="https://github.com/targos"><img src="https://avatars.githubusercontent.com/u/2352663?v=4?s=100" width="100px;" alt="Michaël Zasso"/><br /><sub><b>Michaël Zasso</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=targos" title="Code">💻</a> <a href="https://github.com/NodeSecure/js-x-ray/issues?q=author%3Atargos" title="Bug reports">🐛</a></td>
209
+ </tr>
210
+ </tbody>
202
211
  </table>
203
212
 
204
213
  <!-- markdownlint-restore -->
package/index.d.ts CHANGED
@@ -5,15 +5,15 @@ import {
5
5
  ReportOnFile,
6
6
  RuntimeFileOptions,
7
7
  RuntimeOptions
8
- } from "./types/api";
8
+ } from "./types/api.js";
9
9
  import {
10
10
  Warning,
11
11
  WarningDefault,
12
12
  WarningLocation,
13
13
  WarningName,
14
14
  WarningNameWithValue
15
- } from "./types/warnings";
16
- import { ASTDeps, Dependency } from "./types/astdeps";
15
+ } from "./types/warnings.js";
16
+ import { ASTDeps, Dependency } from "./types/astdeps.js";
17
17
 
18
18
  declare const warnings: Record<WarningName, Pick<WarningDefault, "experimental" | "i18n" | "severity">>;
19
19
 
package/index.js CHANGED
@@ -11,6 +11,13 @@ import isMinified from "is-minified-code";
11
11
  import Analysis from "./src/Analysis.js";
12
12
  import { warnings } from "./src/warnings.js";
13
13
 
14
+ // CONSTANTS
15
+ const kMeriyahDefaultOptions = {
16
+ next: true,
17
+ loc: true,
18
+ raw: true
19
+ };
20
+
14
21
  export function runASTAnalysis(str, options = Object.create(null)) {
15
22
  const { module = true, isMinified = false } = options;
16
23
 
@@ -18,13 +25,7 @@ export function runASTAnalysis(str, options = Object.create(null)) {
18
25
  // Example: #!/usr/bin/env node
19
26
  const strToAnalyze = str.charAt(0) === "#" ? str.slice(str.indexOf("\n")) : str;
20
27
  const isEcmaScriptModule = Boolean(module);
21
- const { body } = meriyah.parseScript(strToAnalyze, {
22
- next: true,
23
- loc: true,
24
- raw: true,
25
- module: isEcmaScriptModule,
26
- globalReturn: !isEcmaScriptModule
27
- });
28
+ const body = parseScriptExtended(strToAnalyze, isEcmaScriptModule);
28
29
 
29
30
  const sastAnalysis = new Analysis();
30
31
  sastAnalysis.analyzeSourceString(str);
@@ -57,11 +58,12 @@ export async function runASTAnalysisOnFile(pathToFile, options = {}) {
57
58
  try {
58
59
  const { packageName = null, module = true } = options;
59
60
  const str = await fs.readFile(pathToFile, "utf-8");
61
+ const filePathString = pathToFile instanceof URL ? pathToFile.href : pathToFile;
60
62
 
61
- const isMin = pathToFile.includes(".min") || isMinified(str);
63
+ const isMin = filePathString.includes(".min") || isMinified(str);
62
64
  const data = runASTAnalysis(str, {
63
65
  isMinified: isMin,
64
- module: path.extname(pathToFile) === ".mjs" ? true : module
66
+ module: path.extname(filePathString) === ".mjs" ? true : module
65
67
  });
66
68
  if (packageName !== null) {
67
69
  data.dependencies.removeByName(packageName);
@@ -84,4 +86,27 @@ export async function runASTAnalysisOnFile(pathToFile, options = {}) {
84
86
  }
85
87
  }
86
88
 
89
+ function parseScriptExtended(strToAnalyze, isEcmaScriptModule) {
90
+ try {
91
+ const { body } = meriyah.parseScript(strToAnalyze, {
92
+ ...kMeriyahDefaultOptions,
93
+ module: isEcmaScriptModule,
94
+ globalReturn: !isEcmaScriptModule
95
+ });
96
+
97
+ return body;
98
+ }
99
+ catch (error) {
100
+ if (error.name === "SyntaxError" && error.description.includes("The import keyword")) {
101
+ const { body } = meriyah.parseScript(strToAnalyze, {
102
+ ...kMeriyahDefaultOptions, module: true
103
+ });
104
+
105
+ return body;
106
+ }
107
+
108
+ throw error;
109
+ }
110
+ }
111
+
87
112
  export { warnings };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nodesecure/js-x-ray",
3
- "version": "5.1.0",
3
+ "version": "6.0.0",
4
4
  "description": "JavaScript AST XRay analysis",
5
5
  "type": "module",
6
6
  "exports": "./index.js",
@@ -10,8 +10,9 @@
10
10
  "scripts": {
11
11
  "lint": "eslint src test",
12
12
  "prepublishOnly": "pkg-ok",
13
- "test": "cross-env esm-tape-runner 'test/**/*.spec.js' | tap-monkey",
14
- "check": "cross-env npm run lint && npm run test"
13
+ "test-only": "cross-env esm-tape-runner 'test/**/*.spec.js' | tap-monkey",
14
+ "test": "c8 --all --src ./src -r html npm run test-only",
15
+ "check": "cross-env npm run lint && npm run test-only"
15
16
  },
16
17
  "repository": {
17
18
  "type": "git",
@@ -38,21 +39,23 @@
38
39
  },
39
40
  "homepage": "https://github.com/NodeSecure/js-x-ray#readme",
40
41
  "dependencies": {
41
- "@nodesecure/sec-literal": "^1.1.0",
42
+ "@nodesecure/estree-ast-utils": "^1.3.0",
43
+ "@nodesecure/sec-literal": "^1.2.0",
42
44
  "estree-walker": "^3.0.1",
43
45
  "is-minified-code": "^2.0.0",
44
- "meriyah": "^4.3.0",
46
+ "meriyah": "^4.3.3",
45
47
  "safe-regex": "^2.1.1"
46
48
  },
47
49
  "devDependencies": {
48
- "@nodesecure/eslint-config": "^1.5.0",
50
+ "@nodesecure/eslint-config": "^1.6.0",
49
51
  "@slimio/is": "^1.5.1",
50
52
  "@small-tech/esm-tape-runner": "^2.0.0",
51
53
  "@small-tech/tap-monkey": "^1.4.0",
52
- "@types/node": "^18.7.13",
54
+ "@types/node": "^18.11.18",
55
+ "c8": "^7.12.0",
53
56
  "cross-env": "^7.0.3",
54
- "eslint": "^8.23.0",
57
+ "eslint": "^8.31.0",
55
58
  "pkg-ok": "^3.0.0",
56
- "tape": "^5.6.0"
59
+ "tape": "^5.6.1"
57
60
  }
58
61
  }
package/src/ASTDeps.js CHANGED
@@ -22,7 +22,7 @@ export default class ASTDeps {
22
22
  }
23
23
 
24
24
  add(depName, location = null, unsafe = false) {
25
- if (depName.trim() === "") {
25
+ if (typeof depName !== "string" || depName.trim() === "") {
26
26
  return;
27
27
  }
28
28
 
package/src/Analysis.js CHANGED
@@ -1,10 +1,10 @@
1
1
  // Import Third-party Dependencies
2
2
  import { Utils, Literal } from "@nodesecure/sec-literal";
3
+ import { VariableTracer } from "@nodesecure/estree-ast-utils";
3
4
 
4
5
  // Import Internal Dependencies
5
6
  import { rootLocation, toArrayLocation } from "./utils.js";
6
7
  import { generateWarning } from "./warnings.js";
7
- import { processMainModuleRequire } from "./constants.js";
8
8
  import ASTDeps from "./ASTDeps.js";
9
9
  import { isObfuscatedCode, hasTrojanSource } from "./obfuscators/index.js";
10
10
  import { runOnProbes } from "./probes/index.js";
@@ -16,6 +16,8 @@ const kDictionaryStrParts = [
16
16
  "0123456789"
17
17
  ];
18
18
 
19
+ const kMaximumEncodedLiterals = 10;
20
+
19
21
  export default class Analysis {
20
22
  hasDictionaryString = false;
21
23
  hasPrefixedIdentifiers = false;
@@ -33,29 +35,36 @@ export default class Analysis {
33
35
  identifiersName = [];
34
36
 
35
37
  constructor() {
36
- this.dependencies = new ASTDeps();
37
-
38
- this.identifiers = new Map();
39
- this.globalParts = new Map();
40
- this.handledEncodedLiteralValues = new Map();
38
+ this.tracer = new VariableTracer()
39
+ .enableDefaultTracing()
40
+ .trace("crypto.createHash", {
41
+ followConsecutiveAssignment: true, moduleName: "crypto"
42
+ });
41
43
 
42
- this.requireIdentifiers = new Set(["require", processMainModuleRequire]);
44
+ this.dependencies = new ASTDeps();
45
+ this.encodedLiterals = new Map();
43
46
  this.warnings = [];
44
47
  this.literalScores = [];
45
48
  }
46
49
 
47
50
  addWarning(name, value, location = rootLocation()) {
48
51
  const isEncodedLiteral = name === "encoded-literal";
49
- if (isEncodedLiteral && this.handledEncodedLiteralValues.has(value)) {
50
- const index = this.handledEncodedLiteralValues.get(value);
51
- this.warnings[index].location.push(toArrayLocation(location));
52
+ if (isEncodedLiteral) {
53
+ if (this.encodedLiterals.size > kMaximumEncodedLiterals) {
54
+ return;
55
+ }
52
56
 
53
- return;
57
+ if (this.encodedLiterals.has(value)) {
58
+ const index = this.encodedLiterals.get(value);
59
+ this.warnings[index].location.push(toArrayLocation(location));
60
+
61
+ return;
62
+ }
54
63
  }
55
64
 
56
65
  this.warnings.push(generateWarning(name, { value, location }));
57
66
  if (isEncodedLiteral) {
58
- this.handledEncodedLiteralValues.set(value, this.warnings.length - 1);
67
+ this.encodedLiterals.set(value, this.warnings.length - 1);
59
68
  }
60
69
  }
61
70
 
@@ -105,11 +114,12 @@ export default class Analysis {
105
114
  this.counter.identifiers = this.identifiersName.length;
106
115
  const [isObfuscated, kind] = isObfuscatedCode(this);
107
116
  if (isObfuscated) {
108
- this.addWarning("obfuscated-code", kind || "unknown");
117
+ this.addWarning("obfuscated-code", kind);
109
118
  }
110
119
 
111
120
  const identifiersLengthArr = this.identifiersName
112
- .filter((value) => value.type !== "property" && typeof value.name === "string").map((value) => value.name.length);
121
+ .filter((value) => value.type !== "property" && typeof value.name === "string")
122
+ .map((value) => value.name.length);
113
123
 
114
124
  const [idsLengthAvg, stringScore] = [sum(identifiersLengthArr), sum(this.literalScores)];
115
125
  if (!isMinified && identifiersLengthArr.length > 5 && idsLengthAvg <= 1.5) {
@@ -119,10 +129,18 @@ export default class Analysis {
119
129
  this.addWarning("suspicious-literal", stringScore);
120
130
  }
121
131
 
132
+ if (this.encodedLiterals.size > kMaximumEncodedLiterals) {
133
+ this.addWarning("suspicious-file", null);
134
+ this.warnings = this.warnings
135
+ .filter((warning) => warning.kind !== "encoded-literal");
136
+ }
137
+
122
138
  return { idsLengthAvg, stringScore, warnings: this.warnings };
123
139
  }
124
140
 
125
141
  walk(node) {
142
+ this.tracer.walk(node);
143
+
126
144
  // Detect TryStatement and CatchClause to known which dependency is required in a Try {} clause
127
145
  if (node.type === "TryStatement" && typeof node.handler !== "undefined") {
128
146
  this.dependencies.isInTryStmt = true;
@@ -1,9 +1,9 @@
1
- // Import Third-party Dependencies
2
- import { Utils } from "@nodesecure/sec-literal";
3
-
4
- export function verify(analysis, prefix) {
5
- const pValue = Object.keys(prefix).pop();
6
- const regexStr = `^${Utils.escapeRegExp(pValue)}[a-zA-Z]{1,2}[0-9]{0,2}$`;
7
-
8
- return analysis.identifiersName.every(({ name }) => new RegExp(regexStr).test(name));
9
- }
1
+ // Import Third-party Dependencies
2
+ import { Utils } from "@nodesecure/sec-literal";
3
+
4
+ export function verify(analysis, prefix) {
5
+ const pValue = Object.keys(prefix).pop();
6
+ const regexStr = `^${Utils.escapeRegExp(pValue)}[a-zA-Z]{1,2}[0-9]{0,2}$`;
7
+
8
+ return analysis.identifiersName.every(({ name }) => new RegExp(regexStr).test(name));
9
+ }
@@ -1,27 +1,27 @@
1
- // Require Internal Dependencies
2
- import { notNullOrUndefined } from "../utils.js";
3
-
4
- // CONSTANTS
5
- const kJJRegularSymbols = new Set(["$", "_"]);
6
-
7
- export function verify(analysis) {
8
- if (analysis.counter.variableDeclarator > 0 || analysis.counter.functionDeclaration > 0) {
9
- return false;
10
- }
11
- if (analysis.idtypes.assignExpr > analysis.idtypes.property) {
12
- return false;
13
- }
14
-
15
- const matchCount = analysis.identifiersName.filter(({ name }) => {
16
- if (!notNullOrUndefined(name)) {
17
- return false;
18
- }
19
- const charsCode = [...new Set([...name])];
20
-
21
- return charsCode.every((char) => kJJRegularSymbols.has(char));
22
- }).length;
23
- const pourcent = ((matchCount / analysis.identifiersName.length) * 100);
24
-
25
- return pourcent > 80;
26
- }
27
-
1
+ // Require Internal Dependencies
2
+ import { notNullOrUndefined } from "../utils.js";
3
+
4
+ // CONSTANTS
5
+ const kJJRegularSymbols = new Set(["$", "_"]);
6
+
7
+ export function verify(analysis) {
8
+ if (analysis.counter.variableDeclarator > 0 || analysis.counter.functionDeclaration > 0) {
9
+ return false;
10
+ }
11
+ if (analysis.idtypes.assignExpr > analysis.idtypes.property) {
12
+ return false;
13
+ }
14
+
15
+ const matchCount = analysis.identifiersName.filter(({ name }) => {
16
+ if (!notNullOrUndefined(name)) {
17
+ return false;
18
+ }
19
+ const charsCode = [...new Set([...name])];
20
+
21
+ return charsCode.every((char) => kJJRegularSymbols.has(char));
22
+ }).length;
23
+ const pourcent = ((matchCount / analysis.identifiersName.length) * 100);
24
+
25
+ return pourcent > 80;
26
+ }
27
+
@@ -1,11 +1,11 @@
1
- // CONSTANTS
2
- const kJSFuckMinimumDoubleUnaryExpr = 5;
3
-
4
- export function verify(analysis) {
5
- const hasZeroAssign = analysis.idtypes.assignExpr === 0
6
- && analysis.idtypes.functionDeclaration === 0
7
- && analysis.idtypes.property === 0
8
- && analysis.idtypes.variableDeclarator === 0;
9
-
10
- return hasZeroAssign && analysis.counter.doubleUnaryArray >= kJSFuckMinimumDoubleUnaryExpr;
11
- }
1
+ // CONSTANTS
2
+ const kJSFuckMinimumDoubleUnaryExpr = 5;
3
+
4
+ export function verify(analysis) {
5
+ const hasZeroAssign = analysis.idtypes.assignExpr === 0
6
+ && analysis.idtypes.functionDeclaration === 0
7
+ && analysis.idtypes.property === 0
8
+ && analysis.idtypes.variableDeclarator === 0;
9
+
10
+ return hasZeroAssign && analysis.counter.doubleUnaryArray >= kJSFuckMinimumDoubleUnaryExpr;
11
+ }
@@ -1,13 +1,13 @@
1
- export function verify(analysis) {
2
- if (analysis.counter.memberExpr > 0) {
3
- return false;
4
- }
5
-
6
- const hasSomePatterns = analysis.counter.doubleUnaryArray > 0
7
- || analysis.counter.deepBinaryExpr > 0
8
- || analysis.counter.encodedArrayValue > 0
9
- || analysis.hasDictionaryString;
10
-
11
- // TODO: hasPrefixedIdentifiers only work for hexadecimal id names generator
12
- return analysis.hasPrefixedIdentifiers && hasSomePatterns;
13
- }
1
+ export function verify(analysis) {
2
+ if (analysis.counter.memberExpr > 0) {
3
+ return false;
4
+ }
5
+
6
+ const hasSomePatterns = analysis.counter.doubleUnaryArray > 0
7
+ || analysis.counter.deepBinaryExpr > 0
8
+ || analysis.counter.encodedArrayValue > 0
9
+ || analysis.hasDictionaryString;
10
+
11
+ // TODO: hasPrefixedIdentifiers only work for hexadecimal id names generator
12
+ return analysis.hasPrefixedIdentifiers && hasSomePatterns;
13
+ }
@@ -1,7 +1,24 @@
1
- import { unsafeUnicodeControlCharacters } from "../constants.js";
1
+ /**
2
+ * Dangerous Unicode control characters that can be used by hackers
3
+ * to perform trojan source.
4
+ */
5
+ const kUnsafeUnicodeControlCharacters = [
6
+ "\u202A",
7
+ "\u202B",
8
+ "\u202D",
9
+ "\u202E",
10
+ "\u202C",
11
+ "\u2066",
12
+ "\u2067",
13
+ "\u2068",
14
+ "\u2069",
15
+ "\u200E",
16
+ "\u200F",
17
+ "\u061C"
18
+ ];
2
19
 
3
20
  export function verify(sourceString) {
4
- for (const unsafeCharacter of unsafeUnicodeControlCharacters) {
21
+ for (const unsafeCharacter of kUnsafeUnicodeControlCharacters) {
5
22
  if (sourceString.includes(unsafeCharacter)) {
6
23
  return true;
7
24
  }