@socketsecurity/cli 0.14.42 → 0.14.44

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 (44) hide show
  1. package/README.md +16 -38
  2. package/bin/cli.js +17 -7
  3. package/bin/npm-cli.js +1 -1
  4. package/bin/npx-cli.js +1 -1
  5. package/dist/constants.d.ts +121 -11
  6. package/dist/constants.js +91 -10
  7. package/dist/constants.js.map +1 -0
  8. package/dist/init.gradle +250 -0
  9. package/dist/module-sync/cli.js +6115 -3836
  10. package/dist/module-sync/cli.js.map +1 -0
  11. package/dist/module-sync/edge.d.ts +66 -0
  12. package/dist/module-sync/errors.d.ts +6 -1
  13. package/dist/module-sync/index.d.ts +192 -0
  14. package/dist/module-sync/index.js +1879 -0
  15. package/dist/module-sync/index.js.map +1 -0
  16. package/dist/module-sync/logging.d.ts +3 -3
  17. package/dist/module-sync/node.d.ts +84 -0
  18. package/dist/module-sync/npm-injection.js +7 -1495
  19. package/dist/module-sync/npm-injection.js.map +1 -0
  20. package/dist/module-sync/npm-paths.d.ts +3 -2
  21. package/dist/module-sync/npm-paths.js +91 -42
  22. package/dist/module-sync/npm-paths.js.map +1 -0
  23. package/dist/module-sync/npm.d.ts +24 -0
  24. package/dist/module-sync/npm.js +99 -0
  25. package/dist/module-sync/npm.js.map +1 -0
  26. package/dist/module-sync/path-resolve.d.ts +1 -1
  27. package/dist/module-sync/proc-log.d.ts +3 -0
  28. package/dist/module-sync/reify.d.ts +1018 -0
  29. package/dist/module-sync/sdk.d.ts +5 -0
  30. package/dist/module-sync/settings.d.ts +5 -4
  31. package/dist/module-sync/shadow-bin.d.ts +1 -1
  32. package/dist/module-sync/shadow-bin.js +33 -12
  33. package/dist/module-sync/shadow-bin.js.map +1 -0
  34. package/dist/module-sync/types.d.ts +45 -0
  35. package/dist/require/cli.js +6114 -3836
  36. package/dist/require/constants.js +1 -1
  37. package/dist/require/index.js +3 -0
  38. package/dist/require/npm.js +3 -0
  39. package/dist/require/vendor.js +2336 -6
  40. package/package.json +69 -42
  41. package/dist/constants.d.ts.map +0 -1
  42. package/dist/module-sync/socket-url.d.ts +0 -40
  43. package/dist/module-sync/socket-url.js +0 -301
  44. package/dist/require/socket-url.js +0 -3
@@ -1,1514 +1,26 @@
1
1
  'use strict';
2
2
 
3
- function _socketInterop(e) {
4
- let c = 0
5
- for (const k in e ?? {}) {
6
- c = c === 0 && k === 'default' ? 1 : 0
7
- if (!c && k !== '__esModule') break
8
- }
9
- return c ? e.default : e
10
- }
11
-
12
- var path = require('node:path');
13
- var process = require('node:process');
14
- var semver = _socketInterop(require('semver'));
15
- var registry = require('@socketsecurity/registry');
16
- var arrays = require('@socketsecurity/registry/lib/arrays');
17
- var objects = require('@socketsecurity/registry/lib/objects');
18
- var packages = require('@socketsecurity/registry/lib/packages');
19
- var prompts = require('@socketsecurity/registry/lib/prompts');
20
- var spinner = require('@socketsecurity/registry/lib/spinner');
21
- var constants = require('./constants.js');
22
- var events = require('node:events');
23
- var https = require('node:https');
24
- var readline = require('node:readline');
25
- var socketUrl = require('./socket-url.js');
26
- var promises = require('node:timers/promises');
3
+ var index = require('./index.js');
27
4
  var npmPaths = require('./npm-paths.js');
28
- var npa = _socketInterop(require('npm-package-arg'));
29
-
30
- const {
31
- LOOP_SENTINEL: LOOP_SENTINEL$2,
32
- NPM_REGISTRY_URL: NPM_REGISTRY_URL$1
33
- } = constants;
34
- function getUrlOrigin(input) {
35
- try {
36
- return URL.parse(input)?.origin ?? '';
37
- } catch {}
38
- return '';
39
- }
40
- function getPackagesToQueryFromDiff(diff_, options) {
41
- const {
42
- includeUnchanged = false,
43
- includeUnknownOrigin = false
44
- } = {
45
- __proto__: null,
46
- ...options
47
- };
48
- const details = [];
49
- // `diff_` is `null` when `npm install --package-lock-only` is passed.
50
- if (!diff_) {
51
- return details;
52
- }
53
- const queue = [...diff_.children];
54
- let pos = 0;
55
- let {
56
- length: queueLength
57
- } = queue;
58
- while (pos < queueLength) {
59
- if (pos === LOOP_SENTINEL$2) {
60
- throw new Error('Detected infinite loop while walking Arborist diff');
61
- }
62
- const diff = queue[pos++];
63
- const {
64
- action
65
- } = diff;
66
- if (action) {
67
- // The `pkgNode`, i.e. the `ideal` node, will be `undefined` if the diff
68
- // action is 'REMOVE'
69
- // The `oldNode`, i.e. the `actual` node, will be `undefined` if the diff
70
- // action is 'ADD'.
71
- const {
72
- actual: oldNode,
73
- ideal: pkgNode
74
- } = diff;
75
- let existing;
76
- let keep = false;
77
- if (action === 'CHANGE') {
78
- if (pkgNode?.package.version !== oldNode?.package.version) {
79
- keep = true;
80
- if (oldNode?.package.name && oldNode.package.name === pkgNode?.package.name) {
81
- existing = oldNode;
82
- }
83
- }
84
- } else {
85
- keep = action !== 'REMOVE';
86
- }
87
- if (keep && pkgNode?.resolved && (!oldNode || oldNode.resolved)) {
88
- const origin = getUrlOrigin(pkgNode.resolved);
89
- if (includeUnknownOrigin || origin === NPM_REGISTRY_URL$1) {
90
- details.push({
91
- node: pkgNode,
92
- origin,
93
- existing
94
- });
95
- }
96
- }
97
- }
98
- for (const child of diff.children) {
99
- queue[queueLength++] = child;
100
- }
101
- }
102
- if (includeUnchanged) {
103
- const {
104
- unchanged
105
- } = diff_;
106
- for (let i = 0, {
107
- length
108
- } = unchanged; i < length; i += 1) {
109
- const pkgNode = unchanged[i];
110
- const origin = getUrlOrigin(pkgNode.resolved);
111
- if (includeUnknownOrigin || origin === NPM_REGISTRY_URL$1) {
112
- details.push({
113
- node: pkgNode,
114
- origin,
115
- existing: pkgNode
116
- });
117
- }
118
- }
119
- }
120
- return details;
121
- }
122
-
123
- const {
124
- API_V0_URL,
125
- abortSignal: abortSignal$2
126
- } = constants;
127
- async function* batchScan(pkgIds) {
128
- const req = https.request(`${API_V0_URL}/purl?alerts=true`, {
129
- method: 'POST',
130
- headers: {
131
- Authorization: `Basic ${Buffer.from(`${socketUrl.getPublicToken()}:`).toString('base64url')}`
132
- },
133
- signal: abortSignal$2
134
- }).end(JSON.stringify({
135
- components: pkgIds.map(id => ({
136
- purl: `pkg:npm/${id}`
137
- }))
138
- }));
139
- const {
140
- 0: res
141
- } = await events.once(req, 'response');
142
- const ok = res.statusCode >= 200 && res.statusCode <= 299;
143
- if (!ok) {
144
- throw new Error(`Socket API Error: ${res.statusCode}`);
145
- }
146
- const rli = readline.createInterface(res);
147
- for await (const line of rli) {
148
- yield JSON.parse(line);
149
- }
150
- }
151
- function isArtifactAlertCveFixable(alert) {
152
- const {
153
- type
154
- } = alert;
155
- return (type === 'cve' || type === 'mediumCVE' || type === 'mildCVE' || type === 'criticalCVE') && !!alert.props?.['firstPatchedVersionIdentifier'] && !!alert.props?.['vulnerableVersionRange'];
156
- }
157
- function isArtifactAlertFixable(alert) {
158
- return alert.type === 'socketUpgradeAvailable' || isArtifactAlertCveFixable(alert);
159
- }
160
-
161
- const {
162
- abortSignal: abortSignal$1
163
- } = constants;
164
- const ERROR_UX = {
165
- block: true,
166
- display: true
167
- };
168
- const IGNORE_UX = {
169
- block: false,
170
- display: false
171
- };
172
- const WARN_UX = {
173
- block: false,
174
- display: true
175
- };
176
-
177
- // Iterates over all entries with ordered issue rule for deferral. Iterates over
178
- // all issue rules and finds the first defined value that does not defer otherwise
179
- // uses the defaultValue. Takes the value and converts into a UX workflow.
180
- function resolveAlertRuleUX(orderedRulesCollection, defaultValue) {
181
- if (defaultValue === true || defaultValue === null || defaultValue === undefined) {
182
- defaultValue = {
183
- action: 'error'
184
- };
185
- } else if (defaultValue === false) {
186
- defaultValue = {
187
- action: 'ignore'
188
- };
189
- }
190
- let block = false;
191
- let display = false;
192
- let needDefault = true;
193
- iterate_entries: for (const rules of orderedRulesCollection) {
194
- for (const rule of rules) {
195
- if (ruleValueDoesNotDefer(rule)) {
196
- needDefault = false;
197
- const narrowingFilter = uxForDefinedNonDeferValue(rule);
198
- block = block || narrowingFilter.block;
199
- display = display || narrowingFilter.display;
200
- continue iterate_entries;
201
- }
202
- }
203
- const narrowingFilter = uxForDefinedNonDeferValue(defaultValue);
204
- block = block || narrowingFilter.block;
205
- display = display || narrowingFilter.display;
206
- }
207
- if (needDefault) {
208
- const narrowingFilter = uxForDefinedNonDeferValue(defaultValue);
209
- block = block || narrowingFilter.block;
210
- display = display || narrowingFilter.display;
211
- }
212
- return {
213
- block,
214
- display
215
- };
216
- }
217
-
218
- // Negative form because it is narrowing the type.
219
- function ruleValueDoesNotDefer(rule) {
220
- if (rule === undefined) {
221
- return false;
222
- }
223
- if (objects.isObject(rule)) {
224
- const {
225
- action
226
- } = rule;
227
- if (action === undefined || action === 'defer') {
228
- return false;
229
- }
230
- }
231
- return true;
232
- }
233
-
234
- // Handles booleans for backwards compatibility.
235
- function uxForDefinedNonDeferValue(ruleValue) {
236
- if (typeof ruleValue === 'boolean') {
237
- return ruleValue ? ERROR_UX : IGNORE_UX;
238
- }
239
- const {
240
- action
241
- } = ruleValue;
242
- if (action === 'warn') {
243
- return WARN_UX;
244
- } else if (action === 'ignore') {
245
- return IGNORE_UX;
246
- }
247
- return ERROR_UX;
248
- }
249
- function createAlertUXLookup(settings) {
250
- const cachedUX = new Map();
251
- return context => {
252
- const {
253
- type
254
- } = context.alert;
255
- let ux = cachedUX.get(type);
256
- if (ux) {
257
- return ux;
258
- }
259
- const orderedRulesCollection = [];
260
- for (const settingsEntry of settings.entries) {
261
- const orderedRules = [];
262
- let target = settingsEntry.start;
263
- while (target !== null) {
264
- const resolvedTarget = settingsEntry.settings[target];
265
- if (!resolvedTarget) {
266
- break;
267
- }
268
- const issueRuleValue = resolvedTarget.issueRules?.[type];
269
- if (typeof issueRuleValue !== 'undefined') {
270
- orderedRules.push(issueRuleValue);
271
- }
272
- target = resolvedTarget.deferTo ?? null;
273
- }
274
- orderedRulesCollection.push(orderedRules);
275
- }
276
- const defaultValue = settings.defaults.issueRules[type];
277
- let resolvedDefaultValue = {
278
- action: 'error'
279
- };
280
- if (defaultValue === false) {
281
- resolvedDefaultValue = {
282
- action: 'ignore'
283
- };
284
- } else if (defaultValue && defaultValue !== true) {
285
- resolvedDefaultValue = {
286
- action: defaultValue.action ?? 'error'
287
- };
288
- }
289
- ux = resolveAlertRuleUX(orderedRulesCollection, resolvedDefaultValue);
290
- cachedUX.set(type, ux);
291
- return ux;
292
- };
293
- }
294
- let _uxLookup;
295
- async function uxLookup(settings) {
296
- while (_uxLookup === undefined) {
297
- // eslint-disable-next-line no-await-in-loop
298
- await promises.setTimeout(1, {
299
- signal: abortSignal$1
300
- });
301
- }
302
- return _uxLookup(settings);
303
- }
304
-
305
- // Start initializing the AlertUxLookupResult immediately.
306
- void (async () => {
307
- const {
308
- orgs,
309
- settings
310
- } = await (async () => {
311
- try {
312
- const socketSdk = await socketUrl.setupSdk(socketUrl.getPublicToken());
313
- const orgResult = await socketSdk.getOrganizations();
314
- if (!orgResult.success) {
315
- throw new Error(`Failed to fetch Socket organization info: ${orgResult.error.message}`);
316
- }
317
- const orgs = [];
318
- for (const org of Object.values(orgResult.data.organizations)) {
319
- if (org) {
320
- orgs.push(org);
321
- }
322
- }
323
- const result = await socketSdk.postSettings(orgs.map(org => ({
324
- organization: org.id
325
- })));
326
- if (!result.success) {
327
- throw new Error(`Failed to fetch API key settings: ${result.error.message}`);
328
- }
329
- return {
330
- orgs,
331
- settings: result.data
332
- };
333
- } catch (e) {
334
- const cause = objects.isObject(e) && 'cause' in e ? e.cause : undefined;
335
- if (socketUrl.isErrnoException(cause) && (cause.code === 'ENOTFOUND' || cause.code === 'ECONNREFUSED')) {
336
- throw new Error('Unable to connect to socket.dev, ensure internet connectivity before retrying', {
337
- cause: e
338
- });
339
- }
340
- throw e;
341
- }
342
- })();
343
-
344
- // Remove any organizations not being enforced.
345
- const enforcedOrgs = socketUrl.getSetting('enforcedOrgs') ?? [];
346
- for (const {
347
- 0: i,
348
- 1: org
349
- } of orgs.entries()) {
350
- if (!enforcedOrgs.includes(org.id)) {
351
- settings.entries.splice(i, 1);
352
- }
353
- }
354
- const socketYml = socketUrl.findSocketYmlSync();
355
- if (socketYml) {
356
- settings.entries.push({
357
- start: socketYml.path,
358
- settings: {
359
- [socketYml.path]: {
360
- deferTo: null,
361
- // TODO: TypeScript complains about the type not matching. We should
362
- // figure out why are providing
363
- // issueRules: { [issueName: string]: boolean }
364
- // but expecting
365
- // issueRules: { [issueName: string]: { action: 'defer' | 'error' | 'ignore' | 'monitor' | 'warn' } }
366
- issueRules: socketYml.parsed.issueRules
367
- }
368
- }
369
- });
370
- }
371
- _uxLookup = createAlertUXLookup(settings);
372
- })();
373
-
374
- const depValid = require(npmPaths.getArboristDepValidPath());
375
-
376
- const {
377
- UNDEFINED_TOKEN
378
- } = constants;
379
- function tryRequire(...ids) {
380
- for (const data of ids) {
381
- let id;
382
- let transformer;
383
- if (Array.isArray(data)) {
384
- id = data[0];
385
- transformer = data[1];
386
- } else {
387
- id = data;
388
- transformer = mod => mod;
389
- }
390
- try {
391
- // Check that the transformed value isn't `undefined` because older
392
- // versions of packages like 'proc-log' may not export a `log` method.
393
- const exported = transformer(require(id));
394
- if (exported !== undefined) {
395
- return exported;
396
- }
397
- } catch {}
398
- }
399
- return undefined;
400
- }
401
- let _log = UNDEFINED_TOKEN;
402
- function getLogger() {
403
- if (_log === UNDEFINED_TOKEN) {
404
- const npmNmPath = npmPaths.getNpmNodeModulesPath();
405
- _log = tryRequire([path.join(npmNmPath, 'proc-log/lib/index.js'),
406
- // The proc-log DefinitelyTyped definition is incorrect. The type definition
407
- // is really that of its export log.
408
- mod => mod.log], path.join(npmNmPath, 'npmlog/lib/log.js'));
409
- }
410
- return _log;
411
- }
412
-
413
- const {
414
- LOOP_SENTINEL: LOOP_SENTINEL$1
415
- } = constants;
416
- const OverrideSet = require(npmPaths.getArboristOverrideSetClassPath());
417
-
418
- // Implementation code not related to patch https://github.com/npm/cli/pull/7025
419
- // is based on https://github.com/npm/cli/blob/v11.0.0/workspaces/arborist/lib/override-set.js:
420
- class SafeOverrideSet extends OverrideSet {
421
- // Patch adding doOverrideSetsConflict is based on
422
- // https://github.com/npm/cli/pull/7025.
423
- static doOverrideSetsConflict(first, second) {
424
- // If override sets contain one another then we can try to use the more specific
425
- // one. However, if neither one is more specific, then we consider them to be
426
- // in conflict.
427
- return this.findSpecificOverrideSet(first, second) === undefined;
428
- }
429
-
430
- // Patch adding findSpecificOverrideSet is based on
431
- // https://github.com/npm/cli/pull/7025.
432
- static findSpecificOverrideSet(first, second) {
433
- let overrideSet = second;
434
- while (overrideSet) {
435
- if (overrideSet.isEqual(first)) {
436
- return second;
437
- }
438
- overrideSet = overrideSet.parent;
439
- }
440
- overrideSet = first;
441
- while (overrideSet) {
442
- if (overrideSet.isEqual(second)) {
443
- return first;
444
- }
445
- overrideSet = overrideSet.parent;
446
- }
447
- // The override sets are incomparable. Neither one contains the other.
448
- const log = getLogger();
449
- log?.silly('Conflicting override sets', first, second);
450
- return undefined;
451
- }
452
-
453
- // Patch adding childrenAreEqual is based on
454
- // https://github.com/npm/cli/pull/7025.
455
- childrenAreEqual(otherOverrideSet) {
456
- const queue = [[this, otherOverrideSet]];
457
- let pos = 0;
458
- let {
459
- length: queueLength
460
- } = queue;
461
- while (pos < queueLength) {
462
- if (pos === LOOP_SENTINEL$1) {
463
- throw new Error('Detected infinite loop while comparing override sets');
464
- }
465
- const {
466
- 0: currSet,
467
- 1: currOtherSet
468
- } = queue[pos++];
469
- const {
470
- children
471
- } = currSet;
472
- const {
473
- children: otherChildren
474
- } = currOtherSet;
475
- if (children.size !== otherChildren.size) {
476
- return false;
477
- }
478
- for (const key of children.keys()) {
479
- if (!otherChildren.has(key)) {
480
- return false;
481
- }
482
- const child = children.get(key);
483
- const otherChild = otherChildren.get(key);
484
- if (child.value !== otherChild.value) {
485
- return false;
486
- }
487
- queue[queueLength++] = [child, otherChild];
488
- }
489
- }
490
- return true;
491
- }
492
- getEdgeRule(edge) {
493
- for (const rule of this.ruleset.values()) {
494
- if (rule.name !== edge.name) {
495
- continue;
496
- }
497
- // If keySpec is * we found our override.
498
- if (rule.keySpec === '*') {
499
- return rule;
500
- }
501
- // Patch replacing
502
- // let spec = npa(`${edge.name}@${edge.spec}`)
503
- // is based on https://github.com/npm/cli/pull/7025.
504
- //
505
- // We need to use the rawSpec here, because the spec has the overrides
506
- // applied to it already.
507
- let spec = npa(`${edge.name}@${edge.rawSpec}`);
508
- if (spec.type === 'alias') {
509
- spec = spec.subSpec;
510
- }
511
- if (spec.type === 'git') {
512
- if (spec.gitRange && rule.keySpec && semver.intersects(spec.gitRange, rule.keySpec)) {
513
- return rule;
514
- }
515
- continue;
516
- }
517
- if (spec.type === 'range' || spec.type === 'version') {
518
- if (rule.keySpec && semver.intersects(spec.fetchSpec, rule.keySpec)) {
519
- return rule;
520
- }
521
- continue;
522
- }
523
- // If we got this far, the spec type is one of tag, directory or file
524
- // which means we have no real way to make version comparisons, so we
525
- // just accept the override.
526
- return rule;
527
- }
528
- return this;
529
- }
530
-
531
- // Patch adding isEqual is based on
532
- // https://github.com/npm/cli/pull/7025.
533
- isEqual(otherOverrideSet) {
534
- if (this === otherOverrideSet) {
535
- return true;
536
- }
537
- if (!otherOverrideSet) {
538
- return false;
539
- }
540
- if (this.key !== otherOverrideSet.key || this.value !== otherOverrideSet.value) {
541
- return false;
542
- }
543
- if (!this.childrenAreEqual(otherOverrideSet)) {
544
- return false;
545
- }
546
- if (!this.parent) {
547
- return !otherOverrideSet.parent;
548
- }
549
- return this.parent.isEqual(otherOverrideSet.parent);
550
- }
551
- }
552
-
553
- const Node = require(npmPaths.getArboristNodeClassPath());
554
-
555
- // Implementation code not related to patch https://github.com/npm/cli/pull/7025
556
- // is based on https://github.com/npm/cli/blob/v11.0.0/workspaces/arborist/lib/node.js:
557
- class SafeNode extends Node {
558
- // Return true if it's safe to remove this node, because anything that is
559
- // depending on it would be fine with the thing that they would resolve to if
560
- // it was removed, or nothing is depending on it in the first place.
561
- canDedupe(preferDedupe = false) {
562
- // Not allowed to mess with shrinkwraps or bundles.
563
- if (this.inDepBundle || this.inShrinkwrap) {
564
- return false;
565
- }
566
- // It's a top level pkg, or a dep of one.
567
- if (!this.resolveParent?.resolveParent) {
568
- return false;
569
- }
570
- // No one wants it, remove it.
571
- if (this.edgesIn.size === 0) {
572
- return true;
573
- }
574
- const other = this.resolveParent.resolveParent.resolve(this.name);
575
- // Nothing else, need this one.
576
- if (!other) {
577
- return false;
578
- }
579
- // If it's the same thing, then always fine to remove.
580
- if (other.matches(this)) {
581
- return true;
582
- }
583
- // If the other thing can't replace this, then skip it.
584
- if (!other.canReplace(this)) {
585
- return false;
586
- }
587
- // Patch replacing
588
- // if (preferDedupe || semver.gte(other.version, this.version)) {
589
- // return true
590
- // }
591
- // is based on https://github.com/npm/cli/pull/7025.
592
- //
593
- // If we prefer dedupe, or if the version is equal, take the other.
594
- if (preferDedupe || semver.eq(other.version, this.version)) {
595
- return true;
596
- }
597
- // If our current version isn't the result of an override, then prefer to
598
- // take the greater version.
599
- if (!this.overridden && semver.gt(other.version, this.version)) {
600
- return true;
601
- }
602
- return false;
603
- }
604
-
605
- // Is it safe to replace one node with another? check the edges to
606
- // make sure no one will get upset. Note that the node might end up
607
- // having its own unmet dependencies, if the new node has new deps.
608
- // Note that there are cases where Arborist will opt to insert a node
609
- // into the tree even though this function returns false! This is
610
- // necessary when a root dependency is added or updated, or when a
611
- // root dependency brings peer deps along with it. In that case, we
612
- // will go ahead and create the invalid state, and then try to resolve
613
- // it with more tree construction, because it's a user request.
614
- canReplaceWith(node, ignorePeers) {
615
- if (this.name !== node.name || this.packageName !== node.packageName) {
616
- return false;
617
- }
618
- // Patch replacing
619
- // if (node.overrides !== this.overrides) {
620
- // return false
621
- // }
622
- // is based on https://github.com/npm/cli/pull/7025.
623
- //
624
- // If this node has no dependencies, then it's irrelevant to check the
625
- // override rules of the replacement node.
626
- if (this.edgesOut.size) {
627
- // XXX need to check for two root nodes?
628
- if (node.overrides) {
629
- if (!node.overrides.isEqual(this.overrides)) {
630
- return false;
631
- }
632
- } else {
633
- if (this.overrides) {
634
- return false;
635
- }
636
- }
637
- }
638
- // To satisfy the patch we ensure `node.overrides === this.overrides`
639
- // so that the condition we want to replace,
640
- // if (this.overrides !== node.overrides) {
641
- // , is not hit.`
642
- const oldOverrideSet = this.overrides;
643
- let result = true;
644
- if (oldOverrideSet !== node.overrides) {
645
- this.overrides = node.overrides;
646
- }
647
- try {
648
- result = super.canReplaceWith(node, ignorePeers);
649
- this.overrides = oldOverrideSet;
650
- } catch (e) {
651
- this.overrides = oldOverrideSet;
652
- throw e;
653
- }
654
- return result;
655
- }
656
-
657
- // Patch adding deleteEdgeIn is based on https://github.com/npm/cli/pull/7025.
658
- deleteEdgeIn(edge) {
659
- this.edgesIn.delete(edge);
660
- const {
661
- overrides
662
- } = edge;
663
- if (overrides) {
664
- this.updateOverridesEdgeInRemoved(overrides);
665
- }
666
- }
667
- addEdgeIn(edge) {
668
- // Patch replacing
669
- // if (edge.overrides) {
670
- // this.overrides = edge.overrides
671
- // }
672
- // is based on https://github.com/npm/cli/pull/7025.
673
- //
674
- // We need to handle the case where the new edge in has an overrides field
675
- // which is different from the current value.
676
- if (!this.overrides || !this.overrides.isEqual(edge.overrides)) {
677
- this.updateOverridesEdgeInAdded(edge.overrides);
678
- }
679
- this.edgesIn.add(edge);
680
- // Try to get metadata from the yarn.lock file.
681
- this.root.meta?.addEdge(edge);
682
- }
683
-
684
- // @ts-ignore: Incorrectly typed as a property instead of an accessor.
685
- get overridden() {
686
- // Patch replacing
687
- // return !!(this.overrides && this.overrides.value && this.overrides.name === this.name)
688
- // is based on https://github.com/npm/cli/pull/7025.
689
- if (!this.overrides || !this.overrides.value || this.overrides.name !== this.name) {
690
- return false;
691
- }
692
- // The overrides rule is for a package with this name, but some override rules
693
- // only apply to specific versions. To make sure this package was actually
694
- // overridden, we check whether any edge going in had the rule applied to it,
695
- // in which case its overrides set is different than its source node.
696
- for (const edge of this.edgesIn) {
697
- if (edge.overrides && edge.overrides.name === this.name && edge.overrides.value === this.version) {
698
- if (!edge.overrides?.isEqual(edge.from?.overrides)) {
699
- return true;
700
- }
701
- }
702
- }
703
- return false;
704
- }
705
-
706
- // Patch adding recalculateOutEdgesOverrides is based on
707
- // https://github.com/npm/cli/pull/7025.
708
- recalculateOutEdgesOverrides() {
709
- // For each edge out propagate the new overrides through.
710
- for (const edge of this.edgesOut.values()) {
711
- edge.reload(true);
712
- if (edge.to) {
713
- edge.to.updateOverridesEdgeInAdded(edge.overrides);
714
- }
715
- }
716
- }
717
-
718
- // @ts-ignore: Incorrectly typed to accept null.
719
- set root(newRoot) {
720
- // Patch removing
721
- // if (!this.overrides && this.parent && this.parent.overrides) {
722
- // this.overrides = this.parent.overrides.getNodeRule(this)
723
- // }
724
- // is based on https://github.com/npm/cli/pull/7025.
725
- //
726
- // The "root" setter is a really large and complex function. To satisfy the
727
- // patch we add a dummy value to `this.overrides` so that the condition we
728
- // want to remove,
729
- // if (!this.overrides && this.parent && this.parent.overrides) {
730
- // , is not hit.
731
- if (!this.overrides) {
732
- this.overrides = new SafeOverrideSet({
733
- overrides: ''
734
- });
735
- }
736
- try {
737
- super.root = newRoot;
738
- this.overrides = undefined;
739
- } catch (e) {
740
- this.overrides = undefined;
741
- throw e;
742
- }
743
- }
744
-
745
- // Patch adding updateOverridesEdgeInAdded is based on
746
- // https://github.com/npm/cli/pull/7025.
747
- //
748
- // This logic isn't perfect either. When we have two edges in that have
749
- // different override sets, then we have to decide which set is correct. This
750
- // function assumes the more specific override set is applicable, so if we have
751
- // dependencies A->B->C and A->C and an override set that specifies what happens
752
- // for C under A->B, this will work even if the new A->C edge comes along and
753
- // tries to change the override set. The strictly correct logic is not to allow
754
- // two edges with different overrides to point to the same node, because even
755
- // if this node can satisfy both, one of its dependencies might need to be
756
- // different depending on the edge leading to it. However, this might cause a
757
- // lot of duplication, because the conflict in the dependencies might never
758
- // actually happen.
759
- updateOverridesEdgeInAdded(otherOverrideSet) {
760
- if (!otherOverrideSet) {
761
- // Assuming there are any overrides at all, the overrides field is never
762
- // undefined for any node at the end state of the tree. So if the new edge's
763
- // overrides is undefined it will be updated later. So we can wait with
764
- // updating the node's overrides field.
765
- return false;
766
- }
767
- if (!this.overrides) {
768
- this.overrides = otherOverrideSet;
769
- this.recalculateOutEdgesOverrides();
770
- return true;
771
- }
772
- if (this.overrides.isEqual(otherOverrideSet)) {
773
- return false;
774
- }
775
- const newOverrideSet = SafeOverrideSet.findSpecificOverrideSet(this.overrides, otherOverrideSet);
776
- if (newOverrideSet) {
777
- if (this.overrides.isEqual(newOverrideSet)) {
778
- return false;
779
- }
780
- this.overrides = newOverrideSet;
781
- this.recalculateOutEdgesOverrides();
782
- return true;
783
- }
784
- // This is an error condition. We can only get here if the new override set
785
- // is in conflict with the existing.
786
- const log = getLogger();
787
- log?.silly('Conflicting override sets', this.name);
788
- return false;
789
- }
790
-
791
- // Patch adding updateOverridesEdgeInRemoved is based on
792
- // https://github.com/npm/cli/pull/7025.
793
- updateOverridesEdgeInRemoved(otherOverrideSet) {
794
- // If this edge's overrides isn't equal to this node's overrides,
795
- // then removing it won't change newOverrideSet later.
796
- if (!this.overrides || !this.overrides.isEqual(otherOverrideSet)) {
797
- return false;
798
- }
799
- let newOverrideSet;
800
- for (const edge of this.edgesIn) {
801
- const {
802
- overrides: edgeOverrides
803
- } = edge;
804
- if (newOverrideSet && edgeOverrides) {
805
- newOverrideSet = SafeOverrideSet.findSpecificOverrideSet(edgeOverrides, newOverrideSet);
806
- } else {
807
- newOverrideSet = edgeOverrides;
808
- }
809
- }
810
- if (this.overrides.isEqual(newOverrideSet)) {
811
- return false;
812
- }
813
- this.overrides = newOverrideSet;
814
- if (newOverrideSet) {
815
- // Optimization: If there's any override set at all, then no non-extraneous
816
- // node has an empty override set. So if we temporarily have no override set
817
- // (for example, we removed all the edges in), there's no use updating all
818
- // the edges out right now. Let's just wait until we have an actual override
819
- // set later.
820
- this.recalculateOutEdgesOverrides();
821
- }
822
- return true;
823
- }
824
- }
825
-
826
- const Edge = require(npmPaths.getArboristEdgeClassPath());
827
-
828
- // The Edge class makes heavy use of private properties which subclasses do NOT
829
- // have access to. So we have to recreate any functionality that relies on those
830
- // private properties and use our own "safe" prefixed non-conflicting private
831
- // properties. Implementation code not related to patch https://github.com/npm/cli/pull/7025
832
- // is based on https://github.com/npm/cli/blob/v11.0.0/workspaces/arborist/lib/edge.js.
833
- //
834
- // The npm application
835
- // Copyright (c) npm, Inc. and Contributors
836
- // Licensed on the terms of The Artistic License 2.0
837
- //
838
- // An edge in the dependency graph.
839
- // Represents a dependency relationship of some kind.
840
- const initializedSafeEdges = new WeakSet();
841
- class SafeEdge extends Edge {
842
- #safeAccept;
843
- #safeError;
844
- #safeExplanation;
845
- #safeFrom;
846
- #safeName;
847
- #safeTo;
848
- constructor(options) {
849
- const {
850
- accept,
851
- from,
852
- name
853
- } = options;
854
- // Defer to supper to validate options and assign non-private values.
855
- super(options);
856
- if (accept !== undefined) {
857
- this.#safeAccept = accept || '*';
858
- }
859
- if (from.constructor !== SafeNode) {
860
- Reflect.setPrototypeOf(from, SafeNode.prototype);
861
- }
862
- this.#safeError = null;
863
- this.#safeExplanation = null;
864
- this.#safeFrom = from;
865
- this.#safeName = name;
866
- this.#safeTo = null;
867
- initializedSafeEdges.add(this);
868
- this.reload(true);
869
- }
870
- get accept() {
871
- return this.#safeAccept;
872
- }
873
- get bundled() {
874
- return !!this.#safeFrom?.package?.bundleDependencies?.includes(this.name);
875
- }
876
- get error() {
877
- if (!this.#safeError) {
878
- if (!this.#safeTo) {
879
- if (this.optional) {
880
- this.#safeError = null;
881
- } else {
882
- this.#safeError = 'MISSING';
883
- }
884
- } else if (this.peer && this.#safeFrom === this.#safeTo.parent && !this.#safeFrom?.isTop) {
885
- this.#safeError = 'PEER LOCAL';
886
- } else if (!this.satisfiedBy(this.#safeTo)) {
887
- this.#safeError = 'INVALID';
888
- }
889
- // Patch adding "else if" condition is based on
890
- // https://github.com/npm/cli/pull/7025.
891
- else if (this.overrides && this.#safeTo.edgesOut.size && SafeOverrideSet.doOverrideSetsConflict(this.overrides, this.#safeTo.overrides)) {
892
- // Any inconsistency between the edge's override set and the target's
893
- // override set is potentially problematic. But we only say the edge is
894
- // in error if the override sets are plainly conflicting. Note that if
895
- // the target doesn't have any dependencies of their own, then this
896
- // inconsistency is irrelevant.
897
- this.#safeError = 'INVALID';
898
- } else {
899
- this.#safeError = 'OK';
900
- }
901
- }
902
- if (this.#safeError === 'OK') {
903
- return null;
904
- }
905
- return this.#safeError;
906
- }
907
-
908
- // @ts-ignore: Incorrectly typed as a property instead of an accessor.
909
- get from() {
910
- return this.#safeFrom;
911
- }
912
-
913
- // @ts-ignore: Incorrectly typed as a property instead of an accessor.
914
- get spec() {
915
- if (this.overrides?.value && this.overrides.value !== '*' && this.overrides.name === this.name) {
916
- // Patch adding "if" condition is based on
917
- // https://github.com/npm/cli/pull/7025.
918
- //
919
- // If this edge has the same overrides field as the source, then we're not
920
- // applying an override for this edge.
921
- if (this.overrides === this.#safeFrom?.overrides) {
922
- // The Edge rawSpec getter will retrieve the private Edge #spec property.
923
- return this.rawSpec;
924
- }
925
- if (this.overrides.value.startsWith('$')) {
926
- const ref = this.overrides.value.slice(1);
927
- // We may be a virtual root, if we are we want to resolve reference
928
- // overrides from the real root, not the virtual one.
929
- const pkg = this.#safeFrom?.sourceReference ? this.#safeFrom.sourceReference.root.package : this.#safeFrom?.root?.package;
930
- if (pkg?.devDependencies?.[ref]) {
931
- return pkg.devDependencies[ref];
932
- }
933
- if (pkg?.optionalDependencies?.[ref]) {
934
- return pkg.optionalDependencies[ref];
935
- }
936
- if (pkg?.dependencies?.[ref]) {
937
- return pkg.dependencies[ref];
938
- }
939
- if (pkg?.peerDependencies?.[ref]) {
940
- return pkg.peerDependencies[ref];
941
- }
942
- throw new Error(`Unable to resolve reference ${this.overrides.value}`);
943
- }
944
- return this.overrides.value;
945
- }
946
- return this.rawSpec;
947
- }
948
-
949
- // @ts-ignore: Incorrectly typed as a property instead of an accessor.
950
- get to() {
951
- return this.#safeTo;
952
- }
953
- detach() {
954
- this.#safeExplanation = null;
955
- // Patch replacing
956
- // if (this.#safeTo) {
957
- // this.#safeTo.edgesIn.delete(this)
958
- // }
959
- // is based on https://github.com/npm/cli/pull/7025.
960
- this.#safeTo?.deleteEdgeIn(this);
961
- this.#safeFrom?.edgesOut.delete(this.name);
962
- this.#safeTo = null;
963
- this.#safeError = 'DETACHED';
964
- this.#safeFrom = null;
965
- }
966
-
967
- // Return the edge data, and an explanation of how that edge came to be here.
968
- // @ts-ignore: Edge#explain is defined with an unused `seen = []` param.
969
- explain() {
970
- if (!this.#safeExplanation) {
971
- const explanation = {
972
- type: this.type,
973
- name: this.name,
974
- spec: this.spec,
975
- bundled: false,
976
- overridden: false,
977
- error: undefined,
978
- from: undefined,
979
- rawSpec: undefined
980
- };
981
- if (this.rawSpec !== this.spec) {
982
- explanation.rawSpec = this.rawSpec;
983
- explanation.overridden = true;
984
- }
985
- if (this.bundled) {
986
- explanation.bundled = this.bundled;
987
- }
988
- if (this.error) {
989
- explanation.error = this.error;
990
- }
991
- if (this.#safeFrom) {
992
- explanation.from = this.#safeFrom.explain();
993
- }
994
- this.#safeExplanation = explanation;
995
- }
996
- return this.#safeExplanation;
997
- }
998
- reload(hard = false) {
999
- if (!initializedSafeEdges.has(this)) {
1000
- // Skip if called during super constructor.
1001
- return;
1002
- }
1003
- this.#safeExplanation = null;
1004
- // Patch adding newOverrideSet and oldOverrideSet is based on
1005
- // https://github.com/npm/cli/pull/7025.
1006
- let newOverrideSet;
1007
- let oldOverrideSet;
1008
- if (this.#safeFrom?.overrides) {
1009
- // Patch replacing
1010
- // this.overrides = this.#safeFrom.overrides.getEdgeRule(this)
1011
- // is based on https://github.com/npm/cli/pull/7025.
1012
- const newOverrideSet = this.#safeFrom.overrides.getEdgeRule(this);
1013
- if (newOverrideSet && !newOverrideSet.isEqual(this.overrides)) {
1014
- // If there's a new different override set we need to propagate it to
1015
- // the nodes. If we're deleting the override set then there's no point
1016
- // propagating it right now since it will be filled with another value
1017
- // later.
1018
- oldOverrideSet = this.overrides;
1019
- this.overrides = newOverrideSet;
1020
- }
1021
- } else {
1022
- this.overrides = undefined;
1023
- }
1024
- const newTo = this.#safeFrom?.resolve(this.name);
1025
- if (newTo !== this.#safeTo) {
1026
- // Patch replacing
1027
- // if (this.#safeTo) {
1028
- // this.#safeTo.edgesIn.delete(this)
1029
- // }
1030
- // is based on https://github.com/npm/cli/pull/7025.
1031
- this.#safeTo?.deleteEdgeIn(this);
1032
- this.#safeTo = newTo ?? null;
1033
- this.#safeError = null;
1034
- this.#safeTo?.addEdgeIn(this);
1035
- } else if (hard) {
1036
- this.#safeError = null;
1037
- }
1038
- // Patch adding "else if" condition based on
1039
- // https://github.com/npm/cli/pull/7025.
1040
- else if (oldOverrideSet) {
1041
- // Propagate the new override set to the target node.
1042
- this.#safeTo.updateOverridesEdgeInRemoved(oldOverrideSet);
1043
- this.#safeTo.updateOverridesEdgeInAdded(newOverrideSet);
1044
- }
1045
- }
1046
- satisfiedBy(node) {
1047
- // Patch replacing
1048
- // if (node.name !== this.#name) {
1049
- // return false
1050
- // }
1051
- // is based on https://github.com/npm/cli/pull/7025.
1052
- if (node.name !== this.#safeName || !this.#safeFrom) {
1053
- return false;
1054
- }
1055
- // NOTE: this condition means we explicitly do not support overriding
1056
- // bundled or shrinkwrapped dependencies
1057
- if (node.hasShrinkwrap || node.inShrinkwrap || node.inBundle) {
1058
- return depValid(node, this.rawSpec, this.#safeAccept, this.#safeFrom);
1059
- }
1060
- // Patch replacing
1061
- // return depValid(node, this.spec, this.#accept, this.#from)
1062
- // is based on https://github.com/npm/cli/pull/7025.
1063
- //
1064
- // If there's no override we just use the spec.
1065
- if (!this.overrides?.keySpec) {
1066
- return depValid(node, this.spec, this.#safeAccept, this.#safeFrom);
1067
- }
1068
- // There's some override. If the target node satisfies the overriding spec
1069
- // then it's okay.
1070
- if (depValid(node, this.spec, this.#safeAccept, this.#safeFrom)) {
1071
- return true;
1072
- }
1073
- // If it doesn't, then it should at least satisfy the original spec.
1074
- if (!depValid(node, this.rawSpec, this.#safeAccept, this.#safeFrom)) {
1075
- return false;
1076
- }
1077
- // It satisfies the original spec, not the overriding spec. We need to make
1078
- // sure it doesn't use the overridden spec.
1079
- // For example, we might have an ^8.0.0 rawSpec, and an override that makes
1080
- // keySpec=8.23.0 and the override value spec=9.0.0.
1081
- // If the node is 9.0.0, then it's okay because it's consistent with spec.
1082
- // If the node is 8.24.0, then it's okay because it's consistent with the rawSpec.
1083
- // If the node is 8.23.0, then it's not okay because even though it's consistent
1084
- // with the rawSpec, it's also consistent with the keySpec.
1085
- // So we're looking for ^8.0.0 or 9.0.0 and not 8.23.0.
1086
- return !depValid(node, this.overrides.keySpec, this.#safeAccept, this.#safeFrom);
1087
- }
1088
- }
1089
-
1090
- const {
1091
- LOOP_SENTINEL,
1092
- NPM,
1093
- NPM_REGISTRY_URL,
1094
- SOCKET_CLI_FIX_PACKAGE_LOCK_FILE,
1095
- SOCKET_CLI_UPDATE_OVERRIDES_IN_PACKAGE_LOCK_FILE,
1096
- abortSignal,
1097
- kInternalsSymbol,
1098
- [kInternalsSymbol]: {
1099
- getIPC
1100
- }
1101
- } = constants;
1102
- const formatter = new socketUrl.ColorOrMarkdown(false);
1103
- function findBestPatchVersion(name, availableVersions, currentMajorVersion, vulnerableVersionRange, _firstPatchedVersionIdentifier) {
1104
- const manifestVersion = registry.getManifestData(NPM, name)?.version;
1105
- // Filter versions that are within the current major version and are not in the vulnerable range
1106
- const eligibleVersions = availableVersions.filter(version => {
1107
- const isSameMajor = semver.major(version) === currentMajorVersion;
1108
- const isNotVulnerable = !semver.satisfies(version, vulnerableVersionRange);
1109
- if (isSameMajor && isNotVulnerable) {
1110
- return true;
1111
- }
1112
- return !!manifestVersion;
1113
- });
1114
- if (eligibleVersions.length === 0) {
1115
- return null;
1116
- }
1117
- // Use semver to find the max satisfying version.
1118
- return semver.maxSatisfying(eligibleVersions, '*');
1119
- }
1120
- function findPackageNodes(tree, packageName) {
1121
- const queue = [{
1122
- node: tree
1123
- }];
1124
- const matches = [];
1125
- let sentinel = 0;
1126
- while (queue.length) {
1127
- if (sentinel++ === LOOP_SENTINEL) {
1128
- throw new Error('Detected infinite loop in findPackageNodes');
1129
- }
1130
- const {
1131
- node: currentNode
1132
- } = queue.pop();
1133
- const node = currentNode.children.get(packageName);
1134
- if (node) {
1135
- matches.push(node);
1136
- }
1137
- const children = [...currentNode.children.values()];
1138
- for (let i = children.length - 1; i >= 0; i -= 1) {
1139
- queue.push({
1140
- node: children[i]
1141
- });
1142
- }
1143
- }
1144
- return matches;
1145
- }
1146
- async function getPackagesAlerts(details, options) {
1147
- let {
1148
- length: remaining
1149
- } = details;
1150
- const packageAlerts = [];
1151
- if (!remaining) {
1152
- return packageAlerts;
1153
- }
1154
- const {
1155
- includeExisting = false,
1156
- includeUnfixable = true,
1157
- output
1158
- } = {
1159
- __proto__: null,
1160
- ...options
1161
- };
1162
- const spinner$1 = output ? new spinner.Spinner({
1163
- stream: output
1164
- }) : undefined;
1165
- const getText = spinner$1 ? () => `Looking up data for ${remaining} packages` : () => '';
1166
- spinner$1?.start(getText());
1167
- try {
1168
- for await (const artifact of batchScan(arrays.arrayUnique(details.map(d => d.node.pkgid)))) {
1169
- if (!artifact.name || !artifact.version || !artifact.alerts?.length) {
1170
- continue;
1171
- }
1172
- const {
1173
- version
1174
- } = artifact;
1175
- const name = packages.resolvePackageName(artifact);
1176
- const id = `${name}@${artifact.version}`;
1177
- let displayWarning = false;
1178
- let alerts = [];
1179
- for (const alert of artifact.alerts) {
1180
- // eslint-disable-next-line no-await-in-loop
1181
- const ux = await uxLookup({
1182
- package: {
1183
- name,
1184
- version
1185
- },
1186
- alert: {
1187
- type: alert.type
1188
- }
1189
- });
1190
- if (ux.display && output) {
1191
- displayWarning = true;
1192
- }
1193
- if (ux.block || ux.display) {
1194
- const fixable = isArtifactAlertFixable(alert);
1195
- if (includeUnfixable || fixable) {
1196
- alerts.push({
1197
- name,
1198
- version,
1199
- key: alert.key,
1200
- type: alert.type,
1201
- block: ux.block,
1202
- raw: alert,
1203
- fixable
1204
- });
1205
- }
1206
- // Lazily access constants.IPC.
1207
- if (includeExisting && !constants.IPC[SOCKET_CLI_FIX_PACKAGE_LOCK_FILE]) {
1208
- // Before we ask about problematic issues, check to see if they
1209
- // already existed in the old version if they did, be quiet.
1210
- const existing = details.find(d => d.existing?.pkgid.startsWith(`${name}@`))?.existing;
1211
- if (existing) {
1212
- const oldArtifact =
1213
- // eslint-disable-next-line no-await-in-loop
1214
- (await batchScan([existing.pkgid]).next()).value;
1215
- if (oldArtifact?.alerts?.length) {
1216
- alerts = alerts.filter(({
1217
- type
1218
- }) => !oldArtifact.alerts.find(a => a.type === type));
1219
- }
1220
- }
1221
- }
1222
- }
1223
- }
1224
- if (displayWarning && spinner$1) {
1225
- spinner$1.stop(`(socket) ${formatter.hyperlink(id, socketUrl.getSocketDevPackageOverviewUrl(NPM, name, version))} contains risks:`);
1226
- }
1227
- alerts.sort((a, b) => a.type < b.type ? -1 : 1);
1228
- if (output) {
1229
- const lines = new Set();
1230
- const translations = getTranslations();
1231
- for (const alert of alerts) {
1232
- const attributes = [...(alert.fixable ? ['fixable'] : []), ...(alert.block ? [] : ['non-blocking'])];
1233
- const maybeAttributes = attributes.length ? ` (${attributes.join('; ')})` : '';
1234
- // Based data from { pageProps: { alertTypes } } of:
1235
- // https://socket.dev/_next/data/94666139314b6437ee4491a0864e72b264547585/en-US.json
1236
- const info = translations.alerts[alert.type];
1237
- const title = info?.title ?? alert.type;
1238
- const maybeDesc = info?.description ? ` - ${info.description}` : '';
1239
- // TODO: emoji seems to mis-align terminals sometimes
1240
- lines.add(` ${title}${maybeAttributes}${maybeDesc}\n`);
1241
- }
1242
- for (const line of lines) {
1243
- output?.write(line);
1244
- }
1245
- }
1246
- spinner$1?.start();
1247
- remaining -= 1;
1248
- if (spinner$1) {
1249
- spinner$1.text = remaining > 0 ? getText() : '';
1250
- }
1251
- packageAlerts.push(...alerts);
1252
- }
1253
- } catch (e) {
1254
- npmPaths.debugLog(e);
1255
- } finally {
1256
- spinner$1?.stop();
1257
- }
1258
- return packageAlerts;
1259
- }
1260
- let _translations;
1261
- function getTranslations() {
1262
- if (_translations === undefined) {
1263
- _translations = require(
1264
- // Lazily access constants.rootPath.
1265
- path.join(constants.rootPath, 'translations.json'));
1266
- }
1267
- return _translations;
1268
- }
1269
- async function updateAdvisoryDependencies(arb, alerts) {
1270
- let patchDataByPkg;
1271
- for (const alert of alerts) {
1272
- if (!isArtifactAlertCveFixable(alert.raw)) {
1273
- continue;
1274
- }
1275
- if (!patchDataByPkg) {
1276
- patchDataByPkg = {};
1277
- }
1278
- const {
1279
- name
1280
- } = alert;
1281
- if (!patchDataByPkg[name]) {
1282
- patchDataByPkg[name] = [];
1283
- }
1284
- const {
1285
- firstPatchedVersionIdentifier,
1286
- vulnerableVersionRange
1287
- } = alert.raw.props;
1288
- patchDataByPkg[name].push({
1289
- firstPatchedVersionIdentifier,
1290
- vulnerableVersionRange
1291
- });
1292
- }
1293
- if (!patchDataByPkg) {
1294
- // No advisories to process.
1295
- return;
1296
- }
1297
- await arb.buildIdealTree();
1298
- const tree = arb.idealTree;
1299
- for (const name of Object.keys(patchDataByPkg)) {
1300
- const nodes = findPackageNodes(tree, name);
1301
- if (!nodes.length) {
1302
- continue;
1303
- }
1304
- // Fetch packument to get available versions.
1305
- // eslint-disable-next-line no-await-in-loop
1306
- const packument = await packages.fetchPackagePackument(name);
1307
- for (const node of nodes) {
1308
- const {
1309
- version
1310
- } = node;
1311
- const majorVerNum = semver.major(version);
1312
- const availableVersions = packument ? Object.keys(packument.versions) : [];
1313
- const patchData = patchDataByPkg[name];
1314
- for (const {
1315
- firstPatchedVersionIdentifier,
1316
- vulnerableVersionRange
1317
- } of patchData) {
1318
- // Find the highest non-vulnerable version within the same major range
1319
- const targetVersion = findBestPatchVersion(name, availableVersions, majorVerNum, vulnerableVersionRange);
1320
- const targetPackument = targetVersion ? packument.versions[targetVersion] : undefined;
1321
- // Check !targetVersion to make TypeScript happy.
1322
- if (!targetVersion || !targetPackument) {
1323
- // No suitable patch version found.
1324
- continue;
1325
- }
1326
- // Use Object.defineProperty to override the version.
1327
- Object.defineProperty(node, 'version', {
1328
- configurable: true,
1329
- enumerable: true,
1330
- get: () => targetVersion
1331
- });
1332
- node.package.version = targetVersion;
1333
- // Update resolved and clear integrity for the new version.
1334
- node.resolved = `${NPM_REGISTRY_URL}/${name}/-/${name}-${targetVersion}.tgz`;
1335
- if (node.integrity) {
1336
- delete node.integrity;
1337
- }
1338
- if ('deprecated' in targetPackument) {
1339
- node.package['deprecated'] = targetPackument.deprecated;
1340
- } else {
1341
- delete node.package['deprecated'];
1342
- }
1343
- const newDeps = {
1344
- ...targetPackument.dependencies
1345
- };
1346
- const {
1347
- dependencies: oldDeps
1348
- } = node.package;
1349
- node.package.dependencies = newDeps;
1350
- if (oldDeps) {
1351
- for (const oldDepName of Object.keys(oldDeps)) {
1352
- if (!objects.hasOwn(newDeps, oldDepName)) {
1353
- node.edgesOut.get(oldDepName)?.detach();
1354
- }
1355
- }
1356
- }
1357
- for (const newDepName of Object.keys(newDeps)) {
1358
- if (!objects.hasOwn(oldDeps, newDepName)) {
1359
- node.addEdgeOut(new Edge({
1360
- from: node,
1361
- name: newDepName,
1362
- spec: newDeps[newDepName],
1363
- type: 'prod'
1364
- }));
1365
- }
1366
- }
1367
- }
1368
- }
1369
- }
1370
- }
1371
- const kRiskyReify = Symbol('riskyReify');
1372
- async function reify(...args) {
1373
- const IPC = await getIPC();
1374
- // We are assuming `this[_diffTrees]()` has been called by `super.reify(...)`:
1375
- // https://github.com/npm/cli/blob/v11.0.0/workspaces/arborist/lib/arborist/reify.js#L141
1376
- let needInfoOn = getPackagesToQueryFromDiff(this.diff, {
1377
- includeUnchanged: !!IPC[SOCKET_CLI_FIX_PACKAGE_LOCK_FILE]
1378
- });
1379
- if (!needInfoOn.length) {
1380
- // Nothing to check, hmmm already installed or all private?
1381
- return await this[kRiskyReify](...args);
1382
- }
1383
- const {
1384
- [SOCKET_CLI_FIX_PACKAGE_LOCK_FILE]: bypassConfirms,
1385
- [SOCKET_CLI_UPDATE_OVERRIDES_IN_PACKAGE_LOCK_FILE]: bypassAlerts
1386
- } = IPC;
1387
- const {
1388
- stderr: output,
1389
- stdin: input
1390
- } = process;
1391
- let alerts = bypassAlerts ? [] : await getPackagesAlerts(needInfoOn, {
1392
- output
1393
- });
1394
- if (alerts.length && !bypassConfirms && !(await prompts.confirm({
1395
- message: 'Accept risks of installing these packages?',
1396
- default: false
1397
- }, {
1398
- input,
1399
- output,
1400
- signal: abortSignal
1401
- }))) {
1402
- throw new Error('Socket npm exiting due to risks');
1403
- }
1404
- if (!alerts.length || !bypassConfirms && !(await prompts.confirm({
1405
- message: 'Try to fix alerts?',
1406
- default: true
1407
- }, {
1408
- input,
1409
- output,
1410
- signal: abortSignal
1411
- }))) {
1412
- return await this[kRiskyReify](...args);
1413
- }
1414
- const prev = new Set(alerts.map(a => a.key));
1415
- let ret;
1416
- /* eslint-disable no-await-in-loop */
1417
- while (alerts.length > 0) {
1418
- await updateAdvisoryDependencies(this, alerts);
1419
- ret = await this[kRiskyReify](...args);
1420
- await this.loadActual();
1421
- await this.buildIdealTree();
1422
- needInfoOn = getPackagesToQueryFromDiff(this.diff, {
1423
- includeUnchanged: true
1424
- });
1425
- alerts = (await getPackagesAlerts(needInfoOn, {
1426
- includeExisting: true,
1427
- includeUnfixable: true
1428
- })).filter(({
1429
- key
1430
- }) => {
1431
- const unseen = !prev.has(key);
1432
- if (unseen) {
1433
- prev.add(key);
1434
- }
1435
- return unseen;
1436
- });
1437
- }
1438
- /* eslint-enable no-await-in-loop */
1439
- return ret;
1440
- }
1441
-
1442
- const Arborist = require(npmPaths.getArboristClassPath());
1443
- const kCtorArgs = Symbol('ctorArgs');
1444
-
1445
- // Implementation code not related to our custom behavior is based on
1446
- // https://github.com/npm/cli/blob/v11.0.0/workspaces/arborist/lib/arborist/index.js:
1447
- class SafeArborist extends Arborist {
1448
- constructor(...ctorArgs) {
1449
- super({
1450
- ...ctorArgs[0],
1451
- audit: true,
1452
- dryRun: true,
1453
- ignoreScripts: true,
1454
- save: false,
1455
- saveBundle: false,
1456
- // progress: false,
1457
- fund: false
1458
- }, ...ctorArgs.slice(1));
1459
- this[kCtorArgs] = ctorArgs;
1460
- }
1461
- async [kRiskyReify](...args) {
1462
- // SafeArborist has suffered side effects and must be rebuilt from scratch.
1463
- const arb = new Arborist(...this[kCtorArgs]);
1464
- arb.idealTree = this.idealTree;
1465
- const ret = await arb.reify(...args);
1466
- Object.assign(this, arb);
1467
- return ret;
1468
- }
1469
-
1470
- // @ts-ignore Incorrectly typed.
1471
- async reify(...args) {
1472
- const options = args[0] ? {
1473
- ...args[0]
1474
- } : {};
1475
- if (options.dryRun) {
1476
- return await this[kRiskyReify](...args);
1477
- }
1478
- const old = {
1479
- ...options,
1480
- dryRun: false,
1481
- save: Boolean(options.save ?? true),
1482
- saveBundle: Boolean(options.saveBundle ?? false)
1483
- };
1484
- args[0] = options;
1485
- options.dryRun = true;
1486
- options.save = false;
1487
- options.saveBundle = false;
1488
- await super.reify(...args);
1489
- options.dryRun = old.dryRun;
1490
- options.save = old.save;
1491
- options.saveBundle = old.saveBundle;
1492
- return await Reflect.apply(reify, this, args);
1493
- }
1494
- }
1495
5
 
1496
6
  function installSafeArborist() {
1497
7
  // Override '@npmcli/arborist' module exports with patched variants based on
1498
8
  // https://github.com/npm/cli/pull/7025.
1499
9
  const cache = require.cache;
1500
10
  cache[npmPaths.getArboristClassPath()] = {
1501
- exports: SafeArborist
11
+ exports: index.SafeArborist
1502
12
  };
1503
13
  cache[npmPaths.getArboristEdgeClassPath()] = {
1504
- exports: SafeEdge
14
+ exports: index.SafeEdge
1505
15
  };
1506
16
  cache[npmPaths.getArboristNodeClassPath()] = {
1507
- exports: SafeNode
17
+ exports: index.SafeNode
1508
18
  };
1509
19
  cache[npmPaths.getArboristOverrideSetClassPath()] = {
1510
- exports: SafeOverrideSet
20
+ exports: index.SafeOverrideSet
1511
21
  };
1512
22
  }
1513
23
 
1514
24
  installSafeArborist();
25
+ //# debugId=dac61d14-9648-405b-a9b5-46614799a46c
26
+ //# sourceMappingURL=npm-injection.js.map