@nodesecure/js-x-ray 7.0.0 → 7.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 +2 -1
- package/index.d.ts +8 -0
- package/package.json +2 -2
- package/src/EntryFilesAnalyser.js +99 -0
- package/src/probes/isImportDeclaration.js +1 -1
- package/src/probes/isLiteral.js +7 -1
- package/types/api.d.ts +17 -0
package/README.md
CHANGED
|
@@ -290,7 +290,7 @@ $ yarn add @nodesecure/estree-ast-util
|
|
|
290
290
|
## Contributors ✨
|
|
291
291
|
|
|
292
292
|
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
|
293
|
-
[](#contributors-)
|
|
294
294
|
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
|
295
295
|
|
|
296
296
|
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
|
|
@@ -321,6 +321,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
|
|
321
321
|
<tr>
|
|
322
322
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/FredGuiou"><img src="https://avatars.githubusercontent.com/u/99122562?v=4?s=100" width="100px;" alt="FredGuiou"/><br /><sub><b>FredGuiou</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=FredGuiou" title="Documentation">📖</a> <a href="https://github.com/NodeSecure/js-x-ray/commits?author=FredGuiou" title="Code">💻</a></td>
|
|
323
323
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/madina0801"><img src="https://avatars.githubusercontent.com/u/101329759?v=4?s=100" width="100px;" alt="Madina"/><br /><sub><b>Madina</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=madina0801" title="Code">💻</a></td>
|
|
324
|
+
<td align="center" valign="top" width="14.28%"><a href="https://github.com/sairuss7"><img src="https://avatars.githubusercontent.com/u/87803528?v=4?s=100" width="100px;" alt="SairussDev"/><br /><sub><b>SairussDev</b></sub></a><br /><a href="https://github.com/NodeSecure/js-x-ray/commits?author=sairuss7" title="Code">💻</a></td>
|
|
324
325
|
</tr>
|
|
325
326
|
</tbody>
|
|
326
327
|
</table>
|
package/index.d.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AstAnalyser,
|
|
3
|
+
AstAnalyserOptions,
|
|
4
|
+
|
|
5
|
+
EntryFilesAnalyser,
|
|
6
|
+
EntryFilesAnalyserOptions,
|
|
7
|
+
|
|
3
8
|
SourceParser,
|
|
4
9
|
runASTAnalysis,
|
|
5
10
|
runASTAnalysisOnFile,
|
|
@@ -23,6 +28,9 @@ declare const warnings: Record<WarningName, Pick<WarningDefault, "experimental"
|
|
|
23
28
|
export {
|
|
24
29
|
warnings,
|
|
25
30
|
AstAnalyser,
|
|
31
|
+
AstAnalyserOptions,
|
|
32
|
+
EntryFilesAnalyser,
|
|
33
|
+
EntryFilesAnalyserOptions,
|
|
26
34
|
SourceParser,
|
|
27
35
|
runASTAnalysis,
|
|
28
36
|
runASTAnalysisOnFile,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nodesecure/js-x-ray",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.1.0",
|
|
4
4
|
"description": "JavaScript AST XRay analysis",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": "./index.js",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"@types/node": "^20.6.2",
|
|
59
59
|
"c8": "^9.0.0",
|
|
60
60
|
"cross-env": "^7.0.3",
|
|
61
|
-
"eslint": "^
|
|
61
|
+
"eslint": "^9.0.0",
|
|
62
62
|
"glob": "^10.3.4",
|
|
63
63
|
"iterator-matcher": "^2.1.0",
|
|
64
64
|
"pkg-ok": "^3.0.0"
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// Import Node.js Dependencies
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
|
|
5
|
+
// Import Internal Dependencies
|
|
6
|
+
import { AstAnalyser } from "./AstAnalyser.js";
|
|
7
|
+
|
|
8
|
+
const kDefaultExtensions = ["js", "cjs", "mjs", "node"];
|
|
9
|
+
|
|
10
|
+
export class EntryFilesAnalyser {
|
|
11
|
+
/**
|
|
12
|
+
* @constructor
|
|
13
|
+
* @param {object} [options={}]
|
|
14
|
+
* @param {AstAnalyser} [options.astAnalyzer=new AstAnalyser()]
|
|
15
|
+
* @param {function} [options.loadExtensions]
|
|
16
|
+
*/
|
|
17
|
+
constructor(options = {}) {
|
|
18
|
+
this.astAnalyzer = options.astAnalyzer ?? new AstAnalyser();
|
|
19
|
+
this.allowedExtensions = options.loadExtensions
|
|
20
|
+
? options.loadExtensions(kDefaultExtensions)
|
|
21
|
+
: kDefaultExtensions;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Asynchronously analyze a set of entry files yielding analysis reports.
|
|
26
|
+
*
|
|
27
|
+
* @param {(string | URL)[]} entryFiles
|
|
28
|
+
* @yields {Object} - Yields an object containing the analysis report for each file.
|
|
29
|
+
*/
|
|
30
|
+
async* analyse(entryFiles) {
|
|
31
|
+
this.analyzedDeps = new Set();
|
|
32
|
+
|
|
33
|
+
for (const file of entryFiles) {
|
|
34
|
+
yield* this.#analyzeFile(file);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async* #analyzeFile(file) {
|
|
39
|
+
const filePath = file instanceof URL ? file.pathname : file;
|
|
40
|
+
const report = await this.astAnalyzer.analyseFile(file);
|
|
41
|
+
|
|
42
|
+
yield { url: filePath, ...report };
|
|
43
|
+
|
|
44
|
+
if (!report.ok) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
yield* this.#analyzeDeps(report.dependencies, path.dirname(filePath));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async* #analyzeDeps(deps, basePath) {
|
|
52
|
+
for (const [name] of deps) {
|
|
53
|
+
const depPath = await this.#getInternalDepPath(name, basePath);
|
|
54
|
+
if (depPath && !this.analyzedDeps.has(depPath)) {
|
|
55
|
+
this.analyzedDeps.add(depPath);
|
|
56
|
+
|
|
57
|
+
yield* this.#analyzeFile(depPath);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async #getInternalDepPath(name, basePath) {
|
|
63
|
+
const depPath = path.join(basePath, name);
|
|
64
|
+
const existingExt = path.extname(name);
|
|
65
|
+
if (existingExt !== "") {
|
|
66
|
+
if (!this.allowedExtensions.includes(existingExt.slice(1))) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (await this.#fileExists(depPath)) {
|
|
71
|
+
return depPath;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
for (const ext of this.allowedExtensions) {
|
|
76
|
+
const depPathWithExt = `${depPath}.${ext}`;
|
|
77
|
+
if (await this.#fileExists(depPathWithExt)) {
|
|
78
|
+
return depPathWithExt;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async #fileExists(path) {
|
|
86
|
+
try {
|
|
87
|
+
await fs.access(path, fs.constants.F_OK);
|
|
88
|
+
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
if (error.code !== "ENOENT") {
|
|
93
|
+
throw error;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
function validateNode(node) {
|
|
10
10
|
return [
|
|
11
11
|
// Note: the source property is the right-side Literal part of the Import
|
|
12
|
-
node.type
|
|
12
|
+
["ImportDeclaration", "ImportExpression"].includes(node.type) && node.source.type === "Literal"
|
|
13
13
|
];
|
|
14
14
|
}
|
|
15
15
|
|
package/src/probes/isLiteral.js
CHANGED
|
@@ -4,13 +4,19 @@ import { builtinModules } from "repl";
|
|
|
4
4
|
// Import Third-party Dependencies
|
|
5
5
|
import { Hex } from "@nodesecure/sec-literal";
|
|
6
6
|
|
|
7
|
+
const kMapRegexIps = Object.freeze({
|
|
8
|
+
regexIPv4: /^(https?:\/\/)(?!127\.)(?!.*:(?:0{1,3}|25[6-9])\.)(?!.*:(?:25[6-9])\.(?:0{1,3}|25[6-9])\.)(?!.*:(?:25[6-9])\.(?:25[6-9])\.(?:0{1,3}|25[6-9])\.)(?!.*:(?:25[6-9])\.(?:25[6-9])\.(?:25[6-9])\.(?:0{1,3}|25[6-9]))((?:\d{1,2}|1\d{2}|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d{2}|2[0-4]\d|25[0-5])(?::\d{1,5})?(\/[^\s]*)?$/,
|
|
9
|
+
regexIPv6: /^(https?:\/\/)(\[[0-9A-Fa-f:]+\])(?::\d{1,5})?(\/[^\s]*)?$/
|
|
10
|
+
});
|
|
11
|
+
|
|
7
12
|
// CONSTANTS
|
|
8
13
|
const kNodeDeps = new Set(builtinModules);
|
|
9
14
|
const kShadyLinkRegExps = [
|
|
15
|
+
kMapRegexIps.regexIPv4,
|
|
16
|
+
kMapRegexIps.regexIPv6,
|
|
10
17
|
/(http[s]?:\/\/bit\.ly.*)$/,
|
|
11
18
|
/(http[s]?:\/\/.*\.(link|xyz|tk|ml|ga|cf|gq|pw|top|club|mw|bd|ke|am|sbs|date|quest|cd|bid|cd|ws|icu|cam|uno|email|stream))$/
|
|
12
19
|
];
|
|
13
|
-
|
|
14
20
|
/**
|
|
15
21
|
* @description Search for Literal AST Node
|
|
16
22
|
* @see https://github.com/estree/estree/blob/master/es5.md#literal
|
package/types/api.d.ts
CHANGED
|
@@ -3,6 +3,9 @@ import { Statement } from "meriyah/dist/src/estree.js";
|
|
|
3
3
|
|
|
4
4
|
export {
|
|
5
5
|
AstAnalyser,
|
|
6
|
+
AstAnalyserOptions,
|
|
7
|
+
EntryFilesAnalyser,
|
|
8
|
+
EntryFilesAnalyserOptions,
|
|
6
9
|
SourceParser,
|
|
7
10
|
runASTAnalysis,
|
|
8
11
|
runASTAnalysisOnFile,
|
|
@@ -101,5 +104,19 @@ declare class AstAnalyser {
|
|
|
101
104
|
analyzeFile(pathToFile: string, options?: RuntimeFileOptions): Promise<ReportOnFile>;
|
|
102
105
|
}
|
|
103
106
|
|
|
107
|
+
interface EntryFilesAnalyserOptions {
|
|
108
|
+
astAnalyzer?: AstAnalyser;
|
|
109
|
+
loadExtensions?: (defaults: string[]) => string[];
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
declare class EntryFilesAnalyser {
|
|
113
|
+
constructor(options?: EntryFilesAnalyserOptions);
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Asynchronously analyze a set of entry files yielding analysis reports.
|
|
117
|
+
*/
|
|
118
|
+
analyse(entryFiles: (string | URL)[]): AsyncGenerator<ReportOnFile & { url: string }>;
|
|
119
|
+
}
|
|
120
|
+
|
|
104
121
|
declare function runASTAnalysis(str: string, options?: RuntimeOptions & AstAnalyserOptions): Report;
|
|
105
122
|
declare function runASTAnalysisOnFile(pathToFile: string, options?: RuntimeFileOptions & AstAnalyserOptions): Promise<ReportOnFile>;
|