@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 +21 -21
- package/README.md +29 -20
- package/index.d.ts +3 -3
- package/index.js +34 -9
- package/package.json +12 -9
- package/src/ASTDeps.js +1 -1
- package/src/Analysis.js +32 -14
- package/src/obfuscators/freejsobfuscator.js +9 -9
- package/src/obfuscators/jjencode.js +27 -27
- package/src/obfuscators/jsfuck.js +11 -11
- package/src/obfuscators/obfuscator-io.js +13 -13
- package/src/obfuscators/trojan-source.js +19 -2
- package/src/probes/index.js +70 -68
- package/src/probes/isArrayExpression.js +11 -8
- package/src/probes/isAssignmentExpression.js +3 -3
- package/src/probes/isClassDeclaration.js +25 -0
- package/src/probes/{isFunctionDeclaration.js → isFunction.js} +12 -1
- package/src/probes/isLiteral.js +49 -52
- package/src/probes/isLiteralRegex.js +1 -3
- package/src/probes/isMemberExpression.js +16 -31
- package/src/probes/isMethodDefinition.js +25 -0
- package/src/probes/isRegexObject.js +8 -3
- package/src/probes/isRequire.js +57 -64
- package/src/probes/isUnsafeCallee.js +3 -1
- package/src/probes/isVariableDeclaration.js +30 -104
- package/src/probes/isWeakCrypto.js +19 -15
- package/src/utils.js +25 -147
- package/src/warnings.js +5 -4
- package/types/api.d.ts +2 -2
- package/types/warnings.d.ts +1 -1
- package/src/constants.js +0 -35
- package/src/probes/isAssignmentExprOrMemberExpr.js +0 -23
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
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-

|
|
6
|
+
[](https://github.com/NodeSecure/js-x-ray/blob/master/LICENSE)
|
|
7
|
+
[](https://api.securityscorecards.dev/projects/github.com/NodeSecure/js-x-ray)
|
|
9
|
+

|
|
10
|
+

|
|
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
|
-
[](#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
|
-
<
|
|
191
|
-
<
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
<
|
|
201
|
-
|
|
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
|
|
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 =
|
|
63
|
+
const isMin = filePathString.includes(".min") || isMinified(str);
|
|
62
64
|
const data = runASTAnalysis(str, {
|
|
63
65
|
isMinified: isMin,
|
|
64
|
-
module: path.extname(
|
|
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": "
|
|
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
|
-
"
|
|
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/
|
|
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.
|
|
46
|
+
"meriyah": "^4.3.3",
|
|
45
47
|
"safe-regex": "^2.1.1"
|
|
46
48
|
},
|
|
47
49
|
"devDependencies": {
|
|
48
|
-
"@nodesecure/eslint-config": "^1.
|
|
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.
|
|
54
|
+
"@types/node": "^18.11.18",
|
|
55
|
+
"c8": "^7.12.0",
|
|
53
56
|
"cross-env": "^7.0.3",
|
|
54
|
-
"eslint": "^8.
|
|
57
|
+
"eslint": "^8.31.0",
|
|
55
58
|
"pkg-ok": "^3.0.0",
|
|
56
|
-
"tape": "^5.6.
|
|
59
|
+
"tape": "^5.6.1"
|
|
57
60
|
}
|
|
58
61
|
}
|
package/src/ASTDeps.js
CHANGED
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.
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
this.tracer = new VariableTracer()
|
|
39
|
+
.enableDefaultTracing()
|
|
40
|
+
.trace("crypto.createHash", {
|
|
41
|
+
followConsecutiveAssignment: true, moduleName: "crypto"
|
|
42
|
+
});
|
|
41
43
|
|
|
42
|
-
this.
|
|
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
|
|
50
|
-
|
|
51
|
-
|
|
52
|
+
if (isEncodedLiteral) {
|
|
53
|
+
if (this.encodedLiterals.size > kMaximumEncodedLiterals) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
52
56
|
|
|
53
|
-
|
|
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.
|
|
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
|
|
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")
|
|
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
|
-
|
|
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
|
|
21
|
+
for (const unsafeCharacter of kUnsafeUnicodeControlCharacters) {
|
|
5
22
|
if (sourceString.includes(unsafeCharacter)) {
|
|
6
23
|
return true;
|
|
7
24
|
}
|