@nodesecure/js-x-ray 4.5.0 → 5.1.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/README.md +26 -25
- package/index.d.ts +35 -140
- package/index.js +2 -56
- package/package.json +7 -6
- package/src/Analysis.js +14 -27
- package/src/constants.js +0 -13
- package/src/probes/index.js +68 -68
- package/src/probes/isImportDeclaration.js +1 -4
- package/src/probes/isLiteral.js +3 -3
- package/src/probes/isLiteralRegex.js +1 -2
- package/src/probes/isRegexObject.js +1 -2
- package/src/probes/isRequire.js +159 -160
- package/src/probes/isUnsafeCallee.js +1 -2
- package/src/probes/isVariableDeclaration.js +104 -104
- package/src/probes/isWeakCrypto.js +4 -7
- package/src/utils.js +0 -22
- package/src/warnings.js +70 -0
- package/types/api.d.ts +44 -0
- package/types/astdeps.d.ts +33 -0
- package/types/warnings.d.ts +33 -0
package/README.md
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
# js-x-ray
|
|
2
2
|

|
|
3
3
|
[](https://github.com/NodeSecure/js-x-ray/commit-activity)
|
|
4
|
-
[](https://github.com/nodejs/security-wg/blob/master/processes/responsible_disclosure_template.md
|
|
5
|
-
)
|
|
6
4
|
[](https://github.com/NodeSecure/js-x-ray/blob/master/LICENSE)
|
|
7
5
|

|
|
8
6
|
|
|
@@ -77,24 +75,23 @@ The analysis will return: `http` (in try), `crypto`, `util` and `fs`.
|
|
|
77
75
|
|
|
78
76
|
This section describes how use `warnings` export.
|
|
79
77
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
});
|
|
78
|
+
```ts
|
|
79
|
+
type WarningName = "parsing-error"
|
|
80
|
+
| "encoded-literal"
|
|
81
|
+
| "unsafe-regex"
|
|
82
|
+
| "unsafe-stmt"
|
|
83
|
+
| "unsafe-assign"
|
|
84
|
+
| "short-identifiers"
|
|
85
|
+
| "suspicious-literal"
|
|
86
|
+
| "obfuscated-code"
|
|
87
|
+
| "weak-crypto"
|
|
88
|
+
| "unsafe-import";
|
|
89
|
+
|
|
90
|
+
declare const warnings: Record<WarningName, {
|
|
91
|
+
i18n: string;
|
|
92
|
+
severity: "Information" | "Warning" | "Critical";
|
|
93
|
+
experimental?: boolean;
|
|
94
|
+
}>;
|
|
98
95
|
```
|
|
99
96
|
|
|
100
97
|
We make a call to `i18n` through the package `NodeSecure/i18n` to get the translation.
|
|
@@ -103,7 +100,7 @@ We make a call to `i18n` through the package `NodeSecure/i18n` to get the transl
|
|
|
103
100
|
import * as jsxray from "@nodesecure/js-x-ray";
|
|
104
101
|
import * as i18n from "@nodesecure/i18n";
|
|
105
102
|
|
|
106
|
-
console.log(i18n.getToken(jsxray.warnings.
|
|
103
|
+
console.log(i18n.getToken(jsxray.warnings["parsing-error"].i18n));
|
|
107
104
|
```
|
|
108
105
|
|
|
109
106
|
## Warnings Legends
|
|
@@ -142,7 +139,7 @@ The method take a first argument which is the code you want to analyse. It will
|
|
|
142
139
|
```ts
|
|
143
140
|
interface Report {
|
|
144
141
|
dependencies: ASTDeps;
|
|
145
|
-
warnings: Warning
|
|
142
|
+
warnings: Warning[];
|
|
146
143
|
idsLengthAvg: number;
|
|
147
144
|
stringScore: number;
|
|
148
145
|
isOneLineRequire: boolean;
|
|
@@ -166,12 +163,12 @@ Run the SAST scanner on a given JavaScript file.
|
|
|
166
163
|
```ts
|
|
167
164
|
export type ReportOnFile = {
|
|
168
165
|
ok: true,
|
|
169
|
-
warnings: Warning
|
|
166
|
+
warnings: Warning[];
|
|
170
167
|
dependencies: ASTDeps;
|
|
171
168
|
isMinified: boolean;
|
|
172
169
|
} | {
|
|
173
170
|
ok: false,
|
|
174
|
-
warnings: Warning
|
|
171
|
+
warnings: Warning[];
|
|
175
172
|
}
|
|
176
173
|
```
|
|
177
174
|
|
|
@@ -181,7 +178,7 @@ export type ReportOnFile = {
|
|
|
181
178
|
## Contributors ✨
|
|
182
179
|
|
|
183
180
|
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
|
184
|
-
[](#contributors-)
|
|
185
182
|
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
|
186
183
|
|
|
187
184
|
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
|
|
@@ -197,6 +194,10 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
|
|
197
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>
|
|
198
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>
|
|
199
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>
|
|
200
201
|
</tr>
|
|
201
202
|
</table>
|
|
202
203
|
|
package/index.d.ts
CHANGED
|
@@ -1,140 +1,35 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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
|
-
idsLengthAvg: number;
|
|
37
|
-
stringScore: number;
|
|
38
|
-
isOneLineRequire: boolean;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
interface SourceLocation {
|
|
42
|
-
start: {
|
|
43
|
-
line: number;
|
|
44
|
-
column: number;
|
|
45
|
-
};
|
|
46
|
-
end: {
|
|
47
|
-
line: number;
|
|
48
|
-
column: number;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
interface Dependency {
|
|
53
|
-
unsafe: boolean;
|
|
54
|
-
inTry: boolean;
|
|
55
|
-
location?: SourceLocation;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
interface WarningsNames {
|
|
59
|
-
parsingError: {
|
|
60
|
-
code: "ast-error",
|
|
61
|
-
i18n: "sast_warnings.ast_error",
|
|
62
|
-
severity: "Information"
|
|
63
|
-
},
|
|
64
|
-
unsafeImport: {
|
|
65
|
-
code: "unsafe-import",
|
|
66
|
-
i18n: "sast_warnings.unsafe_import",
|
|
67
|
-
severity: "Warning"
|
|
68
|
-
},
|
|
69
|
-
unsafeRegex: {
|
|
70
|
-
code: "unsafe-regex",
|
|
71
|
-
i18n: "sast_warnings.unsafe_regex",
|
|
72
|
-
severity: "Warning"
|
|
73
|
-
},
|
|
74
|
-
unsafeStmt: {
|
|
75
|
-
code: "unsafe-stmt",
|
|
76
|
-
i18n: "sast_warnings.unsafe_stmt",
|
|
77
|
-
severity: "Warning"
|
|
78
|
-
},
|
|
79
|
-
unsafeAssign: {
|
|
80
|
-
code: "unsafe-assign",
|
|
81
|
-
i18n: "sast_warnings.unsafe_assign",
|
|
82
|
-
severity: "Warning"
|
|
83
|
-
},
|
|
84
|
-
encodedLiteral: {
|
|
85
|
-
code: "encoded-literal",
|
|
86
|
-
i18n: "sast_warnings.encoded_literal",
|
|
87
|
-
severity: "Information"
|
|
88
|
-
},
|
|
89
|
-
shortIdentifiers: {
|
|
90
|
-
code: "short-identifiers",
|
|
91
|
-
i18n: "sast_warnings.short_identifiers",
|
|
92
|
-
severity: "Warning"
|
|
93
|
-
},
|
|
94
|
-
suspiciousLiteral: {
|
|
95
|
-
code: "suspicious-literal",
|
|
96
|
-
i18n: "sast_warnings.suspicious_literal",
|
|
97
|
-
severity: "Warning"
|
|
98
|
-
},
|
|
99
|
-
obfuscatedCode: {
|
|
100
|
-
code: "obfuscated-code",
|
|
101
|
-
i18n: "sast_warnings.obfuscated_code",
|
|
102
|
-
severity: "Critical"
|
|
103
|
-
},
|
|
104
|
-
weakCrypto: {
|
|
105
|
-
code: "weak-crypto",
|
|
106
|
-
i18n: "sast_warnings.weak_crypto",
|
|
107
|
-
severity: "Information",
|
|
108
|
-
experimental: true
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
interface RuntimeOptions {
|
|
113
|
-
module?: boolean;
|
|
114
|
-
isMinified?: boolean;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
export function runASTAnalysis(str: string, options?: RuntimeOptions): Report;
|
|
118
|
-
|
|
119
|
-
export type ReportOnFile = {
|
|
120
|
-
ok: true,
|
|
121
|
-
warnings: Warning<BaseWarning>[];
|
|
122
|
-
dependencies: ASTDeps;
|
|
123
|
-
isMinified: boolean;
|
|
124
|
-
} | {
|
|
125
|
-
ok: false,
|
|
126
|
-
warnings: Warning<BaseWarning>[];
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
export interface RuntimeFileOptions {
|
|
130
|
-
packageName?: string;
|
|
131
|
-
module?: boolean;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
export function runASTAnalysisOnFile(pathToFile: string, options?: RuntimeFileOptions): Promise<ReportOnFile>;
|
|
135
|
-
|
|
136
|
-
export const warnings: WarningsNames;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
export = JSXRay;
|
|
140
|
-
export as namespace JSXRay;
|
|
1
|
+
import {
|
|
2
|
+
runASTAnalysis,
|
|
3
|
+
runASTAnalysisOnFile,
|
|
4
|
+
Report,
|
|
5
|
+
ReportOnFile,
|
|
6
|
+
RuntimeFileOptions,
|
|
7
|
+
RuntimeOptions
|
|
8
|
+
} from "./types/api";
|
|
9
|
+
import {
|
|
10
|
+
Warning,
|
|
11
|
+
WarningDefault,
|
|
12
|
+
WarningLocation,
|
|
13
|
+
WarningName,
|
|
14
|
+
WarningNameWithValue
|
|
15
|
+
} from "./types/warnings";
|
|
16
|
+
import { ASTDeps, Dependency } from "./types/astdeps";
|
|
17
|
+
|
|
18
|
+
declare const warnings: Record<WarningName, Pick<WarningDefault, "experimental" | "i18n" | "severity">>;
|
|
19
|
+
|
|
20
|
+
export {
|
|
21
|
+
warnings,
|
|
22
|
+
runASTAnalysis,
|
|
23
|
+
runASTAnalysisOnFile,
|
|
24
|
+
Report,
|
|
25
|
+
ReportOnFile,
|
|
26
|
+
RuntimeFileOptions,
|
|
27
|
+
RuntimeOptions,
|
|
28
|
+
ASTDeps,
|
|
29
|
+
Dependency,
|
|
30
|
+
Warning,
|
|
31
|
+
WarningDefault,
|
|
32
|
+
WarningLocation,
|
|
33
|
+
WarningName,
|
|
34
|
+
WarningNameWithValue
|
|
35
|
+
}
|
package/index.js
CHANGED
|
@@ -9,6 +9,7 @@ import isMinified from "is-minified-code";
|
|
|
9
9
|
|
|
10
10
|
// Import Internal Dependencies
|
|
11
11
|
import Analysis from "./src/Analysis.js";
|
|
12
|
+
import { warnings } from "./src/warnings.js";
|
|
12
13
|
|
|
13
14
|
export function runASTAnalysis(str, options = Object.create(null)) {
|
|
14
15
|
const { module = true, isMinified = false } = options;
|
|
@@ -83,59 +84,4 @@ export async function runASTAnalysisOnFile(pathToFile, options = {}) {
|
|
|
83
84
|
}
|
|
84
85
|
}
|
|
85
86
|
|
|
86
|
-
export
|
|
87
|
-
parsingError: {
|
|
88
|
-
code: "ast-error",
|
|
89
|
-
i18n: "sast_warnings.ast_error",
|
|
90
|
-
severity: "Information"
|
|
91
|
-
},
|
|
92
|
-
unsafeImport: {
|
|
93
|
-
code: "unsafe-import",
|
|
94
|
-
i18n: "sast_warnings.unsafe_import",
|
|
95
|
-
severity: "Warning"
|
|
96
|
-
},
|
|
97
|
-
unsafeRegex: {
|
|
98
|
-
code: "unsafe-regex",
|
|
99
|
-
i18n: "sast_warnings.unsafe_regex",
|
|
100
|
-
severity: "Warning"
|
|
101
|
-
},
|
|
102
|
-
unsafeStmt: {
|
|
103
|
-
code: "unsafe-stmt",
|
|
104
|
-
i18n: "sast_warnings.unsafe_stmt",
|
|
105
|
-
severity: "Warning"
|
|
106
|
-
},
|
|
107
|
-
unsafeAssign: {
|
|
108
|
-
code: "unsafe-assign",
|
|
109
|
-
i18n: "sast_warnings.unsafe_assign",
|
|
110
|
-
severity: "Warning"
|
|
111
|
-
},
|
|
112
|
-
encodedLiteral: {
|
|
113
|
-
code: "encoded-literal",
|
|
114
|
-
i18n: "sast_warnings.encoded_literal",
|
|
115
|
-
severity: "Information"
|
|
116
|
-
},
|
|
117
|
-
shortIdentifiers: {
|
|
118
|
-
code: "short-identifiers",
|
|
119
|
-
i18n: "sast_warnings.short_identifiers",
|
|
120
|
-
severity: "Warning"
|
|
121
|
-
},
|
|
122
|
-
suspiciousLiteral: {
|
|
123
|
-
code: "suspicious-literal",
|
|
124
|
-
i18n: "sast_warnings.suspicious_literal",
|
|
125
|
-
severity: "Warning"
|
|
126
|
-
},
|
|
127
|
-
obfuscatedCode: {
|
|
128
|
-
code: "obfuscated-code",
|
|
129
|
-
i18n: "sast_warnings.obfuscated_code",
|
|
130
|
-
severity: "Critical",
|
|
131
|
-
experimental: true
|
|
132
|
-
},
|
|
133
|
-
weakCrypto: {
|
|
134
|
-
code: "weak-crypto",
|
|
135
|
-
i18n: "sast_warnings.weak_crypto",
|
|
136
|
-
severity: "Information",
|
|
137
|
-
experimental: true
|
|
138
|
-
}
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
|
|
87
|
+
export { warnings };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nodesecure/js-x-ray",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.1.0",
|
|
4
4
|
"description": "JavaScript AST XRay analysis",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": "./index.js",
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
],
|
|
28
28
|
"files": [
|
|
29
29
|
"src",
|
|
30
|
+
"types",
|
|
30
31
|
"index.js",
|
|
31
32
|
"index.d.ts"
|
|
32
33
|
],
|
|
@@ -40,18 +41,18 @@
|
|
|
40
41
|
"@nodesecure/sec-literal": "^1.1.0",
|
|
41
42
|
"estree-walker": "^3.0.1",
|
|
42
43
|
"is-minified-code": "^2.0.0",
|
|
43
|
-
"meriyah": "^4.
|
|
44
|
+
"meriyah": "^4.3.0",
|
|
44
45
|
"safe-regex": "^2.1.1"
|
|
45
46
|
},
|
|
46
47
|
"devDependencies": {
|
|
47
|
-
"@nodesecure/eslint-config": "^1.
|
|
48
|
+
"@nodesecure/eslint-config": "^1.5.0",
|
|
48
49
|
"@slimio/is": "^1.5.1",
|
|
49
50
|
"@small-tech/esm-tape-runner": "^2.0.0",
|
|
50
51
|
"@small-tech/tap-monkey": "^1.4.0",
|
|
51
|
-
"@types/node": "^
|
|
52
|
+
"@types/node": "^18.7.13",
|
|
52
53
|
"cross-env": "^7.0.3",
|
|
53
|
-
"eslint": "^8.
|
|
54
|
+
"eslint": "^8.23.0",
|
|
54
55
|
"pkg-ok": "^3.0.0",
|
|
55
|
-
"tape": "^5.
|
|
56
|
+
"tape": "^5.6.0"
|
|
56
57
|
}
|
|
57
58
|
}
|
package/src/Analysis.js
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
import { Utils, Literal } from "@nodesecure/sec-literal";
|
|
3
3
|
|
|
4
4
|
// Import Internal Dependencies
|
|
5
|
-
import { rootLocation, toArrayLocation
|
|
6
|
-
import {
|
|
5
|
+
import { rootLocation, toArrayLocation } from "./utils.js";
|
|
6
|
+
import { generateWarning } from "./warnings.js";
|
|
7
|
+
import { processMainModuleRequire } from "./constants.js";
|
|
7
8
|
import ASTDeps from "./ASTDeps.js";
|
|
8
9
|
import { isObfuscatedCode, hasTrojanSource } from "./obfuscators/index.js";
|
|
9
10
|
import { runOnProbes } from "./probes/index.js";
|
|
@@ -15,19 +16,6 @@ const kDictionaryStrParts = [
|
|
|
15
16
|
"0123456789"
|
|
16
17
|
];
|
|
17
18
|
|
|
18
|
-
const kWarningsNameStr = Object.freeze({
|
|
19
|
-
[_warnings.parsingError]: "parsing-error",
|
|
20
|
-
[_warnings.unsafeImport]: "unsafe-import",
|
|
21
|
-
[_warnings.unsafeRegex]: "unsafe-regex",
|
|
22
|
-
[_warnings.unsafeStmt]: "unsafe-stmt",
|
|
23
|
-
[_warnings.unsafeAssign]: "unsafe-assign",
|
|
24
|
-
[_warnings.encodedLiteral]: "encoded-literal",
|
|
25
|
-
[_warnings.shortIdentifiers]: "short-identifiers",
|
|
26
|
-
[_warnings.suspiciousLiteral]: "suspicious-literal",
|
|
27
|
-
[_warnings.obfuscatedCode]: "obfuscated-code",
|
|
28
|
-
[_warnings.weakCrypto]: "weak-crypto"
|
|
29
|
-
});
|
|
30
|
-
|
|
31
19
|
export default class Analysis {
|
|
32
20
|
hasDictionaryString = false;
|
|
33
21
|
hasPrefixedIdentifiers = false;
|
|
@@ -56,23 +44,24 @@ export default class Analysis {
|
|
|
56
44
|
this.literalScores = [];
|
|
57
45
|
}
|
|
58
46
|
|
|
59
|
-
addWarning(
|
|
60
|
-
|
|
47
|
+
addWarning(name, value, location = rootLocation()) {
|
|
48
|
+
const isEncodedLiteral = name === "encoded-literal";
|
|
49
|
+
if (isEncodedLiteral && this.handledEncodedLiteralValues.has(value)) {
|
|
61
50
|
const index = this.handledEncodedLiteralValues.get(value);
|
|
62
51
|
this.warnings[index].location.push(toArrayLocation(location));
|
|
63
52
|
|
|
64
53
|
return;
|
|
65
54
|
}
|
|
66
|
-
|
|
67
|
-
this.warnings.push(generateWarning(
|
|
68
|
-
if (
|
|
55
|
+
|
|
56
|
+
this.warnings.push(generateWarning(name, { value, location }));
|
|
57
|
+
if (isEncodedLiteral) {
|
|
69
58
|
this.handledEncodedLiteralValues.set(value, this.warnings.length - 1);
|
|
70
59
|
}
|
|
71
60
|
}
|
|
72
61
|
|
|
73
62
|
analyzeSourceString(sourceString) {
|
|
74
63
|
if (hasTrojanSource(sourceString)) {
|
|
75
|
-
this.addWarning(
|
|
64
|
+
this.addWarning("obfuscated-code", "trojan-source");
|
|
76
65
|
}
|
|
77
66
|
}
|
|
78
67
|
|
|
@@ -107,7 +96,7 @@ export default class Analysis {
|
|
|
107
96
|
this.counter.encodedArrayValue++;
|
|
108
97
|
}
|
|
109
98
|
else {
|
|
110
|
-
this.addWarning(
|
|
99
|
+
this.addWarning("encoded-literal", node.value, node.loc);
|
|
111
100
|
}
|
|
112
101
|
}
|
|
113
102
|
}
|
|
@@ -116,7 +105,7 @@ export default class Analysis {
|
|
|
116
105
|
this.counter.identifiers = this.identifiersName.length;
|
|
117
106
|
const [isObfuscated, kind] = isObfuscatedCode(this);
|
|
118
107
|
if (isObfuscated) {
|
|
119
|
-
this.addWarning(
|
|
108
|
+
this.addWarning("obfuscated-code", kind || "unknown");
|
|
120
109
|
}
|
|
121
110
|
|
|
122
111
|
const identifiersLengthArr = this.identifiersName
|
|
@@ -124,10 +113,10 @@ export default class Analysis {
|
|
|
124
113
|
|
|
125
114
|
const [idsLengthAvg, stringScore] = [sum(identifiersLengthArr), sum(this.literalScores)];
|
|
126
115
|
if (!isMinified && identifiersLengthArr.length > 5 && idsLengthAvg <= 1.5) {
|
|
127
|
-
this.addWarning(
|
|
116
|
+
this.addWarning("short-identifiers", idsLengthAvg);
|
|
128
117
|
}
|
|
129
118
|
if (stringScore >= 3) {
|
|
130
|
-
this.addWarning(
|
|
119
|
+
this.addWarning("suspicious-literal", stringScore);
|
|
131
120
|
}
|
|
132
121
|
|
|
133
122
|
return { idsLengthAvg, stringScore, warnings: this.warnings };
|
|
@@ -149,5 +138,3 @@ export default class Analysis {
|
|
|
149
138
|
function sum(arr = []) {
|
|
150
139
|
return arr.length === 0 ? 0 : (arr.reduce((prev, curr) => prev + curr, 0) / arr.length);
|
|
151
140
|
}
|
|
152
|
-
|
|
153
|
-
Analysis.Warnings = _warnings;
|
package/src/constants.js
CHANGED
|
@@ -33,16 +33,3 @@ export const unsafeUnicodeControlCharacters = [
|
|
|
33
33
|
"\u200F",
|
|
34
34
|
"\u061C"
|
|
35
35
|
];
|
|
36
|
-
|
|
37
|
-
export const warnings = Object.freeze({
|
|
38
|
-
parsingError: Symbol("ParsingError"),
|
|
39
|
-
unsafeImport: Symbol("UnsafeImport"),
|
|
40
|
-
unsafeRegex: Symbol("UnsafeRegex"),
|
|
41
|
-
unsafeStmt: Symbol("UnsafeStmt"),
|
|
42
|
-
unsafeAssign: Symbol("UnsafeAssign"),
|
|
43
|
-
encodedLiteral: Symbol("EncodedLiteral"),
|
|
44
|
-
shortIdentifiers: Symbol("ShortIdentifiers"),
|
|
45
|
-
suspiciousLiteral: Symbol("SuspiciousLiteral"),
|
|
46
|
-
obfuscatedCode: Symbol("ObfuscatedCode"),
|
|
47
|
-
weakCrypto: Symbol("WeakCrypto")
|
|
48
|
-
});
|
package/src/probes/index.js
CHANGED
|
@@ -1,68 +1,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 isAssignmentExprOrMemberExpr from "./isAssignmentExprOrMemberExpr.js";
|
|
8
|
-
import isRequire from "./isRequire.js";
|
|
9
|
-
import isImportDeclaration from "./isImportDeclaration.js";
|
|
10
|
-
import isMemberExpression from "./isMemberExpression.js";
|
|
11
|
-
import isArrayExpression from "./isArrayExpression.js";
|
|
12
|
-
import isFunctionDeclaration from "./isFunctionDeclaration.js";
|
|
13
|
-
import isAssignmentExpression from "./isAssignmentExpression.js";
|
|
14
|
-
import isObjectExpression from "./isObjectExpression.js";
|
|
15
|
-
import isUnaryExpression from "./isUnaryExpression.js";
|
|
16
|
-
import isWeakCrypto from "./isWeakCrypto.js";
|
|
17
|
-
|
|
18
|
-
// CONSTANTS
|
|
19
|
-
const kListOfProbes = [
|
|
20
|
-
isUnsafeCallee,
|
|
21
|
-
isLiteral,
|
|
22
|
-
isLiteralRegex,
|
|
23
|
-
isRegexObject,
|
|
24
|
-
isVariableDeclaration,
|
|
25
|
-
isAssignmentExprOrMemberExpr,
|
|
26
|
-
isRequire,
|
|
27
|
-
isImportDeclaration,
|
|
28
|
-
isMemberExpression,
|
|
29
|
-
isAssignmentExpression,
|
|
30
|
-
isObjectExpression,
|
|
31
|
-
isArrayExpression,
|
|
32
|
-
isFunctionDeclaration,
|
|
33
|
-
isUnaryExpression,
|
|
34
|
-
isWeakCrypto
|
|
35
|
-
];
|
|
36
|
-
|
|
37
|
-
const kSymBreak = Symbol.for("breakWalk");
|
|
38
|
-
const kSymSkip = Symbol.for("skipWalk");
|
|
39
|
-
|
|
40
|
-
export function runOnProbes(node, analysis) {
|
|
41
|
-
const breakedGroups = new Set();
|
|
42
|
-
|
|
43
|
-
for (const probe of kListOfProbes) {
|
|
44
|
-
if (breakedGroups.has(probe.breakGroup)) {
|
|
45
|
-
continue;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const [isMatching, data = null] = probe.validateNode(node, analysis);
|
|
49
|
-
if (isMatching) {
|
|
50
|
-
const result = probe.main(node, { analysis, data });
|
|
51
|
-
|
|
52
|
-
if (result === kSymSkip) {
|
|
53
|
-
return "skip";
|
|
54
|
-
}
|
|
55
|
-
if (result === kSymBreak || probe.breakOnMatch) {
|
|
56
|
-
const breakGroup = probe.breakGroup || null;
|
|
57
|
-
if (breakGroup === null) {
|
|
58
|
-
break;
|
|
59
|
-
}
|
|
60
|
-
else {
|
|
61
|
-
breakedGroups.add(breakGroup);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return null;
|
|
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 isAssignmentExprOrMemberExpr from "./isAssignmentExprOrMemberExpr.js";
|
|
8
|
+
import isRequire from "./isRequire.js";
|
|
9
|
+
import isImportDeclaration from "./isImportDeclaration.js";
|
|
10
|
+
import isMemberExpression from "./isMemberExpression.js";
|
|
11
|
+
import isArrayExpression from "./isArrayExpression.js";
|
|
12
|
+
import isFunctionDeclaration from "./isFunctionDeclaration.js";
|
|
13
|
+
import isAssignmentExpression from "./isAssignmentExpression.js";
|
|
14
|
+
import isObjectExpression from "./isObjectExpression.js";
|
|
15
|
+
import isUnaryExpression from "./isUnaryExpression.js";
|
|
16
|
+
import isWeakCrypto from "./isWeakCrypto.js";
|
|
17
|
+
|
|
18
|
+
// CONSTANTS
|
|
19
|
+
const kListOfProbes = [
|
|
20
|
+
isUnsafeCallee,
|
|
21
|
+
isLiteral,
|
|
22
|
+
isLiteralRegex,
|
|
23
|
+
isRegexObject,
|
|
24
|
+
isVariableDeclaration,
|
|
25
|
+
isAssignmentExprOrMemberExpr,
|
|
26
|
+
isRequire,
|
|
27
|
+
isImportDeclaration,
|
|
28
|
+
isMemberExpression,
|
|
29
|
+
isAssignmentExpression,
|
|
30
|
+
isObjectExpression,
|
|
31
|
+
isArrayExpression,
|
|
32
|
+
isFunctionDeclaration,
|
|
33
|
+
isUnaryExpression,
|
|
34
|
+
isWeakCrypto
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
const kSymBreak = Symbol.for("breakWalk");
|
|
38
|
+
const kSymSkip = Symbol.for("skipWalk");
|
|
39
|
+
|
|
40
|
+
export function runOnProbes(node, analysis) {
|
|
41
|
+
const breakedGroups = new Set();
|
|
42
|
+
|
|
43
|
+
for (const probe of kListOfProbes) {
|
|
44
|
+
if (breakedGroups.has(probe.breakGroup)) {
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const [isMatching, data = null] = probe.validateNode(node, analysis);
|
|
49
|
+
if (isMatching) {
|
|
50
|
+
const result = probe.main(node, { analysis, data });
|
|
51
|
+
|
|
52
|
+
if (result === kSymSkip) {
|
|
53
|
+
return "skip";
|
|
54
|
+
}
|
|
55
|
+
if (result === kSymBreak || probe.breakOnMatch) {
|
|
56
|
+
const breakGroup = probe.breakGroup || null;
|
|
57
|
+
if (breakGroup === null) {
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
breakedGroups.add(breakGroup);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
// Require Internal Dependencies
|
|
2
|
-
import { warnings } from "../constants.js";
|
|
3
|
-
|
|
4
1
|
/**
|
|
5
2
|
* @description Search for ESM ImportDeclaration
|
|
6
3
|
* @see https://github.com/estree/estree/blob/master/es2015.md#importdeclaration
|
|
@@ -22,7 +19,7 @@ function main(node, options) {
|
|
|
22
19
|
// Searching for dangerous import "data:text/javascript;..." statement.
|
|
23
20
|
// see: https://2ality.com/2019/10/eval-via-import.html
|
|
24
21
|
if (node.source.value.startsWith("data:text/javascript")) {
|
|
25
|
-
analysis.addWarning(
|
|
22
|
+
analysis.addWarning("unsafe-import", node.source.value, node.loc);
|
|
26
23
|
}
|
|
27
24
|
analysis.dependencies.add(node.source.value, node.loc);
|
|
28
25
|
}
|