@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/src/probes/index.js
CHANGED
|
@@ -1,68 +1,70 @@
|
|
|
1
|
-
// Import all the probes
|
|
2
|
-
import isUnsafeCallee from "./isUnsafeCallee.js";
|
|
3
|
-
import isLiteral from "./isLiteral.js";
|
|
4
|
-
import isLiteralRegex from "./isLiteralRegex.js";
|
|
5
|
-
import isRegexObject from "./isRegexObject.js";
|
|
6
|
-
import isVariableDeclaration from "./isVariableDeclaration.js";
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
import
|
|
14
|
-
import
|
|
15
|
-
import
|
|
16
|
-
import
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
isRequire,
|
|
27
|
-
isImportDeclaration,
|
|
28
|
-
isMemberExpression,
|
|
29
|
-
isAssignmentExpression,
|
|
30
|
-
isObjectExpression,
|
|
31
|
-
isArrayExpression,
|
|
32
|
-
|
|
33
|
-
isUnaryExpression,
|
|
34
|
-
isWeakCrypto
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
1
|
+
// Import all the probes
|
|
2
|
+
import isUnsafeCallee from "./isUnsafeCallee.js";
|
|
3
|
+
import isLiteral from "./isLiteral.js";
|
|
4
|
+
import isLiteralRegex from "./isLiteralRegex.js";
|
|
5
|
+
import isRegexObject from "./isRegexObject.js";
|
|
6
|
+
import isVariableDeclaration from "./isVariableDeclaration.js";
|
|
7
|
+
import isRequire from "./isRequire.js";
|
|
8
|
+
import isImportDeclaration from "./isImportDeclaration.js";
|
|
9
|
+
import isMemberExpression from "./isMemberExpression.js";
|
|
10
|
+
import isArrayExpression from "./isArrayExpression.js";
|
|
11
|
+
import isFunction from "./isFunction.js";
|
|
12
|
+
import isAssignmentExpression from "./isAssignmentExpression.js";
|
|
13
|
+
import isObjectExpression from "./isObjectExpression.js";
|
|
14
|
+
import isUnaryExpression from "./isUnaryExpression.js";
|
|
15
|
+
import isWeakCrypto from "./isWeakCrypto.js";
|
|
16
|
+
import isClassDeclaration from "./isClassDeclaration.js";
|
|
17
|
+
import isMethodDefinition from "./isMethodDefinition.js";
|
|
18
|
+
|
|
19
|
+
// CONSTANTS
|
|
20
|
+
const kListOfProbes = [
|
|
21
|
+
isUnsafeCallee,
|
|
22
|
+
isLiteral,
|
|
23
|
+
isLiteralRegex,
|
|
24
|
+
isRegexObject,
|
|
25
|
+
isVariableDeclaration,
|
|
26
|
+
isRequire,
|
|
27
|
+
isImportDeclaration,
|
|
28
|
+
isMemberExpression,
|
|
29
|
+
isAssignmentExpression,
|
|
30
|
+
isObjectExpression,
|
|
31
|
+
isArrayExpression,
|
|
32
|
+
isFunction,
|
|
33
|
+
isUnaryExpression,
|
|
34
|
+
isWeakCrypto,
|
|
35
|
+
isClassDeclaration,
|
|
36
|
+
isMethodDefinition
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
const kSymBreak = Symbol.for("breakWalk");
|
|
40
|
+
const kSymSkip = Symbol.for("skipWalk");
|
|
41
|
+
|
|
42
|
+
export function runOnProbes(node, analysis) {
|
|
43
|
+
const breakedGroups = new Set();
|
|
44
|
+
|
|
45
|
+
for (const probe of kListOfProbes) {
|
|
46
|
+
if (breakedGroups.has(probe.breakGroup)) {
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const [isMatching, data = null] = probe.validateNode(node, analysis);
|
|
51
|
+
if (isMatching) {
|
|
52
|
+
const result = probe.main(node, { analysis, data });
|
|
53
|
+
|
|
54
|
+
if (result === kSymSkip) {
|
|
55
|
+
return "skip";
|
|
56
|
+
}
|
|
57
|
+
if (result === kSymBreak || probe.breakOnMatch) {
|
|
58
|
+
const breakGroup = probe.breakGroup || null;
|
|
59
|
+
if (breakGroup === null) {
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
breakedGroups.add(breakGroup);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
// Import Internal Dependencies
|
|
2
|
+
import { extractNode } from "../utils.js";
|
|
3
|
+
|
|
4
|
+
// CONSTANTS
|
|
5
|
+
const kLiteralExtractor = extractNode("Literal");
|
|
6
|
+
|
|
1
7
|
/**
|
|
2
8
|
* @description Search for ArrayExpression AST Node (Commonly known as JS Arrays)
|
|
3
9
|
*
|
|
@@ -11,14 +17,11 @@ function validateNode(node) {
|
|
|
11
17
|
];
|
|
12
18
|
}
|
|
13
19
|
|
|
14
|
-
function main(node,
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
analysis.analyzeLiteral(elem, true);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
20
|
+
function main(node, { analysis }) {
|
|
21
|
+
kLiteralExtractor(
|
|
22
|
+
(literalNode) => analysis.analyzeLiteral(literalNode, true),
|
|
23
|
+
node.elements
|
|
24
|
+
);
|
|
22
25
|
}
|
|
23
26
|
|
|
24
27
|
export default {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
// Import
|
|
2
|
-
import {
|
|
1
|
+
// Import Third-party Dependencies
|
|
2
|
+
import { getVariableDeclarationIdentifiers } from "@nodesecure/estree-ast-utils";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* @description Search for AssignmentExpression (Not to be confused with AssignmentPattern).
|
|
@@ -18,7 +18,7 @@ function main(node, options) {
|
|
|
18
18
|
const { analysis } = options;
|
|
19
19
|
|
|
20
20
|
analysis.idtypes.assignExpr++;
|
|
21
|
-
for (const name of
|
|
21
|
+
for (const { name } of getVariableDeclarationIdentifiers(node.left)) {
|
|
22
22
|
analysis.identifiersName.push({ name, type: "assignExpr" });
|
|
23
23
|
}
|
|
24
24
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// Import Internal Dependencies
|
|
2
|
+
import { extractNode } from "../utils.js";
|
|
3
|
+
|
|
4
|
+
// CONSTANTS
|
|
5
|
+
const kIdExtractor = extractNode("Identifier");
|
|
6
|
+
|
|
7
|
+
function validateNode(node) {
|
|
8
|
+
return [
|
|
9
|
+
node.type === "ClassDeclaration"
|
|
10
|
+
];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function main(node, options) {
|
|
14
|
+
const { analysis } = options;
|
|
15
|
+
|
|
16
|
+
kIdExtractor(
|
|
17
|
+
({ name }) => analysis.identifiersName.push({ name, type: "class" }),
|
|
18
|
+
[node.id, node.superClass]
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export default {
|
|
23
|
+
name: "isClassDeclaration",
|
|
24
|
+
validateNode, main, breakOnMatch: false
|
|
25
|
+
};
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
// Import Internal Dependencies
|
|
2
|
+
import { extractNode } from "../utils.js";
|
|
3
|
+
|
|
4
|
+
// CONSTANTS
|
|
5
|
+
const kIdExtractor = extractNode("Identifier");
|
|
6
|
+
|
|
1
7
|
/**
|
|
2
8
|
* @description Search for FunctionDeclaration AST Node.
|
|
3
9
|
*
|
|
@@ -7,13 +13,18 @@
|
|
|
7
13
|
*/
|
|
8
14
|
function validateNode(node) {
|
|
9
15
|
return [
|
|
10
|
-
node.type === "FunctionDeclaration"
|
|
16
|
+
node.type === "FunctionDeclaration" || node.type === "FunctionExpression"
|
|
11
17
|
];
|
|
12
18
|
}
|
|
13
19
|
|
|
14
20
|
function main(node, options) {
|
|
15
21
|
const { analysis } = options;
|
|
16
22
|
|
|
23
|
+
kIdExtractor(
|
|
24
|
+
({ name }) => analysis.identifiersName.push({ name, type: "params" }),
|
|
25
|
+
node.params
|
|
26
|
+
);
|
|
27
|
+
|
|
17
28
|
if (node.id === null || node.id.type !== "Identifier") {
|
|
18
29
|
return;
|
|
19
30
|
}
|
package/src/probes/isLiteral.js
CHANGED
|
@@ -1,52 +1,49 @@
|
|
|
1
|
-
// Import Node.js Dependencies
|
|
2
|
-
import { builtinModules } from "repl";
|
|
3
|
-
|
|
4
|
-
// Import Third-party Dependencies
|
|
5
|
-
import { Hex } from "@nodesecure/sec-literal";
|
|
6
|
-
|
|
7
|
-
//
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
*
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
analysis.addWarning("
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
name: "isLiteral",
|
|
51
|
-
validateNode, main, breakOnMatch: false
|
|
52
|
-
};
|
|
1
|
+
// Import Node.js Dependencies
|
|
2
|
+
import { builtinModules } from "repl";
|
|
3
|
+
|
|
4
|
+
// Import Third-party Dependencies
|
|
5
|
+
import { Hex } from "@nodesecure/sec-literal";
|
|
6
|
+
|
|
7
|
+
// CONSTANTS
|
|
8
|
+
const kNodeDeps = new Set(builtinModules);
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @description Search for Literal AST Node
|
|
12
|
+
* @see https://github.com/estree/estree/blob/master/es5.md#literal
|
|
13
|
+
* @example
|
|
14
|
+
* "foobar"
|
|
15
|
+
*/
|
|
16
|
+
function validateNode(node) {
|
|
17
|
+
return [
|
|
18
|
+
node.type === "Literal" && typeof node.value === "string"
|
|
19
|
+
];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function main(node, options) {
|
|
23
|
+
const { analysis } = options;
|
|
24
|
+
|
|
25
|
+
// We are searching for value obfuscated as hex of a minimum length of 4.
|
|
26
|
+
if (/^[0-9A-Fa-f]{4,}$/g.test(node.value)) {
|
|
27
|
+
const value = Buffer.from(node.value, "hex").toString();
|
|
28
|
+
analysis.analyzeString(value);
|
|
29
|
+
|
|
30
|
+
// If the value we are retrieving is the name of a Node.js dependency,
|
|
31
|
+
// then we add it to the dependencies list and we throw an unsafe-import at the current location.
|
|
32
|
+
if (kNodeDeps.has(value)) {
|
|
33
|
+
analysis.dependencies.add(value, node.loc);
|
|
34
|
+
analysis.addWarning("unsafe-import", null, node.loc);
|
|
35
|
+
}
|
|
36
|
+
else if (value === "require" || !Hex.isSafe(node.value)) {
|
|
37
|
+
analysis.addWarning("encoded-literal", node.value, node.loc);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// Else we are checking all other string with our suspect method
|
|
41
|
+
else {
|
|
42
|
+
analysis.analyzeLiteral(node);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export default {
|
|
47
|
+
name: "isLiteral",
|
|
48
|
+
validateNode, main, breakOnMatch: false
|
|
49
|
+
};
|
|
@@ -1,31 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
// retrieve the member name, like: foo.bar.hello
|
|
18
|
-
// in our case we are searching for process.mainModule.*
|
|
19
|
-
const memberName = getMemberExprName(node);
|
|
20
|
-
|
|
21
|
-
if (memberName.startsWith(processMainModuleRequire)) {
|
|
22
|
-
analysis.dependencies.add(memberName.slice(processMainModuleRequire.length), node.loc);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// TODO: require.main ?
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export default {
|
|
29
|
-
name: "isMemberExpression",
|
|
30
|
-
validateNode, main, breakOnMatch: true, breakGroup: "import"
|
|
31
|
-
};
|
|
1
|
+
function validateNode(node) {
|
|
2
|
+
return [
|
|
3
|
+
node.type === "MemberExpression"
|
|
4
|
+
];
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function main(node, options) {
|
|
8
|
+
const { analysis } = options;
|
|
9
|
+
|
|
10
|
+
analysis.counter[node.computed ? "computedMemberExpr" : "memberExpr"]++;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export default {
|
|
14
|
+
name: "isMemberExpression",
|
|
15
|
+
validateNode, main, breakOnMatch: true, breakGroup: "import"
|
|
16
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// Import Internal Dependencies
|
|
2
|
+
import { extractNode } from "../utils.js";
|
|
3
|
+
|
|
4
|
+
// CONSTANTS
|
|
5
|
+
const kIdExtractor = extractNode("Identifier");
|
|
6
|
+
|
|
7
|
+
function validateNode(node) {
|
|
8
|
+
return [
|
|
9
|
+
node.type === "MethodDefinition"
|
|
10
|
+
];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function main(node, options) {
|
|
14
|
+
const { analysis } = options;
|
|
15
|
+
|
|
16
|
+
kIdExtractor(
|
|
17
|
+
({ name }) => analysis.identifiersName.push({ name, type: "method" }),
|
|
18
|
+
[node.key]
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export default {
|
|
23
|
+
name: "isMethodDefinition",
|
|
24
|
+
validateNode, main, breakOnMatch: false
|
|
25
|
+
};
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
// Import Internal Dependencies
|
|
2
|
-
import { isLiteralRegex } from "../utils.js";
|
|
3
|
-
|
|
4
1
|
// Import Third-party Dependencies
|
|
2
|
+
import { isLiteralRegex } from "@nodesecure/estree-ast-utils";
|
|
5
3
|
import safeRegex from "safe-regex";
|
|
6
4
|
|
|
7
5
|
/**
|
|
@@ -20,6 +18,13 @@ function main(node, options) {
|
|
|
20
18
|
const { analysis } = options;
|
|
21
19
|
|
|
22
20
|
const arg = node.arguments[0];
|
|
21
|
+
/**
|
|
22
|
+
* Note: RegExp Object can contain a RegExpLiteral
|
|
23
|
+
* @see https://github.com/estree/estree/blob/master/es5.md#regexpliteral
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* new RegExp(/^foo/)
|
|
27
|
+
*/
|
|
23
28
|
const pattern = isLiteralRegex(arg) ? arg.regex.pattern : arg.value;
|
|
24
29
|
|
|
25
30
|
// We use the safe-regex package to detect whether or not regex is safe!
|
package/src/probes/isRequire.js
CHANGED
|
@@ -1,54 +1,46 @@
|
|
|
1
1
|
/* eslint-disable consistent-return */
|
|
2
2
|
|
|
3
|
-
// Import Internal Dependencies
|
|
4
|
-
import { isRequireGlobalMemberExpr, getMemberExprName, arrExprToString, concatBinaryExpr } from "../utils.js";
|
|
5
|
-
|
|
6
3
|
// Import Third-party Dependencies
|
|
7
4
|
import { Hex } from "@nodesecure/sec-literal";
|
|
8
5
|
import { walk } from "estree-walker";
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
return false;
|
|
6
|
+
import {
|
|
7
|
+
concatBinaryExpression,
|
|
8
|
+
arrayExpressionToString,
|
|
9
|
+
getMemberExpressionIdentifier,
|
|
10
|
+
getCallExpressionIdentifier
|
|
11
|
+
} from "@nodesecure/estree-ast-utils";
|
|
12
|
+
|
|
13
|
+
function validateNode(node, { tracer }) {
|
|
14
|
+
const id = getCallExpressionIdentifier(node);
|
|
15
|
+
if (id === null) {
|
|
16
|
+
return [false];
|
|
21
17
|
}
|
|
22
18
|
|
|
23
|
-
|
|
24
|
-
}
|
|
19
|
+
const data = tracer.getDataFromIdentifier(id);
|
|
25
20
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
return isRequireGlobalMemberExpr(getMemberExprName(node.callee));
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function isRequireIdentifiers(node, analysis) {
|
|
35
|
-
if (node.type !== "CallExpression") {
|
|
36
|
-
return false;
|
|
37
|
-
}
|
|
38
|
-
const fullName = node.callee.type === "MemberExpression" ? getMemberExprName(node.callee) : node.callee.name;
|
|
39
|
-
|
|
40
|
-
return analysis.requireIdentifiers.has(fullName);
|
|
21
|
+
return [
|
|
22
|
+
data !== null && data.name === "require",
|
|
23
|
+
data?.identifierOrMemberExpr ?? void 0
|
|
24
|
+
];
|
|
41
25
|
}
|
|
42
26
|
|
|
43
27
|
function main(node, options) {
|
|
44
28
|
const { analysis } = options;
|
|
29
|
+
const { tracer } = analysis;
|
|
30
|
+
|
|
31
|
+
if (node.arguments.length === 0) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const arg = node.arguments.at(0);
|
|
45
35
|
|
|
46
|
-
const arg = node.arguments[0];
|
|
47
36
|
switch (arg.type) {
|
|
48
37
|
// const foo = "http"; require(foo);
|
|
49
38
|
case "Identifier":
|
|
50
|
-
if (analysis.
|
|
51
|
-
analysis.dependencies.add(
|
|
39
|
+
if (analysis.tracer.literalIdentifiers.has(arg.name)) {
|
|
40
|
+
analysis.dependencies.add(
|
|
41
|
+
analysis.tracer.literalIdentifiers.get(arg.name),
|
|
42
|
+
node.loc
|
|
43
|
+
);
|
|
52
44
|
}
|
|
53
45
|
else {
|
|
54
46
|
analysis.addWarning("unsafe-import", null, node.loc);
|
|
@@ -60,9 +52,12 @@ function main(node, options) {
|
|
|
60
52
|
analysis.dependencies.add(arg.value, node.loc);
|
|
61
53
|
break;
|
|
62
54
|
|
|
63
|
-
// require(["ht"
|
|
55
|
+
// require(["ht", "tp"])
|
|
64
56
|
case "ArrayExpression": {
|
|
65
|
-
const value =
|
|
57
|
+
const value = [...arrayExpressionToString(arg, { tracer })]
|
|
58
|
+
.join("")
|
|
59
|
+
.trim();
|
|
60
|
+
|
|
66
61
|
if (value === "") {
|
|
67
62
|
analysis.addWarning("unsafe-import", null, node.loc);
|
|
68
63
|
}
|
|
@@ -75,23 +70,27 @@ function main(node, options) {
|
|
|
75
70
|
// require("ht" + "tp");
|
|
76
71
|
case "BinaryExpression": {
|
|
77
72
|
if (arg.operator !== "+") {
|
|
73
|
+
analysis.addWarning("unsafe-import", null, node.loc);
|
|
78
74
|
break;
|
|
79
75
|
}
|
|
80
76
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
77
|
+
try {
|
|
78
|
+
const iter = concatBinaryExpression(arg, {
|
|
79
|
+
tracer, stopOnUnsupportedNode: true
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
analysis.dependencies.add([...iter].join(""), node.loc);
|
|
84
83
|
}
|
|
85
|
-
|
|
86
|
-
analysis.
|
|
84
|
+
catch {
|
|
85
|
+
analysis.addWarning("unsafe-import", null, node.loc);
|
|
87
86
|
}
|
|
88
87
|
break;
|
|
89
88
|
}
|
|
90
89
|
|
|
91
90
|
// require(Buffer.from("...", "hex").toString());
|
|
92
91
|
case "CallExpression": {
|
|
93
|
-
|
|
94
|
-
|
|
92
|
+
walkRequireCallExpression(arg)
|
|
93
|
+
.forEach((depName) => analysis.dependencies.add(depName, node.loc, true));
|
|
95
94
|
|
|
96
95
|
analysis.addWarning("unsafe-import", null, node.loc);
|
|
97
96
|
|
|
@@ -104,7 +103,7 @@ function main(node, options) {
|
|
|
104
103
|
}
|
|
105
104
|
}
|
|
106
105
|
|
|
107
|
-
function
|
|
106
|
+
function walkRequireCallExpression(nodeToWalk) {
|
|
108
107
|
const dependencies = new Set();
|
|
109
108
|
|
|
110
109
|
walk(nodeToWalk, {
|
|
@@ -113,34 +112,30 @@ function parseRequireCallExpression(nodeToWalk) {
|
|
|
113
112
|
return;
|
|
114
113
|
}
|
|
115
114
|
|
|
116
|
-
|
|
117
|
-
|
|
115
|
+
const rootArgument = node.arguments.at(0);
|
|
116
|
+
if (rootArgument.type === "Literal" && Hex.isHex(rootArgument.value)) {
|
|
117
|
+
dependencies.add(Buffer.from(rootArgument.value, "hex").toString());
|
|
118
118
|
|
|
119
119
|
return this.skip();
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
const fullName = node.callee.type === "MemberExpression" ?
|
|
122
|
+
const fullName = node.callee.type === "MemberExpression" ?
|
|
123
|
+
[...getMemberExpressionIdentifier(node.callee)].join(".") :
|
|
124
|
+
node.callee.name;
|
|
125
|
+
|
|
123
126
|
switch (fullName) {
|
|
124
127
|
case "Buffer.from": {
|
|
125
|
-
const [element
|
|
128
|
+
const [element] = node.arguments;
|
|
126
129
|
|
|
127
130
|
if (element.type === "ArrayExpression") {
|
|
128
|
-
const depName =
|
|
129
|
-
|
|
130
|
-
dependencies.add(depName);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
else if (element.type === "Literal" && convert.type === "Literal" && convert.value === "hex") {
|
|
134
|
-
const value = Buffer.from(element.value, "hex").toString();
|
|
135
|
-
dependencies.add(value);
|
|
131
|
+
const depName = [...arrayExpressionToString(element)].join("").trim();
|
|
132
|
+
dependencies.add(depName);
|
|
136
133
|
}
|
|
137
134
|
break;
|
|
138
135
|
}
|
|
139
136
|
case "require.resolve": {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
if (element.type === "Literal") {
|
|
143
|
-
dependencies.add(element.value);
|
|
137
|
+
if (rootArgument.type === "Literal") {
|
|
138
|
+
dependencies.add(rootArgument.value);
|
|
144
139
|
}
|
|
145
140
|
break;
|
|
146
141
|
}
|
|
@@ -148,9 +143,7 @@ function parseRequireCallExpression(nodeToWalk) {
|
|
|
148
143
|
}
|
|
149
144
|
});
|
|
150
145
|
|
|
151
|
-
return
|
|
152
|
-
dependencies: [...dependencies]
|
|
153
|
-
};
|
|
146
|
+
return [...dependencies];
|
|
154
147
|
}
|
|
155
148
|
|
|
156
149
|
export default {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//
|
|
1
|
+
// Import Internal Dependencies
|
|
2
2
|
import { isUnsafeCallee } from "../utils.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -15,6 +15,8 @@ function main(node, options) {
|
|
|
15
15
|
const { analysis, data: calleeName } = options;
|
|
16
16
|
|
|
17
17
|
analysis.addWarning("unsafe-stmt", calleeName, node.loc);
|
|
18
|
+
|
|
19
|
+
return Symbol.for("skipWalk");
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
export default {
|