@nodesecure/scanner 5.2.1 → 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.
Files changed (90) hide show
  1. package/README.md +6 -116
  2. package/dist/class/logger.class.d.ts +27 -0
  3. package/dist/class/logger.class.d.ts.map +1 -0
  4. package/dist/class/logger.class.js +52 -0
  5. package/dist/class/logger.class.js.map +1 -0
  6. package/dist/comparePayloads.d.ts +66 -0
  7. package/dist/comparePayloads.d.ts.map +1 -0
  8. package/dist/comparePayloads.js +147 -0
  9. package/dist/comparePayloads.js.map +1 -0
  10. package/dist/depWalker.d.ts +10 -0
  11. package/dist/depWalker.d.ts.map +1 -0
  12. package/dist/depWalker.js +205 -0
  13. package/dist/depWalker.js.map +1 -0
  14. package/dist/i18n/english.d.ts +9 -0
  15. package/dist/i18n/english.d.ts.map +1 -0
  16. package/dist/i18n/english.js +6 -0
  17. package/dist/i18n/english.js.map +1 -0
  18. package/dist/i18n/french.d.ts +9 -0
  19. package/dist/i18n/french.d.ts.map +1 -0
  20. package/dist/i18n/french.js +6 -0
  21. package/dist/i18n/french.js.map +1 -0
  22. package/dist/index.d.ts +11 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +68 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/npmRegistry.d.ts +9 -0
  27. package/dist/npmRegistry.d.ts.map +1 -0
  28. package/dist/npmRegistry.js +125 -0
  29. package/dist/npmRegistry.js.map +1 -0
  30. package/dist/types.d.ts +216 -0
  31. package/dist/types.d.ts.map +1 -0
  32. package/dist/types.js +4 -0
  33. package/dist/types.js.map +1 -0
  34. package/dist/utils/addMissingVersionFlags.d.ts +3 -0
  35. package/dist/utils/addMissingVersionFlags.d.ts.map +1 -0
  36. package/dist/utils/addMissingVersionFlags.js +21 -0
  37. package/dist/utils/addMissingVersionFlags.js.map +1 -0
  38. package/dist/utils/dirname.d.ts +2 -0
  39. package/dist/utils/dirname.d.ts.map +1 -0
  40. package/dist/utils/dirname.js +8 -0
  41. package/dist/utils/dirname.js.map +1 -0
  42. package/dist/utils/getLinks.d.ts +7 -0
  43. package/dist/utils/getLinks.d.ts.map +1 -0
  44. package/dist/utils/getLinks.js +32 -0
  45. package/dist/utils/getLinks.js.map +1 -0
  46. package/dist/utils/index.d.ts +11 -0
  47. package/dist/utils/index.d.ts.map +1 -0
  48. package/dist/utils/index.js +9 -0
  49. package/dist/utils/index.js.map +1 -0
  50. package/dist/utils/urlToString.d.ts +2 -0
  51. package/dist/utils/urlToString.d.ts.map +1 -0
  52. package/dist/utils/urlToString.js +6 -0
  53. package/dist/utils/urlToString.js.map +1 -0
  54. package/dist/utils/warnings.d.ts +9 -0
  55. package/dist/utils/warnings.d.ts.map +1 -0
  56. package/dist/utils/warnings.js +49 -0
  57. package/dist/utils/warnings.js.map +1 -0
  58. package/package.json +23 -42
  59. package/LICENSE +0 -21
  60. package/i18n/english.js +0 -6
  61. package/i18n/french.js +0 -7
  62. package/index.d.ts +0 -14
  63. package/index.js +0 -74
  64. package/src/class/dependency.class.js +0 -113
  65. package/src/class/logger.class.js +0 -54
  66. package/src/constants.js +0 -13
  67. package/src/depWalker.js +0 -388
  68. package/src/manifest.js +0 -94
  69. package/src/npmRegistry.js +0 -136
  70. package/src/tarball.js +0 -210
  71. package/src/utils/addMissingVersionFlags.js +0 -24
  72. package/src/utils/analyzeDependencies.js +0 -71
  73. package/src/utils/booleanToFlags.js +0 -12
  74. package/src/utils/dirname.js +0 -9
  75. package/src/utils/filterDependencyKind.js +0 -44
  76. package/src/utils/getLinks.js +0 -36
  77. package/src/utils/getPackageName.js +0 -21
  78. package/src/utils/getTarballComposition.js +0 -38
  79. package/src/utils/index.js +0 -18
  80. package/src/utils/isGitDependency.js +0 -11
  81. package/src/utils/isSensitiveFile.js +0 -17
  82. package/src/utils/mergeDependencies.js +0 -30
  83. package/src/utils/parseManifestAuthor.js +0 -45
  84. package/src/utils/semver.js +0 -62
  85. package/src/utils/warnings.js +0 -44
  86. package/types/api.d.ts +0 -15
  87. package/types/logger.d.ts +0 -38
  88. package/types/scanner.d.ts +0 -244
  89. package/types/tarball.d.ts +0 -63
  90. package/types/walker.d.ts +0 -8
package/index.js DELETED
@@ -1,74 +0,0 @@
1
- // Import Node.js Dependencies
2
- import path from "path";
3
- import fs from "fs/promises";
4
- import timers from "timers/promises";
5
- import os from "os";
6
-
7
- // Import Third-party Dependencies
8
- import pacote from "pacote";
9
- import { getLocalRegistryURL } from "@nodesecure/npm-registry-sdk";
10
-
11
- // Import Internal Dependencies
12
- import { depWalker } from "./src/depWalker.js";
13
- import { NPM_TOKEN } from "./src/utils/index.js";
14
- import { ScannerLoggerEvents } from "./src/constants.js";
15
- import Logger from "./src/class/logger.class.js";
16
- import * as tarball from "./src/tarball.js";
17
-
18
- // CONSTANTS
19
- const kDefaultCwdOptions = { forceRootAnalysis: true, usePackageLock: true, includeDevDeps: false };
20
-
21
- export async function cwd(location = process.cwd(), options = {}, logger = new Logger()) {
22
- const registry = options.registry ? new URL(options.registry).toString() : getLocalRegistryURL();
23
-
24
- const finalizedOptions = Object.assign(
25
- { location },
26
- kDefaultCwdOptions,
27
- {
28
- ...options,
29
- registry
30
- }
31
- );
32
-
33
- logger.start(ScannerLoggerEvents.manifest.read);
34
- const packagePath = path.join(location, "package.json");
35
- const str = await fs.readFile(packagePath, "utf-8");
36
- logger.end(ScannerLoggerEvents.manifest.read);
37
-
38
- return depWalker(JSON.parse(str), finalizedOptions, logger);
39
- }
40
-
41
- export async function from(packageName, options = {}, logger = new Logger()) {
42
- const registry = options.registry ? new URL(options.registry).toString() : getLocalRegistryURL();
43
-
44
- logger.start(ScannerLoggerEvents.manifest.fetch);
45
- const manifest = await pacote.manifest(packageName, {
46
- ...NPM_TOKEN, registry, cache: `${os.homedir()}/.npm`
47
- });
48
- logger.end(ScannerLoggerEvents.manifest.fetch);
49
-
50
- return depWalker(manifest, Object.assign(options, { registry }), logger);
51
- }
52
-
53
- export async function verify(packageName = null) {
54
- if (typeof packageName === "undefined" || packageName === null) {
55
- return await tarball.scanPackage(process.cwd());
56
- }
57
-
58
- const tmpLocation = await fs.mkdtemp(path.join(os.tmpdir(), "/"));
59
- const dest = path.join(tmpLocation, packageName);
60
-
61
- try {
62
- await pacote.extract(packageName, dest, {
63
- ...NPM_TOKEN, registry: getLocalRegistryURL(), cache: `${os.homedir()}/.npm`
64
- });
65
-
66
- return await tarball.scanPackage(dest, packageName);
67
- }
68
- finally {
69
- await timers.setImmediate();
70
- await fs.rm(tmpLocation, { recursive: true, force: true });
71
- }
72
- }
73
-
74
- export { depWalker, tarball, Logger, ScannerLoggerEvents };
@@ -1,113 +0,0 @@
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
- this.existOnRemoteRegistry = true;
13
- this.alias = {};
14
-
15
- if (parent !== null) {
16
- parent.addChildren();
17
- }
18
- this.#parent = parent;
19
- }
20
-
21
- addChildren() {
22
- this.dependencyCount += 1;
23
- }
24
-
25
- get fullName() {
26
- return `${this.name} ${this.version}`;
27
- }
28
-
29
- get flags() {
30
- return [...this.#flags];
31
- }
32
-
33
- get parent() {
34
- return this.#parent === null ? {} : { [this.#parent.name]: this.#parent.version };
35
- }
36
-
37
- addFlag(flagName, predicate = true) {
38
- if (typeof flagName !== "string") {
39
- throw new TypeError("flagName argument must be typeof string");
40
- }
41
-
42
- if (predicate) {
43
- if (flagName === "hasDependencies" && this.#parent !== null) {
44
- this.#parent.addFlag("hasIndirectDependencies");
45
- }
46
-
47
- this.#flags.add(flagName);
48
- }
49
- }
50
-
51
- isGit(url) {
52
- this.#flags.add("isGit");
53
- if (typeof url === "string") {
54
- this.gitUrl = url;
55
- }
56
-
57
- return this;
58
- }
59
-
60
- exportAsPlainObject(customId) {
61
- if (this.warnings.length > 0) {
62
- this.addFlag("hasWarnings");
63
- }
64
-
65
- return {
66
- versions: {
67
- [this.version]: {
68
- id: typeof customId === "number" ? customId : Dependency.currentId++,
69
- usedBy: this.parent,
70
- isDevDependency: this.dev,
71
- existOnRemoteRegistry: this.existOnRemoteRegistry,
72
- flags: this.flags,
73
- description: "",
74
- size: 0,
75
- author: {},
76
- engines: {},
77
- repository: {},
78
- scripts: {},
79
- warnings: this.warnings,
80
- composition: {
81
- extensions: [],
82
- files: [],
83
- minified: [],
84
- unused: [],
85
- missing: [],
86
- alias: this.alias,
87
- required_files: [],
88
- required_nodejs: [],
89
- required_thirdparty: [],
90
- required_subpath: []
91
- },
92
- license: "unkown license",
93
- gitUrl: this.gitUrl
94
- }
95
- },
96
- vulnerabilities: [],
97
- metadata: {
98
- dependencyCount: this.dependencyCount,
99
- publishedCount: 0,
100
- lastUpdateAt: null,
101
- lastVersion: null,
102
- hasManyPublishers: false,
103
- hasReceivedUpdateInOneYear: true,
104
- homepage: null,
105
- author: {},
106
- publishers: [],
107
- maintainers: []
108
- }
109
- };
110
- }
111
- }
112
-
113
- Dependency.currentId = 1;
@@ -1,54 +0,0 @@
1
- // Import Node.js Dependencies
2
- import { EventEmitter } from "events";
3
- import { performance } from "perf_hooks";
4
-
5
- export default class Logger extends EventEmitter {
6
- constructor() {
7
- super();
8
-
9
- this.events = new Map();
10
- }
11
-
12
- start(eventName) {
13
- if (this.events.has(eventName)) {
14
- return this;
15
- }
16
-
17
- this.events.set(eventName, {
18
- startedAt: performance.now(),
19
- count: 0
20
- });
21
- this.emit("start", eventName);
22
-
23
- return this;
24
- }
25
-
26
- tick(eventName) {
27
- if (!this.events.has(eventName)) {
28
- return this;
29
- }
30
-
31
- this.events.get(eventName).count++;
32
- this.emit("tick", eventName);
33
-
34
- return this;
35
- }
36
-
37
- count(eventName) {
38
- return this.events.get(eventName)?.count ?? 0;
39
- }
40
-
41
- end(eventName) {
42
- if (!this.events.has(eventName)) {
43
- return this;
44
- }
45
-
46
- const data = this.events.get(eventName);
47
- this.emit("end", eventName, {
48
- ...data,
49
- executionTime: performance.now() - data.startedAt
50
- });
51
-
52
- return this;
53
- }
54
- }
package/src/constants.js DELETED
@@ -1,13 +0,0 @@
1
-
2
- export const ScannerLoggerEvents = {
3
- done: "depWalkerFinished",
4
- analysis: {
5
- tree: "walkTree",
6
- tarball: "tarball",
7
- registry: "registry"
8
- },
9
- manifest: {
10
- read: "readManifest",
11
- fetch: "fetchManifest"
12
- }
13
- };
package/src/depWalker.js DELETED
@@ -1,388 +0,0 @@
1
- // Import Node.js Dependencies
2
- import path from "path";
3
- import { readFileSync, promises as fs } from "fs";
4
- import timers from "timers/promises";
5
- import os from "os";
6
-
7
- // Import Third-party Dependencies
8
- import combineAsyncIterators from "combine-async-iterators";
9
- import * as iter from "itertools";
10
- import pacote from "pacote";
11
- import Arborist from "@npmcli/arborist";
12
- import Lock from "@slimio/lock";
13
- import * as vuln from "@nodesecure/vuln";
14
- import { ScannerLoggerEvents } from "./constants.js";
15
-
16
- // Import Internal Dependencies
17
- import {
18
- mergeDependencies, getCleanDependencyName, getDependenciesWarnings, addMissingVersionFlags, isGitDependency,
19
- NPM_TOKEN
20
- } from "./utils/index.js";
21
- import { scanDirOrArchive } from "./tarball.js";
22
- import { packageMetadata, manifestMetadata } from "./npmRegistry.js";
23
- import Dependency from "./class/dependency.class.js";
24
- import Logger from "./class/logger.class.js";
25
-
26
- const { version: packageVersion } = JSON.parse(
27
- readFileSync(
28
- new URL(path.join("..", "package.json"), import.meta.url)
29
- )
30
- );
31
-
32
- export async function* searchDeepDependencies(packageName, gitURL, options) {
33
- const { exclude, currDepth = 0, parent, maxDepth, registry } = options;
34
-
35
- const { name, version, deprecated, ...pkg } = await pacote.manifest(gitURL ?? packageName, {
36
- ...NPM_TOKEN,
37
- registry,
38
- cache: `${os.homedir()}/.npm`
39
- });
40
- const { dependencies, customResolvers, alias } = mergeDependencies(pkg);
41
-
42
- const current = new Dependency(name, version, parent);
43
- current.alias = Object.fromEntries(alias);
44
-
45
- if (gitURL !== null) {
46
- current.isGit(gitURL);
47
- try {
48
- await pacote.manifest(`${name}@${version}`, {
49
- ...NPM_TOKEN,
50
- registry,
51
- cache: `${os.homedir()}/.npm`
52
- });
53
- }
54
- catch {
55
- current.existOnRemoteRegistry = false;
56
- }
57
- }
58
- current.addFlag("isDeprecated", deprecated === true);
59
- current.addFlag("hasCustomResolver", customResolvers.size > 0);
60
- current.addFlag("hasDependencies", dependencies.size > 0);
61
-
62
- if (currDepth !== maxDepth) {
63
- const config = {
64
- exclude, currDepth: currDepth + 1, parent: current, maxDepth, registry
65
- };
66
-
67
- const gitDependencies = iter.filter(customResolvers.entries(), ([, valueStr]) => isGitDependency(valueStr));
68
- for (const [depName, valueStr] of gitDependencies) {
69
- yield* searchDeepDependencies(depName, valueStr, config);
70
- }
71
-
72
- const depsNames = await Promise.all(iter.map(dependencies.entries(), getCleanDependencyName));
73
- for (const [fullName, cleanName, isLatest] of depsNames) {
74
- if (!isLatest) {
75
- current.addFlag("hasOutdatedDependency");
76
- }
77
-
78
- if (exclude.has(cleanName)) {
79
- current.addChildren();
80
- exclude.get(cleanName).add(current.fullName);
81
- }
82
- else {
83
- exclude.set(cleanName, new Set([current.fullName]));
84
- yield* searchDeepDependencies(fullName, null, config);
85
- }
86
- }
87
- }
88
-
89
- yield current;
90
- }
91
-
92
- export async function* deepReadEdges(currentPackageName, options) {
93
- const { to, parent, exclude, fullLockMode, includeDevDeps, registry } = options;
94
- const { version, integrity = to.integrity } = to.package;
95
-
96
- const updatedVersion = version === "*" || typeof version === "undefined" ? "latest" : version;
97
- const current = new Dependency(currentPackageName, updatedVersion, parent);
98
- current.dev = to.dev;
99
-
100
- if (fullLockMode && !includeDevDeps) {
101
- const { deprecated, _integrity, ...pkg } = await pacote.manifest(`${currentPackageName}@${updatedVersion}`, {
102
- ...NPM_TOKEN,
103
- registry,
104
- cache: `${os.homedir()}/.npm`
105
- });
106
- const { customResolvers, alias } = mergeDependencies(pkg);
107
-
108
- current.alias = Object.fromEntries(alias);
109
- current.addFlag("hasValidIntegrity", _integrity === integrity);
110
- current.addFlag("isDeprecated");
111
- current.addFlag("hasCustomResolver", customResolvers.size > 0);
112
-
113
- if (isGitDependency(to.resolved)) {
114
- current.isGit(to.resolved);
115
- }
116
- }
117
- current.addFlag("hasDependencies", to.edgesOut.size > 0);
118
-
119
- for (const [packageName, { to: toNode }] of to.edgesOut) {
120
- if (toNode === null || (!includeDevDeps && toNode.dev)) {
121
- continue;
122
- }
123
- const cleanName = `${packageName}@${toNode.package.version}`;
124
-
125
- if (exclude.has(cleanName)) {
126
- current.addChildren();
127
- exclude.get(cleanName).add(current.fullName);
128
- }
129
- else {
130
- exclude.set(cleanName, new Set([current.fullName]));
131
- yield* deepReadEdges(packageName, { parent: current, to: toNode, exclude, registry });
132
- }
133
- }
134
- yield current;
135
- }
136
-
137
- export async function* getRootDependencies(manifest, options) {
138
- const {
139
- maxDepth = 4, exclude,
140
- usePackageLock, fullLockMode, includeDevDeps,
141
- location,
142
- registry
143
- } = options;
144
-
145
- const { dependencies, customResolvers, alias } = mergeDependencies(manifest, void 0);
146
- const parent = new Dependency(manifest.name, manifest.version);
147
- parent.alias = Object.fromEntries(alias);
148
-
149
- try {
150
- await pacote.manifest(`${manifest.name}@${manifest.version}`, {
151
- ...NPM_TOKEN,
152
- registry,
153
- cache: `${os.homedir()}/.npm`
154
- });
155
- }
156
- catch {
157
- parent.existOnRemoteRegistry = false;
158
- }
159
- parent.addFlag("hasCustomResolver", customResolvers.size > 0);
160
- parent.addFlag("hasDependencies", dependencies.size > 0);
161
-
162
- let iterators;
163
- if (usePackageLock) {
164
- const arb = new Arborist({
165
- ...NPM_TOKEN,
166
- path: location,
167
- registry
168
- });
169
- let tree;
170
- try {
171
- await fs.access(path.join(location, "node_modules"));
172
- tree = await arb.loadActual();
173
- }
174
- catch {
175
- tree = await arb.loadVirtual();
176
- }
177
-
178
- iterators = [
179
- ...iter
180
- .filter(tree.edgesOut.entries(), ([, { to }]) => to !== null && (includeDevDeps ? true : (!to.dev || to.isWorkspace)))
181
- .map(([packageName, { to }]) => [packageName, to.isWorkspace ? to.target : to])
182
- .map(([packageName, to]) => deepReadEdges(packageName, {
183
- to,
184
- parent,
185
- fullLockMode,
186
- includeDevDeps,
187
- exclude,
188
- registry
189
- }))
190
- ];
191
- }
192
- else {
193
- const configRef = { exclude, maxDepth, parent, registry };
194
- iterators = [
195
- ...iter.filter(customResolvers.entries(), ([, valueStr]) => isGitDependency(valueStr))
196
- .map(([depName, valueStr]) => searchDeepDependencies(depName, valueStr, configRef)),
197
- ...iter.map(dependencies.entries(), ([name, ver]) => searchDeepDependencies(`${name}@${ver}`, null, configRef))
198
- ];
199
- }
200
- for await (const dep of combineAsyncIterators({}, ...iterators)) {
201
- yield dep;
202
- }
203
-
204
- // Add root dependencies to the exclude Map (because the parent is not handled by searchDeepDependencies)
205
- // if we skip this the code will fail to re-link properly dependencies in the following steps
206
- const depsName = await Promise.all(iter.map(dependencies.entries(), getCleanDependencyName));
207
- for (const [, fullRange, isLatest] of depsName) {
208
- if (!isLatest) {
209
- parent.addFlag("hasOutdatedDependency");
210
- }
211
- if (exclude.has(fullRange)) {
212
- exclude.get(fullRange).add(parent.fullName);
213
- }
214
- }
215
-
216
- yield parent;
217
- }
218
-
219
- /**
220
- * @param {*} manifest
221
- * @param {*} options
222
- * @param {Logger} logger
223
- */
224
- export async function depWalker(manifest, options = {}, logger = new Logger()) {
225
- const {
226
- forceRootAnalysis = false,
227
- usePackageLock = false,
228
- includeDevDeps = false,
229
- fullLockMode = false,
230
- maxDepth,
231
- location,
232
- vulnerabilityStrategy = vuln.strategies.NONE,
233
- registry
234
- } = options;
235
-
236
- // Create TMP directory
237
- const tmpLocation = await fs.mkdtemp(path.join(os.tmpdir(), "/"));
238
-
239
- const payload = {
240
- id: tmpLocation.slice(-6),
241
- rootDependencyName: manifest.name,
242
- scannerVersion: packageVersion,
243
- vulnerabilityStrategy,
244
- warnings: []
245
- };
246
-
247
- // We are dealing with an exclude Map to avoid checking a package more than one time in searchDeepDependencies
248
- const exclude = new Map();
249
- const dependencies = new Map();
250
-
251
- {
252
- logger
253
- .start(ScannerLoggerEvents.analysis.tree)
254
- .start(ScannerLoggerEvents.analysis.tarball)
255
- .start(ScannerLoggerEvents.analysis.registry);
256
- const fetchedMetadataPackages = new Set();
257
- const promisesToWait = [];
258
-
259
- const tarballLocker = new Lock({ maxConcurrent: 5 });
260
- tarballLocker.on("freeOne", () => logger.tick(ScannerLoggerEvents.analysis.tarball));
261
-
262
- const rootDepsOptions = { maxDepth, exclude, usePackageLock, fullLockMode, includeDevDeps, location, registry };
263
- for await (const currentDep of getRootDependencies(manifest, rootDepsOptions)) {
264
- const { name, version, dev } = currentDep;
265
-
266
- const current = currentDep.exportAsPlainObject(name === manifest.name ? 0 : void 0);
267
- let proceedDependencyAnalysis = true;
268
-
269
- if (dependencies.has(name)) {
270
- const dep = dependencies.get(name);
271
- promisesToWait.push(manifestMetadata(name, version, dep));
272
-
273
- const currVersion = Object.keys(current.versions)[0];
274
- if (currVersion in dep.versions) {
275
- // The dependency has already entered the analysis
276
- // This happens if the package is used by multiple packages in the tree
277
- proceedDependencyAnalysis = false;
278
- }
279
- else {
280
- dep.versions[currVersion] = current.versions[currVersion];
281
- }
282
- }
283
- else {
284
- dependencies.set(name, current);
285
- }
286
-
287
- // If the dependency is a DevDependencies we ignore it.
288
- if (dev) {
289
- continue;
290
- }
291
-
292
- if (proceedDependencyAnalysis) {
293
- logger.tick(ScannerLoggerEvents.analysis.tree);
294
-
295
- // There is no need to fetch 'N' times the npm metadata for the same package.
296
- if (fetchedMetadataPackages.has(name) || !current.versions[version].existOnRemoteRegistry) {
297
- logger.tick(ScannerLoggerEvents.analysis.registry);
298
- }
299
- else {
300
- fetchedMetadataPackages.add(name);
301
- promisesToWait.push(packageMetadata(name, version, {
302
- ref: current,
303
- logger
304
- }));
305
- }
306
-
307
- promisesToWait.push(scanDirOrArchive(name, version, {
308
- ref: current.versions[version],
309
- location,
310
- tmpLocation: forceRootAnalysis && name === manifest.name ? null : tmpLocation,
311
- locker: tarballLocker,
312
- logger,
313
- registry
314
- }));
315
- }
316
- }
317
-
318
- logger.end(ScannerLoggerEvents.analysis.tree);
319
-
320
- // Wait for all extraction to be done!
321
- await Promise.allSettled(promisesToWait);
322
- await timers.setImmediate();
323
-
324
- logger.end(ScannerLoggerEvents.analysis.tarball).end(ScannerLoggerEvents.analysis.registry);
325
- }
326
-
327
- const { hydratePayloadDependencies, strategy } = await vuln.setStrategy(vulnerabilityStrategy);
328
- await hydratePayloadDependencies(dependencies, {
329
- useStandardFormat: true,
330
- path: location
331
- });
332
-
333
- payload.vulnerabilityStrategy = strategy;
334
-
335
- // We do this because it "seem" impossible to link all dependencies in the first walk.
336
- // Because we are dealing with package only one time it may happen sometimes.
337
- const globalWarnings = [];
338
- for (const [packageName, dependency] of dependencies) {
339
- const metadataIntegrities = dependency.metadata?.integrity ?? {};
340
-
341
- for (const [version, integrity] of Object.entries(metadataIntegrities)) {
342
- const dependencyVer = dependency.versions[version];
343
-
344
- const isEmptyPackage = dependencyVer.warnings
345
- .some((warning) => warning.kind === "empty-package");
346
- if (isEmptyPackage) {
347
- globalWarnings.push(`${packageName}@${version} only contain a package.json file!`);
348
- }
349
-
350
- if (!("integrity" in dependencyVer) || dependencyVer.flags.includes("isGit")) {
351
- continue;
352
- }
353
-
354
- if (dependencyVer.integrity !== integrity) {
355
- globalWarnings.push(`${packageName}@${version} manifest & tarball integrity doesn't match!`);
356
- }
357
- }
358
- for (const [verStr, verDescriptor] of Object.entries(dependency.versions)) {
359
- verDescriptor.flags.push(...addMissingVersionFlags(new Set(verDescriptor.flags), dependency));
360
-
361
- const usedDeps = exclude.get(`${packageName}@${verStr}`) || new Set();
362
- if (usedDeps.size === 0) {
363
- continue;
364
- }
365
-
366
- const usedBy = Object.create(null);
367
- for (const [name, version] of [...usedDeps].map((name) => name.split(" "))) {
368
- usedBy[name] = version;
369
- }
370
- Object.assign(verDescriptor.usedBy, usedBy);
371
- }
372
- }
373
-
374
- try {
375
- const { warnings, flaggedAuthors } = await getDependenciesWarnings(dependencies);
376
- payload.warnings = globalWarnings.concat(warnings);
377
- payload.flaggedAuthors = flaggedAuthors;
378
- payload.dependencies = Object.fromEntries(dependencies);
379
-
380
- return payload;
381
- }
382
- finally {
383
- await timers.setImmediate();
384
- await fs.rm(tmpLocation, { recursive: true, force: true });
385
-
386
- logger.emit(ScannerLoggerEvents.done);
387
- }
388
- }