@nodesecure/scanner 3.3.0 → 3.4.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.js +1 -1
- package/package.json +10 -10
- package/src/class/dependency.class.js +101 -99
- package/src/depWalker.js +21 -8
- package/src/utils/warnings.js +36 -36
- package/types/api.d.ts +1 -1
- package/types/scanner.d.ts +192 -185
package/README.md
CHANGED
|
@@ -50,7 +50,7 @@ See `types/api.d.ts` for a complete TypeScript definition.
|
|
|
50
50
|
|
|
51
51
|
```ts
|
|
52
52
|
function cwd(location: string, options?: Scanner.Options): Promise<Scanner.Payload>;
|
|
53
|
-
function from(packageName: string, options?: Scanner.Options): Promise<Scanner.Payload>;
|
|
53
|
+
function from(packageName: string, options?: Omit<Scanner.Options, "includeDevDeps">): Promise<Scanner.Payload>;
|
|
54
54
|
function verify(packageName?: string | null): Promise<Scanner.VerifyPayload>;
|
|
55
55
|
```
|
|
56
56
|
|
|
@@ -60,6 +60,7 @@ function verify(packageName?: string | null): Promise<Scanner.VerifyPayload>;
|
|
|
60
60
|
interface Options {
|
|
61
61
|
readonly maxDepth?: number;
|
|
62
62
|
readonly usePackageLock?: boolean;
|
|
63
|
+
readonly includeDevDeps?: boolean;
|
|
63
64
|
readonly vulnerabilityStrategy: Strategy.Kind;
|
|
64
65
|
readonly forceRootAnalysis?: boolean;
|
|
65
66
|
readonly fullLockMode?: boolean;
|
package/index.js
CHANGED
|
@@ -16,7 +16,7 @@ import Logger from "./src/class/logger.class.js";
|
|
|
16
16
|
import * as tarball from "./src/tarball.js";
|
|
17
17
|
|
|
18
18
|
// CONSTANTS
|
|
19
|
-
const kDefaultCwdOptions = { forceRootAnalysis: true, usePackageLock: true };
|
|
19
|
+
const kDefaultCwdOptions = { forceRootAnalysis: true, usePackageLock: true, includeDevDeps: false };
|
|
20
20
|
|
|
21
21
|
export async function cwd(location = process.cwd(), options = {}, logger = new Logger()) {
|
|
22
22
|
const finalizedOptions = Object.assign({ location }, kDefaultCwdOptions, options);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nodesecure/scanner",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.0",
|
|
4
4
|
"description": "A package API to run a static analysis of your module's dependencies.",
|
|
5
5
|
"exports": "./index.js",
|
|
6
6
|
"engines": {
|
|
@@ -52,34 +52,34 @@
|
|
|
52
52
|
"@slimio/is": "^1.5.1",
|
|
53
53
|
"@small-tech/esm-tape-runner": "^1.0.3",
|
|
54
54
|
"@small-tech/tap-monkey": "^1.3.0",
|
|
55
|
-
"@types/node": "^17.0.
|
|
55
|
+
"@types/node": "^17.0.21",
|
|
56
56
|
"c8": "^7.11.0",
|
|
57
57
|
"cross-env": "^7.0.3",
|
|
58
|
-
"dotenv": "^
|
|
59
|
-
"eslint": "^8.
|
|
58
|
+
"dotenv": "^16.0.0",
|
|
59
|
+
"eslint": "^8.11.0",
|
|
60
60
|
"get-folder-size": "^3.1.0",
|
|
61
61
|
"pkg-ok": "^2.3.1",
|
|
62
|
-
"sinon": "^
|
|
62
|
+
"sinon": "^13.0.1",
|
|
63
63
|
"snap-shot-core": "^10.2.4",
|
|
64
|
-
"tape": "^5.5.
|
|
64
|
+
"tape": "^5.5.2"
|
|
65
65
|
},
|
|
66
66
|
"dependencies": {
|
|
67
67
|
"@nodesecure/flags": "^2.2.0",
|
|
68
68
|
"@nodesecure/fs-walk": "^1.0.0",
|
|
69
69
|
"@nodesecure/i18n": "^1.2.1",
|
|
70
|
-
"@nodesecure/js-x-ray": "^4.2.
|
|
70
|
+
"@nodesecure/js-x-ray": "^4.2.1",
|
|
71
71
|
"@nodesecure/npm-registry-sdk": "^1.3.0",
|
|
72
72
|
"@nodesecure/ntlp": "^2.1.0",
|
|
73
73
|
"@nodesecure/utils": "^1.0.0",
|
|
74
|
-
"@nodesecure/vuln": "^1.
|
|
74
|
+
"@nodesecure/vuln": "^1.6.0",
|
|
75
75
|
"@npm/types": "^1.0.1",
|
|
76
|
-
"@npmcli/arborist": "^
|
|
76
|
+
"@npmcli/arborist": "^5.0.3",
|
|
77
77
|
"@slimio/lock": "^1.0.0",
|
|
78
78
|
"builtins": "^4.0.0",
|
|
79
79
|
"combine-async-iterators": "^2.0.1",
|
|
80
80
|
"itertools": "^1.7.1",
|
|
81
81
|
"lodash.difference": "^4.5.0",
|
|
82
|
-
"pacote": "^
|
|
82
|
+
"pacote": "^13.0.5",
|
|
83
83
|
"semver": "^7.3.4"
|
|
84
84
|
},
|
|
85
85
|
"type": "module"
|
|
@@ -1,99 +1,101 @@
|
|
|
1
|
-
export default class Dependency {
|
|
2
|
-
#flags = new Set();
|
|
3
|
-
#parent = null;
|
|
4
|
-
|
|
5
|
-
constructor(name, version, parent = null) {
|
|
6
|
-
this.gitUrl = null;
|
|
7
|
-
this.dependencyCount = 0;
|
|
8
|
-
this.warnings = [];
|
|
9
|
-
this.name = name;
|
|
10
|
-
this.version = version;
|
|
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
|
-
|
|
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
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
|
|
1
|
+
export default class Dependency {
|
|
2
|
+
#flags = new Set();
|
|
3
|
+
#parent = null;
|
|
4
|
+
|
|
5
|
+
constructor(name, version, parent = null) {
|
|
6
|
+
this.gitUrl = null;
|
|
7
|
+
this.dependencyCount = 0;
|
|
8
|
+
this.warnings = [];
|
|
9
|
+
this.name = name;
|
|
10
|
+
this.version = version;
|
|
11
|
+
this.dev = false;
|
|
12
|
+
|
|
13
|
+
if (parent !== null) {
|
|
14
|
+
parent.dependencyCount++;
|
|
15
|
+
}
|
|
16
|
+
this.#parent = parent;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
get fullName() {
|
|
20
|
+
return `${this.name} ${this.version}`;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
get flags() {
|
|
24
|
+
return [...this.#flags];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
get parent() {
|
|
28
|
+
return this.#parent === null ? {} : { [this.#parent.name]: this.#parent.version };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
addFlag(flagName, predicate = true) {
|
|
32
|
+
if (typeof flagName !== "string") {
|
|
33
|
+
throw new TypeError("flagName argument must be typeof string");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (predicate) {
|
|
37
|
+
if (flagName === "hasDependencies" && this.#parent !== null) {
|
|
38
|
+
this.#parent.addFlag("hasIndirectDependencies");
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
this.#flags.add(flagName);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
isGit(url) {
|
|
46
|
+
this.#flags.add("isGit");
|
|
47
|
+
if (typeof url === "string") {
|
|
48
|
+
this.gitUrl = url;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return this;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
exportAsPlainObject(customId) {
|
|
55
|
+
if (this.warnings.length > 0) {
|
|
56
|
+
this.addFlag("hasWarnings");
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
versions: {
|
|
61
|
+
[this.version]: {
|
|
62
|
+
id: typeof customId === "number" ? customId : Dependency.currentId++,
|
|
63
|
+
usedBy: this.parent,
|
|
64
|
+
isDevDependency: this.dev,
|
|
65
|
+
flags: this.flags,
|
|
66
|
+
description: "",
|
|
67
|
+
size: 0,
|
|
68
|
+
author: {},
|
|
69
|
+
warnings: this.warnings,
|
|
70
|
+
composition: {
|
|
71
|
+
extensions: [],
|
|
72
|
+
files: [],
|
|
73
|
+
minified: [],
|
|
74
|
+
unused: [],
|
|
75
|
+
missing: [],
|
|
76
|
+
required_files: [],
|
|
77
|
+
required_nodejs: [],
|
|
78
|
+
required_thirdparty: []
|
|
79
|
+
},
|
|
80
|
+
license: "unkown license",
|
|
81
|
+
gitUrl: this.gitUrl
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
vulnerabilities: [],
|
|
85
|
+
metadata: {
|
|
86
|
+
dependencyCount: this.dependencyCount,
|
|
87
|
+
publishedCount: 0,
|
|
88
|
+
lastUpdateAt: null,
|
|
89
|
+
lastVersion: null,
|
|
90
|
+
hasManyPublishers: false,
|
|
91
|
+
hasReceivedUpdateInOneYear: true,
|
|
92
|
+
homepage: null,
|
|
93
|
+
author: {},
|
|
94
|
+
publishers: [],
|
|
95
|
+
maintainers: []
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
Dependency.currentId = 1;
|
package/src/depWalker.js
CHANGED
|
@@ -75,13 +75,15 @@ export async function* searchDeepDependencies(packageName, gitURL, options) {
|
|
|
75
75
|
yield current;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
export async function* deepReadEdges(currentPackageName,
|
|
78
|
+
export async function* deepReadEdges(currentPackageName, options) {
|
|
79
|
+
const { to, parent, exclude, fullLockMode, includeDevDeps } = options;
|
|
79
80
|
const { version, integrity = to.integrity } = to.package;
|
|
80
81
|
|
|
81
82
|
const updatedVersion = version === "*" || typeof version === "undefined" ? "latest" : version;
|
|
82
83
|
const current = new Dependency(currentPackageName, updatedVersion, parent);
|
|
84
|
+
current.dev = to.dev;
|
|
83
85
|
|
|
84
|
-
if (fullLockMode) {
|
|
86
|
+
if (fullLockMode && !includeDevDeps) {
|
|
85
87
|
const { deprecated, _integrity, ...pkg } = await pacote.manifest(`${currentPackageName}@${updatedVersion}`, {
|
|
86
88
|
...NPM_TOKEN,
|
|
87
89
|
registry: getLocalRegistryURL(),
|
|
@@ -96,7 +98,7 @@ export async function* deepReadEdges(currentPackageName, { to, parent, exclude,
|
|
|
96
98
|
current.addFlag("hasDependencies", to.edgesOut.size > 0);
|
|
97
99
|
|
|
98
100
|
for (const [packageName, { to: toNode }] of to.edgesOut) {
|
|
99
|
-
if (toNode === null || toNode.dev) {
|
|
101
|
+
if (toNode === null || (!includeDevDeps && toNode.dev)) {
|
|
100
102
|
continue;
|
|
101
103
|
}
|
|
102
104
|
const cleanName = `${packageName}@${toNode.package.version}`;
|
|
@@ -113,7 +115,11 @@ export async function* deepReadEdges(currentPackageName, { to, parent, exclude,
|
|
|
113
115
|
}
|
|
114
116
|
|
|
115
117
|
export async function* getRootDependencies(manifest, options) {
|
|
116
|
-
const {
|
|
118
|
+
const {
|
|
119
|
+
maxDepth = 4, exclude,
|
|
120
|
+
usePackageLock, fullLockMode, includeDevDeps,
|
|
121
|
+
location
|
|
122
|
+
} = options;
|
|
117
123
|
|
|
118
124
|
const { dependencies, customResolvers } = mergeDependencies(manifest, void 0);
|
|
119
125
|
const parent = new Dependency(manifest.name, manifest.version);
|
|
@@ -137,9 +143,10 @@ export async function* getRootDependencies(manifest, options) {
|
|
|
137
143
|
}
|
|
138
144
|
|
|
139
145
|
iterators = [
|
|
140
|
-
...iter
|
|
146
|
+
...iter
|
|
147
|
+
.filter(tree.edgesOut.entries(), ([, { to }]) => to !== null && (includeDevDeps ? true : (!to.dev || to.isWorkspace)))
|
|
141
148
|
.map(([packageName, { to }]) => [packageName, to.isWorkspace ? to.target : to])
|
|
142
|
-
.map(([packageName, to]) => deepReadEdges(packageName, { to, parent, fullLockMode, exclude }))
|
|
149
|
+
.map(([packageName, to]) => deepReadEdges(packageName, { to, parent, fullLockMode, includeDevDeps, exclude }))
|
|
143
150
|
];
|
|
144
151
|
}
|
|
145
152
|
else {
|
|
@@ -178,6 +185,7 @@ export async function depWalker(manifest, options = {}, logger = new Logger()) {
|
|
|
178
185
|
const {
|
|
179
186
|
forceRootAnalysis = false,
|
|
180
187
|
usePackageLock = false,
|
|
188
|
+
includeDevDeps = false,
|
|
181
189
|
fullLockMode = false,
|
|
182
190
|
maxDepth,
|
|
183
191
|
location,
|
|
@@ -210,9 +218,9 @@ export async function depWalker(manifest, options = {}, logger = new Logger()) {
|
|
|
210
218
|
const tarballLocker = new Lock({ maxConcurrent: 5 });
|
|
211
219
|
tarballLocker.on("freeOne", () => logger.tick(ScannerLoggerEvents.analysis.tarball));
|
|
212
220
|
|
|
213
|
-
const rootDepsOptions = { maxDepth, exclude, usePackageLock, fullLockMode, location };
|
|
221
|
+
const rootDepsOptions = { maxDepth, exclude, usePackageLock, fullLockMode, includeDevDeps, location };
|
|
214
222
|
for await (const currentDep of getRootDependencies(manifest, rootDepsOptions)) {
|
|
215
|
-
const { name, version } = currentDep;
|
|
223
|
+
const { name, version, dev } = currentDep;
|
|
216
224
|
const current = currentDep.exportAsPlainObject(name === manifest.name ? 0 : void 0);
|
|
217
225
|
let proceedDependencyAnalysis = true;
|
|
218
226
|
|
|
@@ -234,6 +242,11 @@ export async function depWalker(manifest, options = {}, logger = new Logger()) {
|
|
|
234
242
|
dependencies.set(name, current);
|
|
235
243
|
}
|
|
236
244
|
|
|
245
|
+
// If the dependency is a DevDependencies we ignore it.
|
|
246
|
+
if (dev) {
|
|
247
|
+
continue;
|
|
248
|
+
}
|
|
249
|
+
|
|
237
250
|
if (proceedDependencyAnalysis) {
|
|
238
251
|
logger.tick(ScannerLoggerEvents.analysis.tree);
|
|
239
252
|
|
package/src/utils/warnings.js
CHANGED
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
// Import Third-party Dependencies
|
|
2
|
-
import { getToken, taggedString } from "@nodesecure/i18n";
|
|
3
|
-
|
|
4
|
-
// CONSTANTS
|
|
5
|
-
const kDetectedDep = taggedString`The dependency '${0}' has been detected in the dependency Tree.`;
|
|
6
|
-
const kWarningsMessages = Object.freeze({
|
|
7
|
-
"@scarf/scarf": getToken("warnings.disable_scarf"),
|
|
8
|
-
iohook: getToken("warnings.keylogging")
|
|
9
|
-
});
|
|
10
|
-
const kPackages = new Set(Object.keys(kWarningsMessages));
|
|
11
|
-
const kAuthors = new Set(["marak", "marak.squires@gmail.com"]);
|
|
12
|
-
|
|
13
|
-
function getWarning(depName) {
|
|
14
|
-
return `${kDetectedDep(depName)} ${kWarningsMessages[depName]}`;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export function getDependenciesWarnings(dependencies) {
|
|
18
|
-
const warnings = [];
|
|
19
|
-
for (const depName of kPackages) {
|
|
20
|
-
if (dependencies.has(depName)) {
|
|
21
|
-
warnings.push(getWarning(depName));
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// TODO: optimize with @nodesecure/author later
|
|
26
|
-
for (const [packageName, dependency] of dependencies) {
|
|
27
|
-
for (const { name, email } of dependency.metadata.maintainers) {
|
|
28
|
-
if (kAuthors.has(name) || kAuthors.has(email)) {
|
|
29
|
-
warnings.push(`'Marak Squires' package '${packageName}' has been detected in the dependency tree`);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
return warnings;
|
|
35
|
-
}
|
|
36
|
-
|
|
1
|
+
// Import Third-party Dependencies
|
|
2
|
+
import { getToken, taggedString } from "@nodesecure/i18n";
|
|
3
|
+
|
|
4
|
+
// CONSTANTS
|
|
5
|
+
const kDetectedDep = taggedString`The dependency '${0}' has been detected in the dependency Tree.`;
|
|
6
|
+
const kWarningsMessages = Object.freeze({
|
|
7
|
+
"@scarf/scarf": getToken("warnings.disable_scarf"),
|
|
8
|
+
iohook: getToken("warnings.keylogging")
|
|
9
|
+
});
|
|
10
|
+
const kPackages = new Set(Object.keys(kWarningsMessages));
|
|
11
|
+
const kAuthors = new Set(["marak", "marak.squires@gmail.com"]);
|
|
12
|
+
|
|
13
|
+
function getWarning(depName) {
|
|
14
|
+
return `${kDetectedDep(depName)} ${kWarningsMessages[depName]}`;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function getDependenciesWarnings(dependencies) {
|
|
18
|
+
const warnings = [];
|
|
19
|
+
for (const depName of kPackages) {
|
|
20
|
+
if (dependencies.has(depName)) {
|
|
21
|
+
warnings.push(getWarning(depName));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// TODO: optimize with @nodesecure/author later
|
|
26
|
+
for (const [packageName, dependency] of dependencies) {
|
|
27
|
+
for (const { name, email } of dependency.metadata.maintainers) {
|
|
28
|
+
if (kAuthors.has(name) || kAuthors.has(email)) {
|
|
29
|
+
warnings.push(`'Marak Squires' package '${packageName}' has been detected in the dependency tree`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return warnings;
|
|
35
|
+
}
|
|
36
|
+
|
package/types/api.d.ts
CHANGED
|
@@ -11,5 +11,5 @@ export {
|
|
|
11
11
|
declare const ScannerLoggerEvents: LoggerEvents;
|
|
12
12
|
|
|
13
13
|
declare function cwd(location: string, options?: Scanner.Options, logger?: Logger): Promise<Scanner.Payload>;
|
|
14
|
-
declare function from(packageName: string, options?: Scanner.Options, logger?: Logger): Promise<Scanner.Payload>;
|
|
14
|
+
declare function from(packageName: string, options?: Omit<Scanner.Options, "includeDevDeps">, logger?: Logger): Promise<Scanner.Payload>;
|
|
15
15
|
declare function verify(packageName?: string | null): Promise<Scanner.VerifyPayload>;
|
package/types/scanner.d.ts
CHANGED
|
@@ -1,185 +1,192 @@
|
|
|
1
|
-
// Import NodeSecure Dependencies
|
|
2
|
-
import * as JSXRay from "@nodesecure/js-x-ray";
|
|
3
|
-
import { license as License } from "@nodesecure/ntlp";
|
|
4
|
-
import * as Vuln from "@nodesecure/vuln";
|
|
5
|
-
import { Flags } from "@nodesecure/flags";
|
|
6
|
-
|
|
7
|
-
// Import Third-party Dependencies
|
|
8
|
-
import { Maintainer } from "@npm/types";
|
|
9
|
-
|
|
10
|
-
export = Scanner;
|
|
11
|
-
|
|
12
|
-
declare namespace Scanner {
|
|
13
|
-
export interface Publisher {
|
|
14
|
-
/**
|
|
15
|
-
* Publisher npm user name.
|
|
16
|
-
*/
|
|
17
|
-
name: string;
|
|
18
|
-
/**
|
|
19
|
-
* Publisher npm user email.
|
|
20
|
-
*/
|
|
21
|
-
email: string;
|
|
22
|
-
/**
|
|
23
|
-
* First version published.
|
|
24
|
-
*/
|
|
25
|
-
version: string;
|
|
26
|
-
/**
|
|
27
|
-
* Date of the first publication
|
|
28
|
-
* @example 2021-08-10T20:45:08.342Z
|
|
29
|
-
*/
|
|
30
|
-
at: string;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export interface DependencyVersion {
|
|
34
|
-
/** Id of the package (useful for usedBy relation) */
|
|
35
|
-
id: number;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
description
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
composition
|
|
52
|
-
|
|
53
|
-
extensions
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
* @see https://github.com/NodeSecure/
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
metadata
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
versions
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
export type
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
id
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
warnings
|
|
128
|
-
|
|
129
|
-
dependencies
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
*
|
|
155
|
-
*
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
* @default
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
* @default
|
|
176
|
-
*/
|
|
177
|
-
readonly
|
|
178
|
-
/**
|
|
179
|
-
*
|
|
180
|
-
*
|
|
181
|
-
* @default false
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
1
|
+
// Import NodeSecure Dependencies
|
|
2
|
+
import * as JSXRay from "@nodesecure/js-x-ray";
|
|
3
|
+
import { license as License } from "@nodesecure/ntlp";
|
|
4
|
+
import * as Vuln from "@nodesecure/vuln";
|
|
5
|
+
import { Flags } from "@nodesecure/flags";
|
|
6
|
+
|
|
7
|
+
// Import Third-party Dependencies
|
|
8
|
+
import { Maintainer } from "@npm/types";
|
|
9
|
+
|
|
10
|
+
export = Scanner;
|
|
11
|
+
|
|
12
|
+
declare namespace Scanner {
|
|
13
|
+
export interface Publisher {
|
|
14
|
+
/**
|
|
15
|
+
* Publisher npm user name.
|
|
16
|
+
*/
|
|
17
|
+
name: string;
|
|
18
|
+
/**
|
|
19
|
+
* Publisher npm user email.
|
|
20
|
+
*/
|
|
21
|
+
email: string;
|
|
22
|
+
/**
|
|
23
|
+
* First version published.
|
|
24
|
+
*/
|
|
25
|
+
version: string;
|
|
26
|
+
/**
|
|
27
|
+
* Date of the first publication
|
|
28
|
+
* @example 2021-08-10T20:45:08.342Z
|
|
29
|
+
*/
|
|
30
|
+
at: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface DependencyVersion {
|
|
34
|
+
/** Id of the package (useful for usedBy relation) */
|
|
35
|
+
id: number;
|
|
36
|
+
isDevDependency: boolean;
|
|
37
|
+
/** By whom (id) is used the package */
|
|
38
|
+
usedBy: Record<string, string>;
|
|
39
|
+
/** Size on disk of the extracted tarball (in bytes) */
|
|
40
|
+
size: number;
|
|
41
|
+
/** Package description */
|
|
42
|
+
description: string;
|
|
43
|
+
/** Author of the package. This information is not trustable and can be empty. */
|
|
44
|
+
author: Maintainer;
|
|
45
|
+
/**
|
|
46
|
+
* JS-X-Ray warnings
|
|
47
|
+
*
|
|
48
|
+
* @see https://github.com/NodeSecure/js-x-ray/blob/master/WARNINGS.md
|
|
49
|
+
*/
|
|
50
|
+
warnings: JSXRay.Warning<JSXRay.BaseWarning>[];
|
|
51
|
+
/** Tarball composition (files and dependencies) */
|
|
52
|
+
composition: {
|
|
53
|
+
/** Files extensions (.js, .md, .exe etc..) */
|
|
54
|
+
extensions: string[];
|
|
55
|
+
files: string[];
|
|
56
|
+
/** Minified files (foo.min.js etc..) */
|
|
57
|
+
minified: string[];
|
|
58
|
+
required_files: string[];
|
|
59
|
+
required_thirdparty: string[];
|
|
60
|
+
required_nodejs: string[];
|
|
61
|
+
unused: string[];
|
|
62
|
+
missing: string[];
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Package licenses with SPDX expression.
|
|
66
|
+
*
|
|
67
|
+
* @see https://github.com/NodeSecure/licenses-conformance
|
|
68
|
+
* @see https://github.com/NodeSecure/npm-tarball-license-parser
|
|
69
|
+
*/
|
|
70
|
+
license: License[];
|
|
71
|
+
/**
|
|
72
|
+
* Flags (Array of string)
|
|
73
|
+
*
|
|
74
|
+
* @see https://github.com/NodeSecure/flags/blob/main/FLAGS.md
|
|
75
|
+
*/
|
|
76
|
+
flags: Flags[];
|
|
77
|
+
/**
|
|
78
|
+
* If the dependency is a GIT repository
|
|
79
|
+
*/
|
|
80
|
+
gitUrl: null | string;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface Dependency {
|
|
84
|
+
/** NPM Registry metadata */
|
|
85
|
+
metadata: {
|
|
86
|
+
/** Count of dependencies */
|
|
87
|
+
dependencyCount: number;
|
|
88
|
+
/** Number of releases published on npm */
|
|
89
|
+
publishedCount: number;
|
|
90
|
+
lastUpdateAt: number;
|
|
91
|
+
/** Last version SemVer */
|
|
92
|
+
lastVersion: number;
|
|
93
|
+
hasChangedAuthor: boolean;
|
|
94
|
+
hasManyPublishers: boolean;
|
|
95
|
+
hasReceivedUpdateInOneYear: boolean;
|
|
96
|
+
/** Author of the package. This information is not trustable and can be empty. */
|
|
97
|
+
author: Maintainer;
|
|
98
|
+
/** Package home page */
|
|
99
|
+
homepage: string | null;
|
|
100
|
+
/**
|
|
101
|
+
* List of maintainers (list of people in the organization related to the package)
|
|
102
|
+
*/
|
|
103
|
+
maintainers: { name: string, email: string }[];
|
|
104
|
+
/**
|
|
105
|
+
* List of people who published this package
|
|
106
|
+
*/
|
|
107
|
+
publishers: Publisher[];
|
|
108
|
+
}
|
|
109
|
+
/** List of versions of this package available in the dependency tree (In the payload) */
|
|
110
|
+
versions: Record<string, DependencyVersion>;
|
|
111
|
+
/**
|
|
112
|
+
* Vulnerabilities fetched dependending on the selected vulnerabilityStrategy
|
|
113
|
+
*
|
|
114
|
+
* @see https://github.com/NodeSecure/vuln
|
|
115
|
+
*/
|
|
116
|
+
vulnerabilities: Vuln.Strategy.StandardVulnerability[];
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export type GlobalWarning = string[];
|
|
120
|
+
export type Dependencies = Record<string, Dependency>;
|
|
121
|
+
|
|
122
|
+
export interface Payload {
|
|
123
|
+
/** Payload unique id */
|
|
124
|
+
id: string;
|
|
125
|
+
/** Name of the analyzed package */
|
|
126
|
+
rootDependencyName: string;
|
|
127
|
+
/** Global warnings list */
|
|
128
|
+
warnings: GlobalWarning[];
|
|
129
|
+
/** All the dependencies of the package (flattened) */
|
|
130
|
+
dependencies: Dependencies;
|
|
131
|
+
/** Version of the scanner used to generate the result */
|
|
132
|
+
scannerVersion: string;
|
|
133
|
+
/** Vulnerability strategy name (npm, snyk, node) */
|
|
134
|
+
vulnerabilityStrategy: Vuln.Strategy.Kind;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export interface VerifyPayload {
|
|
138
|
+
files: {
|
|
139
|
+
list: string[];
|
|
140
|
+
extensions: string[];
|
|
141
|
+
minified: string[];
|
|
142
|
+
};
|
|
143
|
+
directorySize: number;
|
|
144
|
+
uniqueLicenseIds: string[];
|
|
145
|
+
licenses: License[];
|
|
146
|
+
ast: {
|
|
147
|
+
dependencies: Record<string, JSXRay.Dependency>;
|
|
148
|
+
warnings: JSXRay.Warning<JSXRay.BaseWarning>[];
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export interface Options {
|
|
153
|
+
/**
|
|
154
|
+
* Maximum tree depth
|
|
155
|
+
*
|
|
156
|
+
* @default 4
|
|
157
|
+
*/
|
|
158
|
+
readonly maxDepth?: number;
|
|
159
|
+
/**
|
|
160
|
+
* Use root package-lock.json. This will have the effect of triggering the Arborist package.
|
|
161
|
+
*
|
|
162
|
+
* @default false for from() API
|
|
163
|
+
* @default true for cwd() API
|
|
164
|
+
*/
|
|
165
|
+
readonly usePackageLock?: boolean;
|
|
166
|
+
/**
|
|
167
|
+
* Include project devDependencies (only available for cwd command)
|
|
168
|
+
*
|
|
169
|
+
* @default false
|
|
170
|
+
*/
|
|
171
|
+
readonly includeDevDeps?: boolean;
|
|
172
|
+
/**
|
|
173
|
+
* Vulnerability strategy name (npm, snyk, node)
|
|
174
|
+
*
|
|
175
|
+
* @default NONE
|
|
176
|
+
*/
|
|
177
|
+
readonly vulnerabilityStrategy: Vuln.Strategy.Kind;
|
|
178
|
+
/**
|
|
179
|
+
* Analyze root package.
|
|
180
|
+
*
|
|
181
|
+
* @default false for from() API
|
|
182
|
+
* @default true for cwd() API
|
|
183
|
+
*/
|
|
184
|
+
readonly forceRootAnalysis?: boolean;
|
|
185
|
+
/**
|
|
186
|
+
* Deeper dependencies analysis with cwd() API.
|
|
187
|
+
*
|
|
188
|
+
* @default false
|
|
189
|
+
*/
|
|
190
|
+
readonly fullLockMode?: boolean;
|
|
191
|
+
}
|
|
192
|
+
}
|