@socketsecurity/cli-with-sentry 1.0.111 → 1.1.1
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/dist/cli.js +242 -1590
- package/dist/cli.js.map +1 -1
- package/dist/constants.js +6 -5
- package/dist/constants.js.map +1 -1
- package/dist/shadow-npm-bin.js +12 -6
- package/dist/shadow-npm-bin.js.map +1 -1
- package/dist/shadow-npm-inject.js +24 -243
- package/dist/shadow-npm-inject.js.map +1 -1
- package/dist/socket-completion.bash +1 -1
- package/dist/tsconfig.dts.tsbuildinfo +1 -1
- package/dist/types/commands/fix/cmd-fix.d.mts.map +1 -1
- package/dist/types/commands/fix/coana-fix.d.mts +1 -1
- package/dist/types/commands/fix/coana-fix.d.mts.map +1 -1
- package/dist/types/commands/fix/{fix-env-helpers.d.mts → env-helpers.d.mts} +1 -1
- package/dist/types/commands/fix/env-helpers.d.mts.map +1 -0
- package/dist/types/commands/fix/git.d.mts +13 -0
- package/dist/types/commands/fix/git.d.mts.map +1 -0
- package/dist/types/commands/fix/handle-fix.d.mts +1 -1
- package/dist/types/commands/fix/handle-fix.d.mts.map +1 -1
- package/dist/types/commands/fix/pull-request.d.mts +10 -53
- package/dist/types/commands/fix/pull-request.d.mts.map +1 -1
- package/dist/types/commands/fix/types.d.mts +18 -0
- package/dist/types/commands/fix/types.d.mts.map +1 -0
- package/dist/types/commands/scan/fetch-supported-scan-file-names.d.mts +2 -0
- package/dist/types/commands/scan/fetch-supported-scan-file-names.d.mts.map +1 -1
- package/dist/types/constants.d.mts.map +1 -1
- package/dist/types/shadow/npm/arborist/lib/arborist/index.d.mts.map +1 -1
- package/dist/types/shadow/npm/arborist-helpers.d.mts +1 -1
- package/dist/types/shadow/npm/arborist-helpers.d.mts.map +1 -1
- package/dist/types/shadow/npm/bin.d.mts.map +1 -1
- package/dist/types/shadow/npm/paths.d.mts +0 -1
- package/dist/types/shadow/npm/paths.d.mts.map +1 -1
- package/dist/types/utils/alerts-map.d.mts.map +1 -1
- package/dist/types/utils/fs.d.mts +3 -2
- package/dist/types/utils/fs.d.mts.map +1 -1
- package/dist/types/utils/github.d.mts +38 -0
- package/dist/types/utils/github.d.mts.map +1 -0
- package/dist/types/utils/glob.d.mts +0 -1
- package/dist/types/utils/glob.d.mts.map +1 -1
- package/dist/utils.js +843 -888
- package/dist/utils.js.map +1 -1
- package/dist/vendor.js +112511 -119840
- package/external/@socketsecurity/registry/external/libnpmpack.js +96569 -41361
- package/external/@socketsecurity/registry/external/pacote.js +77357 -68133
- package/external/@socketsecurity/registry/lib/fs.js +13 -27
- package/external/@socketsecurity/registry/lib/json.js +42 -0
- package/external/@socketsecurity/registry/manifest.json +4 -4
- package/package.json +11 -11
- package/dist/types/commands/fix/agent-fix.d.mts +0 -42
- package/dist/types/commands/fix/agent-fix.d.mts.map +0 -1
- package/dist/types/commands/fix/fix-branch-helpers.d.mts +0 -4
- package/dist/types/commands/fix/fix-branch-helpers.d.mts.map +0 -1
- package/dist/types/commands/fix/fix-env-helpers.d.mts.map +0 -1
- package/dist/types/commands/fix/get-actual-tree.d.mts +0 -3
- package/dist/types/commands/fix/get-actual-tree.d.mts.map +0 -1
- package/dist/types/commands/fix/npm-fix.d.mts +0 -7
- package/dist/types/commands/fix/npm-fix.d.mts.map +0 -1
- package/dist/types/commands/fix/pnpm-fix.d.mts +0 -7
- package/dist/types/commands/fix/pnpm-fix.d.mts.map +0 -1
- package/dist/types/commands/fix/shared.d.mts +0 -10
- package/dist/types/commands/fix/shared.d.mts.map +0 -1
- package/dist/types/commands/fix/socket-git.d.mts +0 -32
- package/dist/types/commands/fix/socket-git.d.mts.map +0 -1
|
@@ -8,8 +8,7 @@ var constants = require('./constants.js');
|
|
|
8
8
|
var utils = require('./utils.js');
|
|
9
9
|
var require$$9 = require('../external/@socketsecurity/registry/lib/debug');
|
|
10
10
|
var logger = require('../external/@socketsecurity/registry/lib/logger');
|
|
11
|
-
var
|
|
12
|
-
var require$$10 = require('../external/@socketsecurity/registry/lib/objects');
|
|
11
|
+
var require$$11 = require('../external/@socketsecurity/registry/lib/objects');
|
|
13
12
|
|
|
14
13
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
15
14
|
let _arboristPkgPath;
|
|
@@ -66,120 +65,14 @@ function getUrlOrigin(input) {
|
|
|
66
65
|
} catch {}
|
|
67
66
|
return '';
|
|
68
67
|
}
|
|
69
|
-
function
|
|
70
|
-
const {
|
|
71
|
-
minSatisfying = false,
|
|
72
|
-
vulnerableVersionRange
|
|
73
|
-
} = {
|
|
74
|
-
__proto__: null,
|
|
75
|
-
...options
|
|
76
|
-
};
|
|
77
|
-
const manifestData = registry.getManifestData('npm', node.name);
|
|
78
|
-
let eligibleVersions;
|
|
79
|
-
if (manifestData && manifestData.name === manifestData.package) {
|
|
80
|
-
const major = utils.getMajor(manifestData.version);
|
|
81
|
-
if (typeof major !== 'number') {
|
|
82
|
-
return null;
|
|
83
|
-
}
|
|
84
|
-
eligibleVersions = availableVersions.filter(v => utils.getMajor(v) === major);
|
|
85
|
-
} else {
|
|
86
|
-
const major = utils.getMajor(node.version);
|
|
87
|
-
if (typeof major !== 'number') {
|
|
88
|
-
return null;
|
|
89
|
-
}
|
|
90
|
-
eligibleVersions = availableVersions.filter(v =>
|
|
91
|
-
// Filter for versions that are within the current major version and
|
|
92
|
-
// are NOT in the vulnerable range.
|
|
93
|
-
utils.getMajor(v) === major && (!vulnerableVersionRange || !vendor.semverExports.satisfies(v, vulnerableVersionRange)));
|
|
94
|
-
}
|
|
95
|
-
if (eligibleVersions) {
|
|
96
|
-
const satisfying = minSatisfying ? vendor.semverExports.minSatisfying : vendor.semverExports.maxSatisfying;
|
|
97
|
-
return satisfying(eligibleVersions, '*');
|
|
98
|
-
}
|
|
99
|
-
return null;
|
|
100
|
-
}
|
|
101
|
-
function findPackageNode(tree, name, version) {
|
|
102
|
-
const queue = [tree];
|
|
103
|
-
const visited = new Set();
|
|
104
|
-
let sentinel = 0;
|
|
105
|
-
while (queue.length) {
|
|
106
|
-
if (sentinel++ === constants.LOOP_SENTINEL) {
|
|
107
|
-
throw new Error('Detected infinite loop in findPackageNode');
|
|
108
|
-
}
|
|
109
|
-
const nodeOrLink = queue.pop();
|
|
110
|
-
const node = getTargetNode(nodeOrLink);
|
|
111
|
-
if (visited.has(node)) {
|
|
112
|
-
continue;
|
|
113
|
-
}
|
|
114
|
-
visited.add(node);
|
|
115
|
-
if (node.name === name && (typeof version !== 'string' || node.version === version)) {
|
|
116
|
-
return node;
|
|
117
|
-
}
|
|
118
|
-
for (const child of node.children.values()) {
|
|
119
|
-
queue.push(child);
|
|
120
|
-
}
|
|
121
|
-
for (const edge of node.edgesOut.values()) {
|
|
122
|
-
const {
|
|
123
|
-
to
|
|
124
|
-
} = edge;
|
|
125
|
-
if (to) {
|
|
126
|
-
queue.push(to);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
return undefined;
|
|
131
|
-
}
|
|
132
|
-
function findPackageNodes(tree, name, version) {
|
|
133
|
-
const matches = [];
|
|
134
|
-
const queue = [tree];
|
|
135
|
-
const visited = new Set();
|
|
136
|
-
let sentinel = 0;
|
|
137
|
-
while (queue.length) {
|
|
138
|
-
if (sentinel++ === constants.LOOP_SENTINEL) {
|
|
139
|
-
throw new Error('Detected infinite loop in findPackageNodes');
|
|
140
|
-
}
|
|
141
|
-
const nodeOrLink = queue.pop();
|
|
142
|
-
const node = getTargetNode(nodeOrLink);
|
|
143
|
-
if (visited.has(node)) {
|
|
144
|
-
continue;
|
|
145
|
-
}
|
|
146
|
-
visited.add(node);
|
|
147
|
-
const {
|
|
148
|
-
version: targetVersion
|
|
149
|
-
} = node;
|
|
150
|
-
if (!targetVersion && Array.isArray(node.errors) && node.errors.length) {
|
|
151
|
-
require$$9.debugFn('notice', `miss: version for ${node.name} due to errors:\n`, node.errors);
|
|
152
|
-
}
|
|
153
|
-
if (node.name === name && ("undefined" !== 'string')) {
|
|
154
|
-
matches.push(node);
|
|
155
|
-
}
|
|
156
|
-
for (const child of node.children.values()) {
|
|
157
|
-
queue.push(child);
|
|
158
|
-
}
|
|
159
|
-
for (const edge of node.edgesOut.values()) {
|
|
160
|
-
const {
|
|
161
|
-
to
|
|
162
|
-
} = edge;
|
|
163
|
-
if (to) {
|
|
164
|
-
queue.push(to);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
return matches;
|
|
169
|
-
}
|
|
170
|
-
async function getAlertsMapFromArborist(arb, options) {
|
|
68
|
+
async function getAlertsMapFromArborist(arb, needInfoOn, options) {
|
|
171
69
|
const opts = {
|
|
172
70
|
__proto__: null,
|
|
173
71
|
consolidate: false,
|
|
174
72
|
nothrow: false,
|
|
175
73
|
...options,
|
|
176
|
-
filter: utils.toFilterConfig(require$$
|
|
74
|
+
filter: utils.toFilterConfig(require$$11.getOwn(options, 'filter'))
|
|
177
75
|
};
|
|
178
|
-
const needInfoOn = getDetailsFromDiff(arb.diff, {
|
|
179
|
-
filter: {
|
|
180
|
-
existing: opts.filter.existing
|
|
181
|
-
}
|
|
182
|
-
});
|
|
183
76
|
const purls = needInfoOn.map(d => utils.idToNpmPurl(d.node.pkgid));
|
|
184
77
|
let overrides;
|
|
185
78
|
const overridesMap = (arb.actualTree ?? arb.idealTree ?? (await arb.loadActual()))?.overrides?.children;
|
|
@@ -206,7 +99,7 @@ function getDetailsFromDiff(diff, options) {
|
|
|
206
99
|
const filterConfig = utils.toFilterConfig({
|
|
207
100
|
existing: false,
|
|
208
101
|
unknownOrigin: true,
|
|
209
|
-
...require$$
|
|
102
|
+
...require$$11.getOwn(options, 'filter')
|
|
210
103
|
});
|
|
211
104
|
const queue = [...diff.children];
|
|
212
105
|
let pos = 0;
|
|
@@ -273,112 +166,6 @@ function getDetailsFromDiff(diff, options) {
|
|
|
273
166
|
}
|
|
274
167
|
return details;
|
|
275
168
|
}
|
|
276
|
-
function getTargetNode(nodeOrLink) {
|
|
277
|
-
return nodeOrLink?.isLink ? nodeOrLink.target : nodeOrLink ?? null;
|
|
278
|
-
}
|
|
279
|
-
function isTopLevel(tree, node) {
|
|
280
|
-
return getTargetNode(tree.children.get(node.name)) === node;
|
|
281
|
-
}
|
|
282
|
-
function updateNode(node, newVersion, newVersionPackument) {
|
|
283
|
-
// Object.defineProperty is needed to set the version property and replace
|
|
284
|
-
// the old value with newVersion.
|
|
285
|
-
Object.defineProperty(node, 'version', {
|
|
286
|
-
configurable: true,
|
|
287
|
-
enumerable: true,
|
|
288
|
-
get: () => newVersion
|
|
289
|
-
});
|
|
290
|
-
// Update package.version associated with the node.
|
|
291
|
-
node.package.version = newVersion;
|
|
292
|
-
// Update node.resolved.
|
|
293
|
-
const purlObj = vendor.packageurlJsExports.PackageURL.fromString(utils.idToNpmPurl(node.name));
|
|
294
|
-
node.resolved = `${constants.NPM_REGISTRY_URL}/${node.name}/-/${purlObj.name}-${newVersion}.tgz`;
|
|
295
|
-
// Update node.integrity with the targetPackument.dist.integrity value if available
|
|
296
|
-
// else delete node.integrity so a new value is resolved for the target version.
|
|
297
|
-
const {
|
|
298
|
-
integrity
|
|
299
|
-
} = newVersionPackument.dist;
|
|
300
|
-
if (integrity) {
|
|
301
|
-
node.integrity = integrity;
|
|
302
|
-
} else {
|
|
303
|
-
delete node.integrity;
|
|
304
|
-
}
|
|
305
|
-
// Update node.package.deprecated based on targetPackument.deprecated.
|
|
306
|
-
if (require$$10.hasOwn(newVersionPackument, 'deprecated')) {
|
|
307
|
-
node.package['deprecated'] = newVersionPackument.deprecated;
|
|
308
|
-
} else {
|
|
309
|
-
delete node.package['deprecated'];
|
|
310
|
-
}
|
|
311
|
-
// Update node.package.dependencies.
|
|
312
|
-
const newDeps = {
|
|
313
|
-
...newVersionPackument.dependencies
|
|
314
|
-
};
|
|
315
|
-
const {
|
|
316
|
-
dependencies: oldDeps
|
|
317
|
-
} = node.package;
|
|
318
|
-
node.package.dependencies = newDeps;
|
|
319
|
-
if (oldDeps) {
|
|
320
|
-
for (const oldDepName of Object.keys(oldDeps)) {
|
|
321
|
-
if (!require$$10.hasOwn(newDeps, oldDepName)) {
|
|
322
|
-
// Detach old edges for dependencies that don't exist on the updated
|
|
323
|
-
// node.package.dependencies.
|
|
324
|
-
node.edgesOut.get(oldDepName)?.detach();
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
for (const newDepName of Object.keys(newDeps)) {
|
|
329
|
-
if (!require$$10.hasOwn(oldDeps, newDepName)) {
|
|
330
|
-
// Add new edges for dependencies that don't exist on the old
|
|
331
|
-
// node.package.dependencies.
|
|
332
|
-
node.addEdgeOut(new Edge({
|
|
333
|
-
from: node,
|
|
334
|
-
name: newDepName,
|
|
335
|
-
spec: newDeps[newDepName],
|
|
336
|
-
type: 'prod'
|
|
337
|
-
}));
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
function updatePackageJsonFromNode(editablePkgJson, tree, node, newVersion, rangeStyle) {
|
|
342
|
-
let result = false;
|
|
343
|
-
if (!isTopLevel(tree, node)) {
|
|
344
|
-
return result;
|
|
345
|
-
}
|
|
346
|
-
const {
|
|
347
|
-
name
|
|
348
|
-
} = node;
|
|
349
|
-
for (const depField of ['dependencies', 'optionalDependencies', 'peerDependencies']) {
|
|
350
|
-
const depObject = editablePkgJson.content[depField];
|
|
351
|
-
const depValue = require$$10.hasOwn(depObject, name) ? depObject[name] : undefined;
|
|
352
|
-
if (typeof depValue !== 'string' || depValue.startsWith('catalog:')) {
|
|
353
|
-
continue;
|
|
354
|
-
}
|
|
355
|
-
let oldRange = depValue;
|
|
356
|
-
// Use npa if depValue looks like more than just a semver range.
|
|
357
|
-
if (depValue.includes(':')) {
|
|
358
|
-
const npaResult = utils.npa(depValue);
|
|
359
|
-
if (!npaResult || npaResult.subSpec) {
|
|
360
|
-
continue;
|
|
361
|
-
}
|
|
362
|
-
oldRange = npaResult.rawSpec;
|
|
363
|
-
}
|
|
364
|
-
const oldMin = utils.getMinVersion(oldRange);
|
|
365
|
-
const newRange = oldMin &&
|
|
366
|
-
// Ensure we're on the same major version...
|
|
367
|
-
utils.getMajor(newVersion) === oldMin.major &&
|
|
368
|
-
// and not a downgrade.
|
|
369
|
-
vendor.semverExports.gte(newVersion, oldMin.version) ? utils.applyRange(oldRange, newVersion, rangeStyle) : oldRange;
|
|
370
|
-
if (oldRange !== newRange) {
|
|
371
|
-
result = true;
|
|
372
|
-
editablePkgJson.update({
|
|
373
|
-
[depField]: {
|
|
374
|
-
...depObject,
|
|
375
|
-
[name]: newRange
|
|
376
|
-
}
|
|
377
|
-
});
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
return result;
|
|
381
|
-
}
|
|
382
169
|
|
|
383
170
|
// @ts-ignore
|
|
384
171
|
const {
|
|
@@ -398,13 +185,6 @@ const SAFE_NO_SAVE_ARBORIST_REIFY_OPTIONS_OVERRIDES = {
|
|
|
398
185
|
saveBundle: false,
|
|
399
186
|
silent: true
|
|
400
187
|
};
|
|
401
|
-
const SAFE_WITH_SAVE_ARBORIST_REIFY_OPTIONS_OVERRIDES = {
|
|
402
|
-
// @ts-ignore
|
|
403
|
-
__proto__: null,
|
|
404
|
-
...SAFE_NO_SAVE_ARBORIST_REIFY_OPTIONS_OVERRIDES,
|
|
405
|
-
dryRun: false,
|
|
406
|
-
save: true
|
|
407
|
-
};
|
|
408
188
|
const kCtorArgs = Symbol('ctorArgs');
|
|
409
189
|
const kRiskyReify = Symbol('riskyReify');
|
|
410
190
|
const Arborist = vendor.arboristExports;
|
|
@@ -455,23 +235,34 @@ class SafeArborist extends Arborist {
|
|
|
455
235
|
},
|
|
456
236
|
// @ts-ignore: TypeScript gets grumpy about rest parameters.
|
|
457
237
|
...args.slice(1));
|
|
458
|
-
const shadowAcceptRisks = ipc[constants.SOCKET_CLI_SHADOW_ACCEPT_RISKS];
|
|
459
|
-
const shadowProgress = ipc[constants.SOCKET_CLI_SHADOW_PROGRESS];
|
|
460
|
-
const shadowSilent = ipc[constants.SOCKET_CLI_SHADOW_SILENT];
|
|
238
|
+
const shadowAcceptRisks = !!ipc[constants.SOCKET_CLI_SHADOW_ACCEPT_RISKS];
|
|
239
|
+
const shadowProgress = !!ipc[constants.SOCKET_CLI_SHADOW_PROGRESS];
|
|
240
|
+
const shadowSilent = !!ipc[constants.SOCKET_CLI_SHADOW_SILENT];
|
|
461
241
|
const acceptRisks = shadowAcceptRisks || constants.ENV.SOCKET_CLI_ACCEPT_RISKS;
|
|
242
|
+
const reportOnlyBlocking = acceptRisks || options.dryRun || options['yes'];
|
|
462
243
|
const silent = !!options['silent'];
|
|
463
244
|
const spinner = silent || !shadowProgress ? undefined : constants.spinner;
|
|
464
245
|
const isShadowNpx = binName === 'npx';
|
|
465
|
-
const
|
|
246
|
+
const hasExisting = await utils.findUp('node_modules', {
|
|
247
|
+
cwd: process.cwd(),
|
|
248
|
+
onlyDirectories: true
|
|
249
|
+
});
|
|
250
|
+
const shouldCheckExisting = reportOnlyBlocking ? true : isShadowNpx;
|
|
251
|
+
const needInfoOn = getDetailsFromDiff(this.diff, {
|
|
252
|
+
filter: {
|
|
253
|
+
existing: shouldCheckExisting
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
const alertsMap = await getAlertsMapFromArborist(this, needInfoOn, {
|
|
466
257
|
apiToken: ipc[constants.SOCKET_CLI_SHADOW_API_TOKEN],
|
|
467
258
|
spinner,
|
|
468
|
-
filter:
|
|
259
|
+
filter: reportOnlyBlocking ? {
|
|
469
260
|
actions: ['error'],
|
|
470
261
|
blocked: true,
|
|
471
|
-
existing:
|
|
262
|
+
existing: shouldCheckExisting
|
|
472
263
|
} : {
|
|
473
264
|
actions: ['error', 'monitor', 'warn'],
|
|
474
|
-
existing:
|
|
265
|
+
existing: shouldCheckExisting
|
|
475
266
|
}
|
|
476
267
|
});
|
|
477
268
|
if (alertsMap.size) {
|
|
@@ -485,7 +276,7 @@ class SafeArborist extends Arborist {
|
|
|
485
276
|
Socket ${binName} exiting due to risks.${viewAllRisks ? '' : `\nView all risks - Rerun with environment variable ${constants.SOCKET_CLI_VIEW_ALL_RISKS}=1.`}${acceptRisks ? '' : `\nAccept risks - Rerun with environment variable ${constants.SOCKET_CLI_ACCEPT_RISKS}=1.`}
|
|
486
277
|
`.trim());
|
|
487
278
|
} else if (!silent && !shadowSilent) {
|
|
488
|
-
logger.logger.success(`Socket ${binName} ${acceptRisks ? 'accepted' : 'found no'} risks`);
|
|
279
|
+
logger.logger.success(`Socket ${binName} ${acceptRisks ? 'accepted' : 'found no'}${hasExisting ? ' new' : ''} risks`);
|
|
489
280
|
if (isShadowNpx) {
|
|
490
281
|
logger.logger.log(`Running ${options.add[0]}`);
|
|
491
282
|
}
|
|
@@ -517,15 +308,5 @@ function installSafeArborist() {
|
|
|
517
308
|
}
|
|
518
309
|
|
|
519
310
|
installSafeArborist();
|
|
520
|
-
|
|
521
|
-
exports.Arborist = Arborist;
|
|
522
|
-
exports.SAFE_NO_SAVE_ARBORIST_REIFY_OPTIONS_OVERRIDES = SAFE_NO_SAVE_ARBORIST_REIFY_OPTIONS_OVERRIDES;
|
|
523
|
-
exports.SAFE_WITH_SAVE_ARBORIST_REIFY_OPTIONS_OVERRIDES = SAFE_WITH_SAVE_ARBORIST_REIFY_OPTIONS_OVERRIDES;
|
|
524
|
-
exports.findBestPatchVersion = findBestPatchVersion;
|
|
525
|
-
exports.findPackageNode = findPackageNode;
|
|
526
|
-
exports.findPackageNodes = findPackageNodes;
|
|
527
|
-
exports.getAlertsMapFromArborist = getAlertsMapFromArborist;
|
|
528
|
-
exports.updateNode = updateNode;
|
|
529
|
-
exports.updatePackageJsonFromNode = updatePackageJsonFromNode;
|
|
530
|
-
//# debugId=ef09cd0e-acf2-43e3-8f8e-3dff17a3741b
|
|
311
|
+
//# debugId=f70f8c63-2b3f-4731-b7f5-7e6cf01f055
|
|
531
312
|
//# sourceMappingURL=shadow-npm-inject.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shadow-npm-inject.js","sources":["../src/shadow/npm/paths.mts","../src/shadow/npm/arborist/types.mts","../src/shadow/npm/arborist-helpers.mts","../src/shadow/npm/arborist/lib/arborist/index.mts","../src/shadow/npm/arborist/index.mts","../src/shadow/npm/inject.mts"],"sourcesContent":["import path from 'node:path'\n\nimport { normalizePath } from '@socketsecurity/registry/lib/path'\n\nimport constants from '../../constants.mts'\nimport { getNpmRequire } from '../../utils/npm-paths.mts'\n\nlet _arboristPkgPath: string | undefined\nexport function getArboristPackagePath() {\n if (_arboristPkgPath === undefined) {\n const pkgName = '@npmcli/arborist'\n const mainPathWithForwardSlashes = normalizePath(\n getNpmRequire().resolve(pkgName),\n )\n const arboristPkgPathWithForwardSlashes = mainPathWithForwardSlashes.slice(\n 0,\n mainPathWithForwardSlashes.lastIndexOf(pkgName) + pkgName.length,\n )\n _arboristPkgPath = constants.WIN32\n ? path.normalize(arboristPkgPathWithForwardSlashes)\n : arboristPkgPathWithForwardSlashes\n }\n return _arboristPkgPath\n}\n\nlet _arboristClassPath: string | undefined\nexport function getArboristClassPath() {\n if (_arboristClassPath === undefined) {\n _arboristClassPath = path.join(\n getArboristPackagePath(),\n 'lib/arborist/index.js',\n )\n }\n return _arboristClassPath\n}\n\nlet _arboristDepValidPath: string | undefined\nexport function getArboristDepValidPath() {\n if (_arboristDepValidPath === undefined) {\n _arboristDepValidPath = path.join(\n getArboristPackagePath(),\n 'lib/dep-valid.js',\n )\n }\n return _arboristDepValidPath\n}\n\nlet _arboristEdgeClassPath: string | undefined\nexport function getArboristEdgeClassPath() {\n if (_arboristEdgeClassPath === undefined) {\n _arboristEdgeClassPath = path.join(getArboristPackagePath(), 'lib/edge.js')\n }\n return _arboristEdgeClassPath\n}\n\nlet _arboristNodeClassPath: string | undefined\nexport function getArboristNodeClassPath() {\n if (_arboristNodeClassPath === undefined) {\n _arboristNodeClassPath = path.join(getArboristPackagePath(), 'lib/node.js')\n }\n return _arboristNodeClassPath\n}\n\nlet _arboristOverrideSetClassPath: string | undefined\nexport function getArboristOverrideSetClassPath() {\n if (_arboristOverrideSetClassPath === undefined) {\n _arboristOverrideSetClassPath = path.join(\n getArboristPackagePath(),\n 'lib/override-set.js',\n )\n }\n return _arboristOverrideSetClassPath\n}\n","import { createEnum } from '../../../utils/objects.mts'\n\nimport type {\n Advisory as BaseAdvisory,\n Arborist as BaseArborist,\n Options as BaseArboristOptions,\n AuditReport as BaseAuditReport,\n Diff as BaseDiff,\n Edge as BaseEdge,\n Node as BaseNode,\n BaseOverrideSet,\n BuildIdealTreeOptions,\n ReifyOptions,\n} from '@npmcli/arborist'\n\nexport type ArboristOptions = BaseArboristOptions & {\n npmCommand?: string\n npmVersion?: string\n}\n\nexport type ArboristClass = ArboristInstance & {\n new (...args: any): ArboristInstance\n}\n\nexport type ArboristInstance = Omit<\n typeof BaseArborist,\n | 'actualTree'\n | 'auditReport'\n | 'buildIdealTree'\n | 'diff'\n | 'idealTree'\n | 'loadActual'\n | 'loadVirtual'\n | 'reify'\n> & {\n auditReport?: AuditReportInstance | null | undefined\n actualTree?: NodeClass | null | undefined\n diff: Diff | null\n idealTree?: NodeClass | null | undefined\n buildIdealTree(options?: BuildIdealTreeOptions): Promise<NodeClass>\n loadActual(options?: ArboristOptions): Promise<NodeClass>\n loadVirtual(options?: ArboristOptions): Promise<NodeClass>\n reify(options?: ArboristReifyOptions): Promise<NodeClass>\n}\n\nexport type ArboristReifyOptions = ReifyOptions & ArboristOptions\n\nexport type AuditAdvisory = Omit<BaseAdvisory, 'id'> & {\n id: number\n cwe: string[]\n cvss: {\n score: number\n vectorString: string\n }\n vulnerable_versions: string\n}\n\nexport type AuditReportInstance = Omit<BaseAuditReport, 'report'> & {\n report: { [dependency: string]: AuditAdvisory[] }\n}\n\nexport const DiffAction = createEnum({\n add: 'ADD',\n change: 'CHANGE',\n remove: 'REMOVE',\n})\n\nexport type Diff = Omit<\n BaseDiff,\n | 'actual'\n | 'children'\n | 'filterSet'\n | 'ideal'\n | 'leaves'\n | 'removed'\n | 'shrinkwrapInflated'\n | 'unchanged'\n> & {\n actual: NodeClass\n children: Diff[]\n filterSet: Set<NodeClass>\n ideal: NodeClass\n leaves: NodeClass[]\n parent: Diff | null\n removed: NodeClass[]\n shrinkwrapInflated: Set<NodeClass>\n unchanged: NodeClass[]\n}\n\nexport type EdgeClass = Omit<\n BaseEdge,\n | 'accept'\n | 'detach'\n | 'optional'\n | 'overrides'\n | 'peer'\n | 'peerConflicted'\n | 'rawSpec'\n | 'reload'\n | 'satisfiedBy'\n | 'spec'\n | 'to'\n> & {\n optional: boolean\n overrides: OverrideSetClass | undefined\n peer: boolean\n peerConflicted: boolean\n rawSpec: string\n get accept(): string | undefined\n get spec(): string\n get to(): NodeClass | null\n new (...args: any): EdgeClass\n detach(): void\n reload(hard?: boolean): void\n satisfiedBy(node: NodeClass): boolean\n}\n\nexport type LinkClass = Omit<NodeClass, 'isLink'> & {\n readonly isLink: true\n}\n\nexport type NodeClass = Omit<\n BaseNode,\n | 'addEdgeIn'\n | 'addEdgeOut'\n | 'canDedupe'\n | 'canReplace'\n | 'canReplaceWith'\n | 'children'\n | 'deleteEdgeIn'\n | 'edgesIn'\n | 'edgesOut'\n | 'from'\n | 'hasShrinkwrap'\n | 'inDepBundle'\n | 'inShrinkwrap'\n | 'integrity'\n | 'isTop'\n | 'matches'\n | 'meta'\n | 'name'\n | 'overrides'\n | 'packageName'\n | 'parent'\n | 'recalculateOutEdgesOverrides'\n | 'resolve'\n | 'resolveParent'\n | 'root'\n | 'target'\n | 'updateOverridesEdgeInAdded'\n | 'updateOverridesEdgeInRemoved'\n | 'version'\n | 'versions'\n> & {\n name: string\n version: string\n children: Map<string, NodeClass | LinkClass>\n edgesIn: Set<EdgeClass>\n edgesOut: Map<string, EdgeClass>\n from: NodeClass | null\n hasShrinkwrap: boolean\n inShrinkwrap: boolean | undefined\n integrity?: string | null\n isTop: boolean | undefined\n meta: BaseNode['meta'] & {\n addEdge(edge: EdgeClass): void\n }\n overrides: OverrideSetClass | undefined\n target: NodeClass\n versions: string[]\n get inDepBundle(): boolean\n get packageName(): string | null\n get parent(): NodeClass | null\n set parent(value: NodeClass | null)\n get resolveParent(): NodeClass | null\n get root(): NodeClass | null\n set root(value: NodeClass | null)\n new (...args: any): NodeClass\n addEdgeIn(edge: EdgeClass): void\n addEdgeOut(edge: EdgeClass): void\n canDedupe(preferDedupe?: boolean): boolean\n canReplace(node: NodeClass, ignorePeers?: string[]): boolean\n canReplaceWith(node: NodeClass, ignorePeers?: string[]): boolean\n deleteEdgeIn(edge: EdgeClass): void\n matches(node: NodeClass): boolean\n recalculateOutEdgesOverrides(): void\n resolve(name: string): NodeClass\n updateOverridesEdgeInAdded(\n otherOverrideSet: OverrideSetClass | undefined,\n ): boolean\n updateOverridesEdgeInRemoved(otherOverrideSet: OverrideSetClass): boolean\n}\n\nexport interface OverrideSetClass\n extends Omit<\n BaseOverrideSet,\n | 'ancestry'\n | 'children'\n | 'getEdgeRule'\n | 'getMatchingRule'\n | 'getNodeRule'\n | 'parent'\n | 'ruleset'\n > {\n children: Map<string, OverrideSetClass>\n key: string | undefined\n keySpec: string | undefined\n name: string | undefined\n parent: OverrideSetClass | undefined\n value: string | undefined\n version: string | undefined\n // eslint-disable-next-line @typescript-eslint/no-misused-new\n new (...args: any[]): OverrideSetClass\n get isRoot(): boolean\n get ruleset(): Map<string, OverrideSetClass>\n ancestry(): Generator<OverrideSetClass>\n childrenAreEqual(otherOverrideSet: OverrideSetClass | undefined): boolean\n getEdgeRule(edge: EdgeClass): OverrideSetClass\n getMatchingRule(node: NodeClass): OverrideSetClass | null\n getNodeRule(node: NodeClass): OverrideSetClass\n isEqual(otherOverrideSet: OverrideSetClass | undefined): boolean\n}\n","import semver from 'semver'\n\nimport { PackageURL } from '@socketregistry/packageurl-js'\nimport { getManifestData } from '@socketsecurity/registry'\nimport { debugFn } from '@socketsecurity/registry/lib/debug'\nimport { getOwn, hasOwn } from '@socketsecurity/registry/lib/objects'\nimport { fetchPackagePackument } from '@socketsecurity/registry/lib/packages'\n\nimport constants from '../../constants.mts'\nimport { Edge } from './arborist/index.mts'\nimport { DiffAction } from './arborist/types.mts'\nimport { getAlertsMapFromPurls } from '../../utils/alerts-map.mts'\nimport { toFilterConfig } from '../../utils/filter-config.mts'\nimport { npa } from '../../utils/npm-package-arg.mts'\nimport { applyRange, getMajor, getMinVersion } from '../../utils/semver.mts'\nimport { idToNpmPurl } from '../../utils/spec.mts'\n\nimport type {\n ArboristInstance,\n Diff,\n EdgeClass,\n LinkClass,\n NodeClass,\n} from './arborist/types.mts'\nimport type { AliasResult } from '../../utils/npm-package-arg.mts'\nimport type { RangeStyle } from '../../utils/semver.mts'\nimport type {\n AlertFilter,\n AlertsByPurl,\n} from '../../utils/socket-package-alert.mts'\nimport type { EditablePackageJson } from '@socketsecurity/registry/lib/packages'\nimport type { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nfunction getUrlOrigin(input: string): string {\n try {\n // TODO: URL.parse is available in Node 22.1.0. We can use it when we drop Node 18.\n // https://nodejs.org/docs/latest-v22.x/api/url.html#urlparseinput-base\n // return URL.parse(input)?.origin ?? ''\n return new URL(input).origin ?? ''\n } catch {}\n return ''\n}\n\nexport type BestPatchVersionOptions = {\n minSatisfying?: boolean | undefined\n vulnerableVersionRange?: string | undefined\n}\n\nexport function findBestPatchVersion(\n node: NodeClass,\n availableVersions: string[],\n options?: BestPatchVersionOptions | undefined,\n): string | null {\n const { minSatisfying = false, vulnerableVersionRange } = {\n __proto__: null,\n ...options,\n } as BestPatchVersionOptions\n const manifestData = getManifestData('npm', node.name)\n let eligibleVersions\n if (manifestData && manifestData.name === manifestData.package) {\n const major = getMajor(manifestData.version)\n if (typeof major !== 'number') {\n return null\n }\n eligibleVersions = availableVersions.filter(v => getMajor(v) === major)\n } else {\n const major = getMajor(node.version)\n if (typeof major !== 'number') {\n return null\n }\n eligibleVersions = availableVersions.filter(\n v =>\n // Filter for versions that are within the current major version and\n // are NOT in the vulnerable range.\n getMajor(v) === major &&\n (!vulnerableVersionRange ||\n !semver.satisfies(v, vulnerableVersionRange)),\n )\n }\n if (eligibleVersions) {\n const satisfying = minSatisfying\n ? semver.minSatisfying\n : semver.maxSatisfying\n return satisfying(eligibleVersions, '*')\n }\n return null\n}\n\nexport function findPackageNode(\n tree: NodeClass,\n name: string,\n version?: string | undefined,\n): NodeClass | undefined {\n const queue: Array<NodeClass | LinkClass> = [tree]\n const visited = new Set<NodeClass>()\n let sentinel = 0\n while (queue.length) {\n if (sentinel++ === constants.LOOP_SENTINEL) {\n throw new Error('Detected infinite loop in findPackageNode')\n }\n const nodeOrLink = queue.pop()!\n const node = getTargetNode(nodeOrLink)\n if (visited.has(node)) {\n continue\n }\n visited.add(node)\n if (\n node.name === name &&\n (typeof version !== 'string' || node.version === version)\n ) {\n return node\n }\n for (const child of node.children.values()) {\n queue.push(child)\n }\n for (const edge of node.edgesOut.values()) {\n const { to } = edge\n if (to) {\n queue.push(to)\n }\n }\n }\n return undefined\n}\n\nexport function findPackageNodes(\n tree: NodeClass,\n name: string,\n version?: string | undefined,\n): NodeClass[] {\n const matches: NodeClass[] = []\n const queue: Array<NodeClass | LinkClass> = [tree]\n const visited = new Set<NodeClass>()\n let sentinel = 0\n while (queue.length) {\n if (sentinel++ === constants.LOOP_SENTINEL) {\n throw new Error('Detected infinite loop in findPackageNodes')\n }\n const nodeOrLink = queue.pop()!\n const node = getTargetNode(nodeOrLink)\n if (visited.has(node)) {\n continue\n }\n visited.add(node)\n\n const { version: targetVersion } = node\n if (!targetVersion && Array.isArray(node.errors) && node.errors.length) {\n debugFn(\n 'notice',\n `miss: version for ${node.name} due to errors:\\n`,\n node.errors,\n )\n }\n if (\n node.name === name &&\n (typeof version !== 'string' || node.version === version)\n ) {\n matches.push(node)\n }\n for (const child of node.children.values()) {\n queue.push(child)\n }\n for (const edge of node.edgesOut.values()) {\n const { to } = edge\n if (to) {\n queue.push(to)\n }\n }\n }\n return matches\n}\n\nexport type GetAlertsMapFromArboristOptions = {\n apiToken?: string | undefined\n consolidate?: boolean | undefined\n filter?: AlertFilter | undefined\n nothrow?: boolean | undefined\n spinner?: Spinner | undefined\n}\n\nexport async function getAlertsMapFromArborist(\n arb: ArboristInstance,\n options?: GetAlertsMapFromArboristOptions | undefined,\n): Promise<AlertsByPurl> {\n const opts = {\n __proto__: null,\n consolidate: false,\n nothrow: false,\n ...options,\n filter: toFilterConfig(getOwn(options, 'filter')),\n } as GetAlertsMapFromArboristOptions & { filter: AlertFilter }\n\n const needInfoOn = getDetailsFromDiff(arb.diff, {\n filter: {\n existing: opts.filter.existing,\n },\n })\n\n const purls = needInfoOn.map(d => idToNpmPurl(d.node.pkgid))\n\n let overrides: { [key: string]: string } | undefined\n const overridesMap = (\n arb.actualTree ??\n arb.idealTree ??\n (await arb.loadActual())\n )?.overrides?.children\n if (overridesMap) {\n overrides = Object.fromEntries(\n Array.from(overridesMap.entries()).map(([key, overrideSet]) => {\n return [key, overrideSet.value!]\n }),\n )\n }\n\n return await getAlertsMapFromPurls(purls, {\n overrides,\n ...opts,\n })\n}\n\nexport type DiffQueryFilter = {\n existing?: boolean | undefined\n unknownOrigin?: boolean | undefined\n}\n\nexport type DiffQueryOptions = {\n filter?: DiffQueryFilter | undefined\n}\n\nexport type PackageDetail = {\n node: NodeClass\n existing?: NodeClass | undefined\n}\n\nexport function getDetailsFromDiff(\n diff: Diff | null,\n options?: DiffQueryOptions | undefined,\n): PackageDetail[] {\n const details: PackageDetail[] = []\n // `diff` is `null` when `npm install --package-lock-only` is passed.\n if (!diff) {\n debugFn('notice', `miss: diff is ${diff}`)\n return details\n }\n\n const { NPM_REGISTRY_URL } = constants\n\n const filterConfig = toFilterConfig({\n existing: false,\n unknownOrigin: true,\n ...getOwn(options, 'filter'),\n }) as DiffQueryFilter\n\n const queue: Diff[] = [...diff.children]\n let pos = 0\n let { length: queueLength } = queue\n while (pos < queueLength) {\n if (pos === constants.LOOP_SENTINEL) {\n throw new Error('Detected infinite loop while walking Arborist diff')\n }\n const currDiff = queue[pos++]!\n const { action } = currDiff\n if (action) {\n // The `pkgNode`, i.e. the `ideal` node, will be `undefined` if the diff\n // action is 'REMOVE'\n // The `oldNode`, i.e. the `actual` node, will be `undefined` if the diff\n // action is 'ADD'.\n const { actual: oldNode, ideal: pkgNode } = currDiff\n let existing: NodeClass | undefined\n let keep = false\n if (action === DiffAction.change) {\n if (pkgNode?.package.version !== oldNode?.package.version) {\n keep = true\n if (\n oldNode?.package.name &&\n oldNode.package.name === pkgNode?.package.name\n ) {\n existing = oldNode\n }\n }\n } else {\n keep = action !== DiffAction.remove\n }\n if (keep && pkgNode?.resolved && (!oldNode || oldNode.resolved)) {\n if (\n filterConfig.unknownOrigin ||\n getUrlOrigin(pkgNode.resolved) === NPM_REGISTRY_URL\n ) {\n details.push({\n node: pkgNode,\n existing,\n })\n }\n }\n }\n for (const child of currDiff.children) {\n queue[queueLength++] = child\n }\n }\n if (filterConfig.existing) {\n const { unchanged } = diff\n for (let i = 0, { length } = unchanged; i < length; i += 1) {\n const pkgNode = unchanged[i]!\n if (\n filterConfig.unknownOrigin ||\n getUrlOrigin(pkgNode.resolved!) === NPM_REGISTRY_URL\n ) {\n details.push({\n node: pkgNode,\n existing: pkgNode,\n })\n }\n }\n }\n return details\n}\n\nexport function getTargetNode(nodeOrLink: NodeClass | LinkClass): NodeClass\nexport function getTargetNode<T>(nodeOrLink: T): NodeClass | null\nexport function getTargetNode(nodeOrLink: any): NodeClass | null {\n return nodeOrLink?.isLink ? nodeOrLink.target : (nodeOrLink ?? null)\n}\n\nexport function isTopLevel(tree: NodeClass, node: NodeClass): boolean {\n return getTargetNode(tree.children.get(node.name)) === node\n}\n\nexport type Packument = Exclude<\n Awaited<ReturnType<typeof fetchPackagePackument>>,\n null\n>\n\nexport function updateNode(\n node: NodeClass,\n newVersion: string,\n newVersionPackument: Packument['versions'][number],\n): void {\n // Object.defineProperty is needed to set the version property and replace\n // the old value with newVersion.\n Object.defineProperty(node, 'version', {\n configurable: true,\n enumerable: true,\n get: () => newVersion,\n })\n // Update package.version associated with the node.\n node.package.version = newVersion\n // Update node.resolved.\n const purlObj = PackageURL.fromString(idToNpmPurl(node.name))\n node.resolved = `${constants.NPM_REGISTRY_URL}/${node.name}/-/${purlObj.name}-${newVersion}.tgz`\n // Update node.integrity with the targetPackument.dist.integrity value if available\n // else delete node.integrity so a new value is resolved for the target version.\n const { integrity } = newVersionPackument.dist\n if (integrity) {\n node.integrity = integrity\n } else {\n delete node.integrity\n }\n // Update node.package.deprecated based on targetPackument.deprecated.\n if (hasOwn(newVersionPackument, 'deprecated')) {\n node.package['deprecated'] = newVersionPackument.deprecated as string\n } else {\n delete node.package['deprecated']\n }\n // Update node.package.dependencies.\n const newDeps = { ...newVersionPackument.dependencies }\n const { dependencies: oldDeps } = node.package\n node.package.dependencies = newDeps\n if (oldDeps) {\n for (const oldDepName of Object.keys(oldDeps)) {\n if (!hasOwn(newDeps, oldDepName)) {\n // Detach old edges for dependencies that don't exist on the updated\n // node.package.dependencies.\n node.edgesOut.get(oldDepName)?.detach()\n }\n }\n }\n for (const newDepName of Object.keys(newDeps)) {\n if (!hasOwn(oldDeps, newDepName)) {\n // Add new edges for dependencies that don't exist on the old\n // node.package.dependencies.\n node.addEdgeOut(\n new Edge({\n from: node,\n name: newDepName,\n spec: newDeps[newDepName],\n type: 'prod',\n }) as unknown as EdgeClass,\n )\n }\n }\n}\n\nexport function updatePackageJsonFromNode(\n editablePkgJson: EditablePackageJson,\n tree: NodeClass,\n node: NodeClass,\n newVersion: string,\n rangeStyle?: RangeStyle | undefined,\n): boolean {\n let result = false\n if (!isTopLevel(tree, node)) {\n return result\n }\n const { name } = node\n for (const depField of [\n 'dependencies',\n 'optionalDependencies',\n 'peerDependencies',\n ]) {\n const depObject = editablePkgJson.content[depField] as\n | { [key: string]: string }\n | undefined\n const depValue = hasOwn(depObject, name) ? depObject[name] : undefined\n if (typeof depValue !== 'string' || depValue.startsWith('catalog:')) {\n continue\n }\n let oldRange = depValue\n // Use npa if depValue looks like more than just a semver range.\n if (depValue.includes(':')) {\n const npaResult = npa(depValue)\n if (!npaResult || (npaResult as AliasResult).subSpec) {\n continue\n }\n oldRange = npaResult.rawSpec\n }\n const oldMin = getMinVersion(oldRange)\n const newRange =\n oldMin &&\n // Ensure we're on the same major version...\n getMajor(newVersion) === oldMin.major &&\n // and not a downgrade.\n semver.gte(newVersion, oldMin.version)\n ? applyRange(oldRange, newVersion, rangeStyle)\n : oldRange\n if (oldRange !== newRange) {\n result = true\n editablePkgJson.update({\n [depField]: {\n ...depObject,\n [name]: newRange,\n },\n })\n }\n }\n return result\n}\n","// @ts-ignore\nimport UntypedArborist from '@npmcli/arborist/lib/arborist/index.js'\n\nimport { debugDir } from '@socketsecurity/registry/lib/debug'\nimport { logger } from '@socketsecurity/registry/lib/logger'\n\nimport constants from '../../../../../constants.mts'\nimport { logAlertsMap } from '../../../../../utils/socket-package-alert.mts'\nimport { getAlertsMapFromArborist } from '../../../arborist-helpers.mts'\n\nimport type {\n ArboristClass,\n ArboristReifyOptions,\n NodeClass,\n} from '../../types.mts'\n\nconst {\n kInternalsSymbol,\n [kInternalsSymbol as unknown as 'Symbol(kInternalsSymbol)']: { getIpc },\n} = constants\n\nexport const SAFE_NO_SAVE_ARBORIST_REIFY_OPTIONS_OVERRIDES = {\n __proto__: null,\n audit: false,\n dryRun: true,\n fund: false,\n ignoreScripts: true,\n progress: false,\n save: false,\n saveBundle: false,\n silent: true,\n}\n\nexport const SAFE_WITH_SAVE_ARBORIST_REIFY_OPTIONS_OVERRIDES = {\n // @ts-ignore\n __proto__: null,\n ...SAFE_NO_SAVE_ARBORIST_REIFY_OPTIONS_OVERRIDES,\n dryRun: false,\n save: true,\n}\n\nexport const kCtorArgs = Symbol('ctorArgs')\n\nexport const kRiskyReify = Symbol('riskyReify')\n\nexport const Arborist: ArboristClass = UntypedArborist\n\n// Implementation code not related to our custom behavior is based on\n// https://github.com/npm/cli/blob/v11.0.0/workspaces/arborist/lib/arborist/index.js:\nexport class SafeArborist extends Arborist {\n constructor(...ctorArgs: ConstructorParameters<ArboristClass>) {\n super(\n {\n path:\n (ctorArgs.length ? ctorArgs[0]?.path : undefined) ?? process.cwd(),\n ...(ctorArgs.length ? ctorArgs[0] : undefined),\n ...SAFE_NO_SAVE_ARBORIST_REIFY_OPTIONS_OVERRIDES,\n },\n ...ctorArgs.slice(1),\n )\n ;(this as any)[kCtorArgs] = ctorArgs\n }\n\n async [kRiskyReify](\n ...args: Parameters<InstanceType<ArboristClass>['reify']>\n ): Promise<NodeClass> {\n const ctorArgs = (this as any)[kCtorArgs]\n const arb = new Arborist(\n {\n ...(ctorArgs.length ? ctorArgs[0] : undefined),\n progress: false,\n },\n ...ctorArgs.slice(1),\n )\n const ret = await (arb.reify as (...args: any[]) => Promise<NodeClass>)(\n {\n ...(args.length ? args[0] : undefined),\n progress: false,\n },\n ...args.slice(1),\n )\n Object.assign(this, arb)\n return ret\n }\n\n // @ts-ignore Incorrectly typed.\n override async reify(\n this: SafeArborist,\n ...args: Parameters<InstanceType<ArboristClass>['reify']>\n ): Promise<NodeClass> {\n const options = {\n __proto__: null,\n ...(args.length ? args[0] : undefined),\n } as ArboristReifyOptions\n\n const ipc = await getIpc()\n debugDir('inspect', { ipc })\n\n const binName = ipc[constants.SOCKET_CLI_SHADOW_BIN]\n if (!binName) {\n return await this[kRiskyReify](...args)\n }\n\n await super.reify(\n {\n ...options,\n ...SAFE_NO_SAVE_ARBORIST_REIFY_OPTIONS_OVERRIDES,\n progress: false,\n },\n // @ts-ignore: TypeScript gets grumpy about rest parameters.\n ...args.slice(1),\n )\n\n const shadowAcceptRisks = ipc[constants.SOCKET_CLI_SHADOW_ACCEPT_RISKS]\n const shadowProgress = ipc[constants.SOCKET_CLI_SHADOW_PROGRESS]\n const shadowSilent = ipc[constants.SOCKET_CLI_SHADOW_SILENT]\n\n const acceptRisks =\n shadowAcceptRisks || constants.ENV.SOCKET_CLI_ACCEPT_RISKS\n const silent = !!options['silent']\n const spinner = silent || !shadowProgress ? undefined : constants.spinner\n const isShadowNpx = binName === 'npx'\n\n const alertsMap = await getAlertsMapFromArborist(this, {\n apiToken: ipc[constants.SOCKET_CLI_SHADOW_API_TOKEN],\n spinner,\n filter:\n acceptRisks || options.dryRun || options['yes']\n ? {\n actions: ['error'],\n blocked: true,\n existing: true,\n }\n : {\n actions: ['error', 'monitor', 'warn'],\n existing: isShadowNpx,\n },\n })\n\n if (alertsMap.size) {\n process.exitCode = 1\n const viewAllRisks = constants.ENV.SOCKET_CLI_VIEW_ALL_RISKS\n logAlertsMap(alertsMap, {\n hideAt: viewAllRisks ? 'none' : 'middle',\n output: process.stderr,\n })\n throw new Error(\n `\n Socket ${binName} exiting due to risks.${\n viewAllRisks\n ? ''\n : `\\nView all risks - Rerun with environment variable ${constants.SOCKET_CLI_VIEW_ALL_RISKS}=1.`\n }${\n acceptRisks\n ? ''\n : `\\nAccept risks - Rerun with environment variable ${constants.SOCKET_CLI_ACCEPT_RISKS}=1.`\n }\n `.trim(),\n )\n } else if (!silent && !shadowSilent) {\n logger.success(\n `Socket ${binName} ${acceptRisks ? 'accepted' : 'found no'} risks`,\n )\n if (isShadowNpx) {\n logger.log(`Running ${options.add![0]}`)\n }\n }\n\n return await this[kRiskyReify](...args)\n }\n}\n","import { createRequire } from 'node:module'\n\n// @ts-ignore\nimport UntypedEdge from '@npmcli/arborist/lib/edge.js'\n// @ts-ignore\nimport UntypedNode from '@npmcli/arborist/lib/node.js'\n// @ts-ignore\nimport UntypedOverrideSet from '@npmcli/arborist/lib/override-set.js'\n\nimport {\n getArboristClassPath,\n getArboristEdgeClassPath,\n getArboristNodeClassPath,\n getArboristOverrideSetClassPath,\n} from '../paths.mts'\nimport { Arborist, SafeArborist } from './lib/arborist/index.mts'\n\nimport type { EdgeClass, NodeClass, OverrideSetClass } from './types.mts'\n\nconst require = createRequire(import.meta.url)\n\nexport { Arborist, SafeArborist }\n\nexport const Edge: EdgeClass = UntypedEdge\n\nexport const Node: NodeClass = UntypedNode\n\nexport const OverrideSet: OverrideSetClass = UntypedOverrideSet\n\nexport function installSafeArborist() {\n // Override '@npmcli/arborist' module exports with patched variants based on\n // https://github.com/npm/cli/pull/8089.\n const cache: { [key: string]: any } = require.cache\n cache[getArboristClassPath()] = { exports: SafeArborist }\n cache[getArboristEdgeClassPath()] = { exports: Edge }\n cache[getArboristNodeClassPath()] = { exports: Node }\n cache[getArboristOverrideSetClassPath()] = { exports: OverrideSet }\n}\n","import { installSafeArborist } from './arborist/index.mts'\n\ninstallSafeArborist()\n"],"names":["_arboristPkgPath","add","change","remove","minSatisfying","vulnerableVersionRange","__proto__","eligibleVersions","getMajor","visited","queue","to","version","debugFn","matches","consolidate","nothrow","filter","existing","NPM_REGISTRY_URL","unknownOrigin","length","action","actual","ideal","keep","node","unchanged","Object","configurable","enumerable","integrity","dependencies","from","name","spec","type","semver","result","getIpc","audit","dryRun","fund","ignoreScripts","progress","save","saveBundle","silent","path","ipc","apiToken","blocked","actions","hideAt","logger","cache","exports","installSafeArborist"],"mappings":";;;;;;;;;;;;;;AAOA;AACO;;;AAGH;AAGA;AAIAA;AAGF;AACA;AACF;AAEA;AACO;;;AAML;AACA;AACF;AAaA;AACO;;;AAGL;AACA;AACF;AAEA;AACO;;;AAGL;AACA;AACF;AAEA;AACO;;;AAML;AACA;AACF;;ACXO;AACLC;AACAC;AACAC;AACF;;AChCA;;AAEI;AACA;AACA;;;AAGF;AACF;AAOO;;AAKGC;AAAuBC;AAAuB;AACpDC;;;;AAIF;;AAEE;AACA;AACE;AACF;AACAC;AACF;AACE;AACA;AACE;AACF;AACAA;AAEI;AACA;AACAC;AAIN;AACA;;AAIE;AACF;AACA;AACF;AAEO;AAKL;AACA;;;AAGE;AACE;AACF;AACA;AACA;AACA;AACE;AACF;AACAC;AACA;AAIE;AACF;;AAEEC;AACF;;;AAEUC;AAAG;AACX;AACED;AACF;AACF;AACF;AACA;AACF;AAEO;;AAML;AACA;;;AAGE;AACE;AACF;AACA;AACA;AACA;AACE;AACF;AACAD;;AAEQG;AAAuB;AAC/B;AACEC;AAKF;AACA;AAIEC;AACF;;AAEEJ;AACF;;;AAEUC;AAAG;AACX;AACED;AACF;AACF;AACF;AACA;AACF;AAUO;AAIL;AACEJ;AACAS;AACAC;AACA;;;AAIF;AACEC;AACEC;AACF;AACF;AAEA;AAEA;;AAMA;;AAGM;AACF;AAEJ;AAEA;;;AAGA;AACF;AAgBO;;AAKL;;AAEEL;AACA;AACF;;AAEQM;AAAiB;;AAGvBD;AACAE;AACA;AACF;AAEA;;;AAEMC;AAAoB;;AAExB;AACE;AACF;AACA;;AACQC;AAAO;AACf;AACE;AACA;AACA;AACA;;AACQC;AAAiBC;AAAe;AACxC;;AAEA;;AAEIC;AACA;AAIEP;AACF;AACF;AACF;AACEO;AACF;AACA;AACE;;AAKIC;AACAR;AACF;AACF;AACF;AACF;AACA;AACER;AACF;AACF;;;AAEUiB;AAAU;AAClB;AAAkBN;;AAChB;AACA;;AAKIK;AACAR;AACF;AACF;AACF;AACF;AACA;AACF;AAIO;;AAEP;AAEO;AACL;AACF;AAOO;AAKL;AACA;AACAU;AACEC;AACAC;;AAEF;AACA;AACAJ;AACA;AACA;AACAA;AACA;AACA;;AACQK;;AACR;;AAEA;;AAEA;AACA;AACA;;AAEA;AACE;AACF;AACA;AACA;AAAkB;;;AACVC;;AACRN;AACA;;AAEI;AACE;AACA;;AAEF;AACF;AACF;;AAEE;AACE;AACA;AACAA;AAEIO;AACAC;AACAC;AACAC;AACF;AAEJ;AACF;AACF;AAEO;;AAQL;AACE;AACF;;AACQF;AAAK;;AAMX;AAGA;;AAEE;AACF;;AAEA;AACA;AACE;AACA;AACE;AACF;;AAEF;AACA;;AAGE;AACA1B;AACA;AACA6B;;AAIAC;;AAEE;AACE;AACA;AACF;AACF;AACF;AACF;AACA;AACF;;AC7bA;AAgBA;;AAEE;AAA+DC;AAAO;AACxE;AAEO;AACLjC;AACAkC;AACAC;AACAC;AACAC;AACAC;AACAC;AACAC;AACAC;AACF;AAEO;AACL;AACAzC;AACA;AACAmC;AACAI;AACF;AAEO;AAEA;AAEA;;AAEP;AACA;AACO;;AAEH;AAEIG;;;;AAOF;AACJ;AAEA;AAGE;AACA;;AAGIJ;;AAIJ;;AAGIA;;AAIJhB;AACA;AACF;;AAEA;AACA;AAIE;AACEtB;;;AAIF;;AACsB2C;AAAI;AAE1B;;;AAGA;;AAII;AACA;AACAL;;AAEF;AACA;AAGF;AACA;AACA;;AAIA;;AAEA;AAEA;AACEM;;;;AAMQC;AACAjC;AACF;AAEEkC;AACAlC;AACF;AACR;;;AAIE;;AAEEmC;;AAEF;;AAGN;AAQA;AAGI;AACEC;AAGA;;AAEA;AACF;;AAGF;AACF;;ACvJA;AAIO;AAEA;AAEA;AAEA;AACL;AACA;AACA;AACAC;AAAkCC;;AAClCD;AAAsCC;;AACtCD;AAAsCC;;AACtCD;AAA6CC;;AAC/C;;ACnCAC;;;;;;;;;;","debugId":"ef09cd0e-acf2-43e3-8f8e-3dff17a3741b"}
|
|
1
|
+
{"version":3,"file":"shadow-npm-inject.js","sources":["../src/shadow/npm/paths.mts","../src/shadow/npm/arborist/types.mts","../src/shadow/npm/arborist-helpers.mts","../src/shadow/npm/arborist/lib/arborist/index.mts","../src/shadow/npm/arborist/index.mts","../src/shadow/npm/inject.mts"],"sourcesContent":["import path from 'node:path'\n\nimport { normalizePath } from '@socketsecurity/registry/lib/path'\n\nimport constants from '../../constants.mts'\nimport { getNpmRequire } from '../../utils/npm-paths.mts'\n\nlet _arboristPkgPath: string | undefined\nexport function getArboristPackagePath() {\n if (_arboristPkgPath === undefined) {\n const pkgName = '@npmcli/arborist'\n const mainPathWithForwardSlashes = normalizePath(\n getNpmRequire().resolve(pkgName),\n )\n const arboristPkgPathWithForwardSlashes = mainPathWithForwardSlashes.slice(\n 0,\n mainPathWithForwardSlashes.lastIndexOf(pkgName) + pkgName.length,\n )\n _arboristPkgPath = constants.WIN32\n ? path.normalize(arboristPkgPathWithForwardSlashes)\n : arboristPkgPathWithForwardSlashes\n }\n return _arboristPkgPath\n}\n\nlet _arboristClassPath: string | undefined\nexport function getArboristClassPath() {\n if (_arboristClassPath === undefined) {\n _arboristClassPath = path.join(\n getArboristPackagePath(),\n 'lib/arborist/index.js',\n )\n }\n return _arboristClassPath\n}\n\nlet _arboristEdgeClassPath: string | undefined\nexport function getArboristEdgeClassPath() {\n if (_arboristEdgeClassPath === undefined) {\n _arboristEdgeClassPath = path.join(getArboristPackagePath(), 'lib/edge.js')\n }\n return _arboristEdgeClassPath\n}\n\nlet _arboristNodeClassPath: string | undefined\nexport function getArboristNodeClassPath() {\n if (_arboristNodeClassPath === undefined) {\n _arboristNodeClassPath = path.join(getArboristPackagePath(), 'lib/node.js')\n }\n return _arboristNodeClassPath\n}\n\nlet _arboristOverrideSetClassPath: string | undefined\nexport function getArboristOverrideSetClassPath() {\n if (_arboristOverrideSetClassPath === undefined) {\n _arboristOverrideSetClassPath = path.join(\n getArboristPackagePath(),\n 'lib/override-set.js',\n )\n }\n return _arboristOverrideSetClassPath\n}\n","import { createEnum } from '../../../utils/objects.mts'\n\nimport type {\n Advisory as BaseAdvisory,\n Arborist as BaseArborist,\n Options as BaseArboristOptions,\n AuditReport as BaseAuditReport,\n Diff as BaseDiff,\n Edge as BaseEdge,\n Node as BaseNode,\n BaseOverrideSet,\n BuildIdealTreeOptions,\n ReifyOptions,\n} from '@npmcli/arborist'\n\nexport type ArboristOptions = BaseArboristOptions & {\n npmCommand?: string\n npmVersion?: string\n}\n\nexport type ArboristClass = ArboristInstance & {\n new (...args: any): ArboristInstance\n}\n\nexport type ArboristInstance = Omit<\n typeof BaseArborist,\n | 'actualTree'\n | 'auditReport'\n | 'buildIdealTree'\n | 'diff'\n | 'idealTree'\n | 'loadActual'\n | 'loadVirtual'\n | 'reify'\n> & {\n auditReport?: AuditReportInstance | null | undefined\n actualTree?: NodeClass | null | undefined\n diff: Diff | null\n idealTree?: NodeClass | null | undefined\n buildIdealTree(options?: BuildIdealTreeOptions): Promise<NodeClass>\n loadActual(options?: ArboristOptions): Promise<NodeClass>\n loadVirtual(options?: ArboristOptions): Promise<NodeClass>\n reify(options?: ArboristReifyOptions): Promise<NodeClass>\n}\n\nexport type ArboristReifyOptions = ReifyOptions & ArboristOptions\n\nexport type AuditAdvisory = Omit<BaseAdvisory, 'id'> & {\n id: number\n cwe: string[]\n cvss: {\n score: number\n vectorString: string\n }\n vulnerable_versions: string\n}\n\nexport type AuditReportInstance = Omit<BaseAuditReport, 'report'> & {\n report: { [dependency: string]: AuditAdvisory[] }\n}\n\nexport const DiffAction = createEnum({\n add: 'ADD',\n change: 'CHANGE',\n remove: 'REMOVE',\n})\n\nexport type Diff = Omit<\n BaseDiff,\n | 'actual'\n | 'children'\n | 'filterSet'\n | 'ideal'\n | 'leaves'\n | 'removed'\n | 'shrinkwrapInflated'\n | 'unchanged'\n> & {\n actual: NodeClass\n children: Diff[]\n filterSet: Set<NodeClass>\n ideal: NodeClass\n leaves: NodeClass[]\n parent: Diff | null\n removed: NodeClass[]\n shrinkwrapInflated: Set<NodeClass>\n unchanged: NodeClass[]\n}\n\nexport type EdgeClass = Omit<\n BaseEdge,\n | 'accept'\n | 'detach'\n | 'optional'\n | 'overrides'\n | 'peer'\n | 'peerConflicted'\n | 'rawSpec'\n | 'reload'\n | 'satisfiedBy'\n | 'spec'\n | 'to'\n> & {\n optional: boolean\n overrides: OverrideSetClass | undefined\n peer: boolean\n peerConflicted: boolean\n rawSpec: string\n get accept(): string | undefined\n get spec(): string\n get to(): NodeClass | null\n new (...args: any): EdgeClass\n detach(): void\n reload(hard?: boolean): void\n satisfiedBy(node: NodeClass): boolean\n}\n\nexport type LinkClass = Omit<NodeClass, 'isLink'> & {\n readonly isLink: true\n}\n\nexport type NodeClass = Omit<\n BaseNode,\n | 'addEdgeIn'\n | 'addEdgeOut'\n | 'canDedupe'\n | 'canReplace'\n | 'canReplaceWith'\n | 'children'\n | 'deleteEdgeIn'\n | 'edgesIn'\n | 'edgesOut'\n | 'from'\n | 'hasShrinkwrap'\n | 'inDepBundle'\n | 'inShrinkwrap'\n | 'integrity'\n | 'isTop'\n | 'matches'\n | 'meta'\n | 'name'\n | 'overrides'\n | 'packageName'\n | 'parent'\n | 'recalculateOutEdgesOverrides'\n | 'resolve'\n | 'resolveParent'\n | 'root'\n | 'target'\n | 'updateOverridesEdgeInAdded'\n | 'updateOverridesEdgeInRemoved'\n | 'version'\n | 'versions'\n> & {\n name: string\n version: string\n children: Map<string, NodeClass | LinkClass>\n edgesIn: Set<EdgeClass>\n edgesOut: Map<string, EdgeClass>\n from: NodeClass | null\n hasShrinkwrap: boolean\n inShrinkwrap: boolean | undefined\n integrity?: string | null\n isTop: boolean | undefined\n meta: BaseNode['meta'] & {\n addEdge(edge: EdgeClass): void\n }\n overrides: OverrideSetClass | undefined\n target: NodeClass\n versions: string[]\n get inDepBundle(): boolean\n get packageName(): string | null\n get parent(): NodeClass | null\n set parent(value: NodeClass | null)\n get resolveParent(): NodeClass | null\n get root(): NodeClass | null\n set root(value: NodeClass | null)\n new (...args: any): NodeClass\n addEdgeIn(edge: EdgeClass): void\n addEdgeOut(edge: EdgeClass): void\n canDedupe(preferDedupe?: boolean): boolean\n canReplace(node: NodeClass, ignorePeers?: string[]): boolean\n canReplaceWith(node: NodeClass, ignorePeers?: string[]): boolean\n deleteEdgeIn(edge: EdgeClass): void\n matches(node: NodeClass): boolean\n recalculateOutEdgesOverrides(): void\n resolve(name: string): NodeClass\n updateOverridesEdgeInAdded(\n otherOverrideSet: OverrideSetClass | undefined,\n ): boolean\n updateOverridesEdgeInRemoved(otherOverrideSet: OverrideSetClass): boolean\n}\n\nexport interface OverrideSetClass\n extends Omit<\n BaseOverrideSet,\n | 'ancestry'\n | 'children'\n | 'getEdgeRule'\n | 'getMatchingRule'\n | 'getNodeRule'\n | 'parent'\n | 'ruleset'\n > {\n children: Map<string, OverrideSetClass>\n key: string | undefined\n keySpec: string | undefined\n name: string | undefined\n parent: OverrideSetClass | undefined\n value: string | undefined\n version: string | undefined\n // eslint-disable-next-line @typescript-eslint/no-misused-new\n new (...args: any[]): OverrideSetClass\n get isRoot(): boolean\n get ruleset(): Map<string, OverrideSetClass>\n ancestry(): Generator<OverrideSetClass>\n childrenAreEqual(otherOverrideSet: OverrideSetClass | undefined): boolean\n getEdgeRule(edge: EdgeClass): OverrideSetClass\n getMatchingRule(node: NodeClass): OverrideSetClass | null\n getNodeRule(node: NodeClass): OverrideSetClass\n isEqual(otherOverrideSet: OverrideSetClass | undefined): boolean\n}\n","import semver from 'semver'\n\nimport { PackageURL } from '@socketregistry/packageurl-js'\nimport { getManifestData } from '@socketsecurity/registry'\nimport { debugFn } from '@socketsecurity/registry/lib/debug'\nimport { getOwn, hasOwn } from '@socketsecurity/registry/lib/objects'\nimport { fetchPackagePackument } from '@socketsecurity/registry/lib/packages'\n\nimport constants from '../../constants.mts'\nimport { Edge } from './arborist/index.mts'\nimport { DiffAction } from './arborist/types.mts'\nimport { getAlertsMapFromPurls } from '../../utils/alerts-map.mts'\nimport { toFilterConfig } from '../../utils/filter-config.mts'\nimport { npa } from '../../utils/npm-package-arg.mts'\nimport { applyRange, getMajor, getMinVersion } from '../../utils/semver.mts'\nimport { idToNpmPurl } from '../../utils/spec.mts'\n\nimport type {\n ArboristInstance,\n Diff,\n EdgeClass,\n LinkClass,\n NodeClass,\n} from './arborist/types.mts'\nimport type { AliasResult } from '../../utils/npm-package-arg.mts'\nimport type { RangeStyle } from '../../utils/semver.mts'\nimport type {\n AlertFilter,\n AlertsByPurl,\n} from '../../utils/socket-package-alert.mts'\nimport type { EditablePackageJson } from '@socketsecurity/registry/lib/packages'\nimport type { Spinner } from '@socketsecurity/registry/lib/spinner'\n\nfunction getUrlOrigin(input: string): string {\n try {\n // TODO: URL.parse is available in Node 22.1.0. We can use it when we drop Node 18.\n // https://nodejs.org/docs/latest-v22.x/api/url.html#urlparseinput-base\n // return URL.parse(input)?.origin ?? ''\n return new URL(input).origin ?? ''\n } catch {}\n return ''\n}\n\nexport type BestPatchVersionOptions = {\n minSatisfying?: boolean | undefined\n vulnerableVersionRange?: string | undefined\n}\n\nexport function findBestPatchVersion(\n node: NodeClass,\n availableVersions: string[],\n options?: BestPatchVersionOptions | undefined,\n): string | null {\n const { minSatisfying = false, vulnerableVersionRange } = {\n __proto__: null,\n ...options,\n } as BestPatchVersionOptions\n const manifestData = getManifestData('npm', node.name)\n let eligibleVersions\n if (manifestData && manifestData.name === manifestData.package) {\n const major = getMajor(manifestData.version)\n if (typeof major !== 'number') {\n return null\n }\n eligibleVersions = availableVersions.filter(v => getMajor(v) === major)\n } else {\n const major = getMajor(node.version)\n if (typeof major !== 'number') {\n return null\n }\n eligibleVersions = availableVersions.filter(\n v =>\n // Filter for versions that are within the current major version and\n // are NOT in the vulnerable range.\n getMajor(v) === major &&\n (!vulnerableVersionRange ||\n !semver.satisfies(v, vulnerableVersionRange)),\n )\n }\n if (eligibleVersions) {\n const satisfying = minSatisfying\n ? semver.minSatisfying\n : semver.maxSatisfying\n return satisfying(eligibleVersions, '*')\n }\n return null\n}\n\nexport function findPackageNode(\n tree: NodeClass,\n name: string,\n version?: string | undefined,\n): NodeClass | undefined {\n const queue: Array<NodeClass | LinkClass> = [tree]\n const visited = new Set<NodeClass>()\n let sentinel = 0\n while (queue.length) {\n if (sentinel++ === constants.LOOP_SENTINEL) {\n throw new Error('Detected infinite loop in findPackageNode')\n }\n const nodeOrLink = queue.pop()!\n const node = getTargetNode(nodeOrLink)\n if (visited.has(node)) {\n continue\n }\n visited.add(node)\n if (\n node.name === name &&\n (typeof version !== 'string' || node.version === version)\n ) {\n return node\n }\n for (const child of node.children.values()) {\n queue.push(child)\n }\n for (const edge of node.edgesOut.values()) {\n const { to } = edge\n if (to) {\n queue.push(to)\n }\n }\n }\n return undefined\n}\n\nexport function findPackageNodes(\n tree: NodeClass,\n name: string,\n version?: string | undefined,\n): NodeClass[] {\n const matches: NodeClass[] = []\n const queue: Array<NodeClass | LinkClass> = [tree]\n const visited = new Set<NodeClass>()\n let sentinel = 0\n while (queue.length) {\n if (sentinel++ === constants.LOOP_SENTINEL) {\n throw new Error('Detected infinite loop in findPackageNodes')\n }\n const nodeOrLink = queue.pop()!\n const node = getTargetNode(nodeOrLink)\n if (visited.has(node)) {\n continue\n }\n visited.add(node)\n\n const { version: targetVersion } = node\n if (!targetVersion && Array.isArray(node.errors) && node.errors.length) {\n debugFn(\n 'notice',\n `miss: version for ${node.name} due to errors:\\n`,\n node.errors,\n )\n }\n if (\n node.name === name &&\n (typeof version !== 'string' || node.version === version)\n ) {\n matches.push(node)\n }\n for (const child of node.children.values()) {\n queue.push(child)\n }\n for (const edge of node.edgesOut.values()) {\n const { to } = edge\n if (to) {\n queue.push(to)\n }\n }\n }\n return matches\n}\n\nexport type GetAlertsMapFromArboristOptions = {\n apiToken?: string | undefined\n consolidate?: boolean | undefined\n filter?: AlertFilter | undefined\n nothrow?: boolean | undefined\n spinner?: Spinner | undefined\n}\n\nexport async function getAlertsMapFromArborist(\n arb: ArboristInstance,\n needInfoOn: PackageDetail[],\n options?: GetAlertsMapFromArboristOptions | undefined,\n): Promise<AlertsByPurl> {\n const opts = {\n __proto__: null,\n consolidate: false,\n nothrow: false,\n ...options,\n filter: toFilterConfig(getOwn(options, 'filter')),\n } as GetAlertsMapFromArboristOptions & { filter: AlertFilter }\n\n const purls = needInfoOn.map(d => idToNpmPurl(d.node.pkgid))\n\n let overrides: { [key: string]: string } | undefined\n const overridesMap = (\n arb.actualTree ??\n arb.idealTree ??\n (await arb.loadActual())\n )?.overrides?.children\n if (overridesMap) {\n overrides = Object.fromEntries(\n Array.from(overridesMap.entries()).map(([key, overrideSet]) => {\n return [key, overrideSet.value!]\n }),\n )\n }\n\n return await getAlertsMapFromPurls(purls, {\n overrides,\n ...opts,\n })\n}\n\nexport type DiffQueryFilter = {\n existing?: boolean | undefined\n unknownOrigin?: boolean | undefined\n}\n\nexport type DiffQueryOptions = {\n filter?: DiffQueryFilter | undefined\n}\n\nexport type PackageDetail = {\n node: NodeClass\n existing?: NodeClass | undefined\n}\n\nexport function getDetailsFromDiff(\n diff: Diff | null,\n options?: DiffQueryOptions | undefined,\n): PackageDetail[] {\n const details: PackageDetail[] = []\n // `diff` is `null` when `npm install --package-lock-only` is passed.\n if (!diff) {\n debugFn('notice', `miss: diff is ${diff}`)\n return details\n }\n\n const { NPM_REGISTRY_URL } = constants\n\n const filterConfig = toFilterConfig({\n existing: false,\n unknownOrigin: true,\n ...getOwn(options, 'filter'),\n }) as DiffQueryFilter\n\n const queue: Diff[] = [...diff.children]\n let pos = 0\n let { length: queueLength } = queue\n while (pos < queueLength) {\n if (pos === constants.LOOP_SENTINEL) {\n throw new Error('Detected infinite loop while walking Arborist diff')\n }\n const currDiff = queue[pos++]!\n const { action } = currDiff\n if (action) {\n // The `pkgNode`, i.e. the `ideal` node, will be `undefined` if the diff\n // action is 'REMOVE'\n // The `oldNode`, i.e. the `actual` node, will be `undefined` if the diff\n // action is 'ADD'.\n const { actual: oldNode, ideal: pkgNode } = currDiff\n let existing: NodeClass | undefined\n let keep = false\n if (action === DiffAction.change) {\n if (pkgNode?.package.version !== oldNode?.package.version) {\n keep = true\n if (\n oldNode?.package.name &&\n oldNode.package.name === pkgNode?.package.name\n ) {\n existing = oldNode\n }\n }\n } else {\n keep = action !== DiffAction.remove\n }\n if (keep && pkgNode?.resolved && (!oldNode || oldNode.resolved)) {\n if (\n filterConfig.unknownOrigin ||\n getUrlOrigin(pkgNode.resolved) === NPM_REGISTRY_URL\n ) {\n details.push({\n node: pkgNode,\n existing,\n })\n }\n }\n }\n for (const child of currDiff.children) {\n queue[queueLength++] = child\n }\n }\n if (filterConfig.existing) {\n const { unchanged } = diff\n for (let i = 0, { length } = unchanged; i < length; i += 1) {\n const pkgNode = unchanged[i]!\n if (\n filterConfig.unknownOrigin ||\n getUrlOrigin(pkgNode.resolved!) === NPM_REGISTRY_URL\n ) {\n details.push({\n node: pkgNode,\n existing: pkgNode,\n })\n }\n }\n }\n return details\n}\n\nexport function getTargetNode(nodeOrLink: NodeClass | LinkClass): NodeClass\nexport function getTargetNode<T>(nodeOrLink: T): NodeClass | null\nexport function getTargetNode(nodeOrLink: any): NodeClass | null {\n return nodeOrLink?.isLink ? nodeOrLink.target : (nodeOrLink ?? null)\n}\n\nexport function isTopLevel(tree: NodeClass, node: NodeClass): boolean {\n return getTargetNode(tree.children.get(node.name)) === node\n}\n\nexport type Packument = Exclude<\n Awaited<ReturnType<typeof fetchPackagePackument>>,\n null\n>\n\nexport function updateNode(\n node: NodeClass,\n newVersion: string,\n newVersionPackument: Packument['versions'][number],\n): void {\n // Object.defineProperty is needed to set the version property and replace\n // the old value with newVersion.\n Object.defineProperty(node, 'version', {\n configurable: true,\n enumerable: true,\n get: () => newVersion,\n })\n // Update package.version associated with the node.\n node.package.version = newVersion\n // Update node.resolved.\n const purlObj = PackageURL.fromString(idToNpmPurl(node.name))\n node.resolved = `${constants.NPM_REGISTRY_URL}/${node.name}/-/${purlObj.name}-${newVersion}.tgz`\n // Update node.integrity with the targetPackument.dist.integrity value if available\n // else delete node.integrity so a new value is resolved for the target version.\n const { integrity } = newVersionPackument.dist\n if (integrity) {\n node.integrity = integrity\n } else {\n delete node.integrity\n }\n // Update node.package.deprecated based on targetPackument.deprecated.\n if (hasOwn(newVersionPackument, 'deprecated')) {\n node.package['deprecated'] = newVersionPackument.deprecated as string\n } else {\n delete node.package['deprecated']\n }\n // Update node.package.dependencies.\n const newDeps = { ...newVersionPackument.dependencies }\n const { dependencies: oldDeps } = node.package\n node.package.dependencies = newDeps\n if (oldDeps) {\n for (const oldDepName of Object.keys(oldDeps)) {\n if (!hasOwn(newDeps, oldDepName)) {\n // Detach old edges for dependencies that don't exist on the updated\n // node.package.dependencies.\n node.edgesOut.get(oldDepName)?.detach()\n }\n }\n }\n for (const newDepName of Object.keys(newDeps)) {\n if (!hasOwn(oldDeps, newDepName)) {\n // Add new edges for dependencies that don't exist on the old\n // node.package.dependencies.\n node.addEdgeOut(\n new Edge({\n from: node,\n name: newDepName,\n spec: newDeps[newDepName],\n type: 'prod',\n }) as unknown as EdgeClass,\n )\n }\n }\n}\n\nexport function updatePackageJsonFromNode(\n editablePkgJson: EditablePackageJson,\n tree: NodeClass,\n node: NodeClass,\n newVersion: string,\n rangeStyle?: RangeStyle | undefined,\n): boolean {\n let result = false\n if (!isTopLevel(tree, node)) {\n return result\n }\n const { name } = node\n for (const depField of [\n 'dependencies',\n 'optionalDependencies',\n 'peerDependencies',\n ]) {\n const depObject = editablePkgJson.content[depField] as\n | { [key: string]: string }\n | undefined\n const depValue = hasOwn(depObject, name) ? depObject[name] : undefined\n if (typeof depValue !== 'string' || depValue.startsWith('catalog:')) {\n continue\n }\n let oldRange = depValue\n // Use npa if depValue looks like more than just a semver range.\n if (depValue.includes(':')) {\n const npaResult = npa(depValue)\n if (!npaResult || (npaResult as AliasResult).subSpec) {\n continue\n }\n oldRange = npaResult.rawSpec\n }\n const oldMin = getMinVersion(oldRange)\n const newRange =\n oldMin &&\n // Ensure we're on the same major version...\n getMajor(newVersion) === oldMin.major &&\n // and not a downgrade.\n semver.gte(newVersion, oldMin.version)\n ? applyRange(oldRange, newVersion, rangeStyle)\n : oldRange\n if (oldRange !== newRange) {\n result = true\n editablePkgJson.update({\n [depField]: {\n ...depObject,\n [name]: newRange,\n },\n })\n }\n }\n return result\n}\n","// @ts-ignore\nimport UntypedArborist from '@npmcli/arborist/lib/arborist/index.js'\n\nimport { debugDir } from '@socketsecurity/registry/lib/debug'\nimport { logger } from '@socketsecurity/registry/lib/logger'\n\nimport constants from '../../../../../constants.mts'\nimport { findUp } from '../../../../../utils/fs.mts'\nimport { logAlertsMap } from '../../../../../utils/socket-package-alert.mts'\nimport {\n getAlertsMapFromArborist,\n getDetailsFromDiff,\n} from '../../../arborist-helpers.mts'\n\nimport type {\n ArboristClass,\n ArboristReifyOptions,\n NodeClass,\n} from '../../types.mts'\n\nconst {\n kInternalsSymbol,\n [kInternalsSymbol as unknown as 'Symbol(kInternalsSymbol)']: { getIpc },\n} = constants\n\nexport const SAFE_NO_SAVE_ARBORIST_REIFY_OPTIONS_OVERRIDES = {\n __proto__: null,\n audit: false,\n dryRun: true,\n fund: false,\n ignoreScripts: true,\n progress: false,\n save: false,\n saveBundle: false,\n silent: true,\n}\n\nexport const SAFE_WITH_SAVE_ARBORIST_REIFY_OPTIONS_OVERRIDES = {\n // @ts-ignore\n __proto__: null,\n ...SAFE_NO_SAVE_ARBORIST_REIFY_OPTIONS_OVERRIDES,\n dryRun: false,\n save: true,\n}\n\nexport const kCtorArgs = Symbol('ctorArgs')\n\nexport const kRiskyReify = Symbol('riskyReify')\n\nexport const Arborist: ArboristClass = UntypedArborist\n\n// Implementation code not related to our custom behavior is based on\n// https://github.com/npm/cli/blob/v11.0.0/workspaces/arborist/lib/arborist/index.js:\nexport class SafeArborist extends Arborist {\n constructor(...ctorArgs: ConstructorParameters<ArboristClass>) {\n super(\n {\n path:\n (ctorArgs.length ? ctorArgs[0]?.path : undefined) ?? process.cwd(),\n ...(ctorArgs.length ? ctorArgs[0] : undefined),\n ...SAFE_NO_SAVE_ARBORIST_REIFY_OPTIONS_OVERRIDES,\n },\n ...ctorArgs.slice(1),\n )\n ;(this as any)[kCtorArgs] = ctorArgs\n }\n\n async [kRiskyReify](\n ...args: Parameters<InstanceType<ArboristClass>['reify']>\n ): Promise<NodeClass> {\n const ctorArgs = (this as any)[kCtorArgs]\n const arb = new Arborist(\n {\n ...(ctorArgs.length ? ctorArgs[0] : undefined),\n progress: false,\n },\n ...ctorArgs.slice(1),\n )\n const ret = await (arb.reify as (...args: any[]) => Promise<NodeClass>)(\n {\n ...(args.length ? args[0] : undefined),\n progress: false,\n },\n ...args.slice(1),\n )\n Object.assign(this, arb)\n return ret\n }\n\n // @ts-ignore Incorrectly typed.\n override async reify(\n this: SafeArborist,\n ...args: Parameters<InstanceType<ArboristClass>['reify']>\n ): Promise<NodeClass> {\n const options = {\n __proto__: null,\n ...(args.length ? args[0] : undefined),\n } as ArboristReifyOptions\n\n const ipc = await getIpc()\n debugDir('inspect', { ipc })\n\n const binName = ipc[constants.SOCKET_CLI_SHADOW_BIN]\n if (!binName) {\n return await this[kRiskyReify](...args)\n }\n\n await super.reify(\n {\n ...options,\n ...SAFE_NO_SAVE_ARBORIST_REIFY_OPTIONS_OVERRIDES,\n progress: false,\n },\n // @ts-ignore: TypeScript gets grumpy about rest parameters.\n ...args.slice(1),\n )\n\n const shadowAcceptRisks = !!ipc[constants.SOCKET_CLI_SHADOW_ACCEPT_RISKS]\n const shadowProgress = !!ipc[constants.SOCKET_CLI_SHADOW_PROGRESS]\n const shadowSilent = !!ipc[constants.SOCKET_CLI_SHADOW_SILENT]\n\n const acceptRisks =\n shadowAcceptRisks || constants.ENV.SOCKET_CLI_ACCEPT_RISKS\n const reportOnlyBlocking = acceptRisks || options.dryRun || options['yes']\n const silent = !!options['silent']\n const spinner = silent || !shadowProgress ? undefined : constants.spinner\n\n const isShadowNpx = binName === 'npx'\n const hasExisting = await findUp('node_modules', {\n cwd: process.cwd(),\n onlyDirectories: true,\n })\n const shouldCheckExisting = reportOnlyBlocking ? true : isShadowNpx\n\n const needInfoOn = getDetailsFromDiff(this.diff, {\n filter: {\n existing: shouldCheckExisting,\n },\n })\n\n const alertsMap = await getAlertsMapFromArborist(this, needInfoOn, {\n apiToken: ipc[constants.SOCKET_CLI_SHADOW_API_TOKEN],\n spinner,\n filter: reportOnlyBlocking\n ? {\n actions: ['error'],\n blocked: true,\n existing: shouldCheckExisting,\n }\n : {\n actions: ['error', 'monitor', 'warn'],\n existing: shouldCheckExisting,\n },\n })\n\n if (alertsMap.size) {\n process.exitCode = 1\n const viewAllRisks = constants.ENV.SOCKET_CLI_VIEW_ALL_RISKS\n logAlertsMap(alertsMap, {\n hideAt: viewAllRisks ? 'none' : 'middle',\n output: process.stderr,\n })\n throw new Error(\n `\n Socket ${binName} exiting due to risks.${\n viewAllRisks\n ? ''\n : `\\nView all risks - Rerun with environment variable ${constants.SOCKET_CLI_VIEW_ALL_RISKS}=1.`\n }${\n acceptRisks\n ? ''\n : `\\nAccept risks - Rerun with environment variable ${constants.SOCKET_CLI_ACCEPT_RISKS}=1.`\n }\n `.trim(),\n )\n } else if (!silent && !shadowSilent) {\n logger.success(\n `Socket ${binName} ${acceptRisks ? 'accepted' : 'found no'}${hasExisting ? ' new' : ''} risks`,\n )\n if (isShadowNpx) {\n logger.log(`Running ${options.add![0]}`)\n }\n }\n\n return await this[kRiskyReify](...args)\n }\n}\n","import { createRequire } from 'node:module'\n\n// @ts-ignore\nimport UntypedEdge from '@npmcli/arborist/lib/edge.js'\n// @ts-ignore\nimport UntypedNode from '@npmcli/arborist/lib/node.js'\n// @ts-ignore\nimport UntypedOverrideSet from '@npmcli/arborist/lib/override-set.js'\n\nimport {\n getArboristClassPath,\n getArboristEdgeClassPath,\n getArboristNodeClassPath,\n getArboristOverrideSetClassPath,\n} from '../paths.mts'\nimport { Arborist, SafeArborist } from './lib/arborist/index.mts'\n\nimport type { EdgeClass, NodeClass, OverrideSetClass } from './types.mts'\n\nconst require = createRequire(import.meta.url)\n\nexport { Arborist, SafeArborist }\n\nexport const Edge: EdgeClass = UntypedEdge\n\nexport const Node: NodeClass = UntypedNode\n\nexport const OverrideSet: OverrideSetClass = UntypedOverrideSet\n\nexport function installSafeArborist() {\n // Override '@npmcli/arborist' module exports with patched variants based on\n // https://github.com/npm/cli/pull/8089.\n const cache: { [key: string]: any } = require.cache\n cache[getArboristClassPath()] = { exports: SafeArborist }\n cache[getArboristEdgeClassPath()] = { exports: Edge }\n cache[getArboristNodeClassPath()] = { exports: Node }\n cache[getArboristOverrideSetClassPath()] = { exports: OverrideSet }\n}\n","import { installSafeArborist } from './arborist/index.mts'\n\ninstallSafeArborist()\n"],"names":["_arboristPkgPath","add","change","remove","__proto__","consolidate","nothrow","debugFn","NPM_REGISTRY_URL","existing","unknownOrigin","length","action","actual","ideal","keep","node","queue","unchanged","getIpc","audit","dryRun","fund","ignoreScripts","progress","save","saveBundle","silent","path","Object","ipc","cwd","onlyDirectories","filter","apiToken","blocked","actions","hideAt","logger","cache","exports","installSafeArborist"],"mappings":";;;;;;;;;;;;;AAOA;AACO;;;AAGH;AAGA;AAIAA;AAGF;AACA;AACF;AAEA;AACO;;;AAML;AACA;AACF;AAEA;AACO;;;AAGL;AACA;AACF;AAEA;AACO;;;AAGL;AACA;AACF;AAEA;AACO;;;AAML;AACA;AACF;;ACAO;AACLC;AACAC;AACAC;AACF;;AChCA;;AAEI;AACA;AACA;;;AAGF;AACF;AA2IO;AAKL;AACEC;AACAC;AACAC;AACA;;;AAIF;AAEA;;AAMA;;AAGM;AACF;AAEJ;AAEA;;;AAGA;AACF;AAgBO;;AAKL;;AAEEC;AACA;AACF;;AAEQC;AAAiB;;AAGvBC;AACAC;AACA;AACF;AAEA;;;AAEMC;AAAoB;;AAExB;AACE;AACF;AACA;;AACQC;AAAO;AACf;AACE;AACA;AACA;AACA;;AACQC;AAAiBC;AAAe;AACxC;;AAEA;;AAEIC;AACA;AAIEN;AACF;AACF;AACF;AACEM;AACF;AACA;AACE;;AAKIC;AACAP;AACF;AACF;AACF;AACF;AACA;AACEQ;AACF;AACF;;;AAEUC;AAAU;AAClB;AAAkBP;;AAChB;AACA;;AAKIK;AACAP;AACF;AACF;AACF;AACF;AACA;AACF;;ACtTA;AAoBA;;AAEE;AAA+DU;AAAO;AACxE;AAEO;AACLf;AACAgB;AACAC;AACAC;AACAC;AACAC;AACAC;AACAC;AACAC;AACF;AAUO;AAEA;AAEA;;AAEP;AACA;AACO;;AAEH;AAEIC;;;;AAOF;AACJ;AAEA;AAGE;AACA;;AAGIJ;;AAIJ;;AAGIA;;AAIJK;AACA;AACF;;AAEA;AACA;AAIE;AACEzB;;;AAIF;;AACsB0B;AAAI;AAE1B;;;AAGA;;AAII;AACA;AACAN;;AAEF;AACA;;;;;;AAUF;;AAGA;AACA;AACEO;AACAC;AACF;AACA;AAEA;AACEC;AACExB;AACF;AACF;;AAGEyB;;;;AAKMC;AACA1B;AACF;AAEE2B;AACA3B;AACF;AACN;;;AAIE;;AAEE4B;;AAEF;;AAGN;AAQA;AAGI;AACEC;AAGA;;AAEA;AACF;;AAGF;AACF;;ACvKA;AAIO;AAEA;AAEA;AAEA;AACL;AACA;AACA;AACAC;AAAkCC;;AAClCD;AAAsCC;;AACtCD;AAAsCC;;AACtCD;AAA6CC;;AAC/C;;ACnCAC","debugId":"f70f8c63-2b3f-4731-b7f5-7e6cf01f055"}
|
|
@@ -87,7 +87,7 @@ FLAGS=(
|
|
|
87
87
|
[dependencies]="--json --limit --markdown --offset"
|
|
88
88
|
[diff-scan]=""
|
|
89
89
|
[diff-scan get]="--after --before --depth --file --json"
|
|
90
|
-
[fix]="--auto-merge --
|
|
90
|
+
[fix]="--auto-merge --id --limit --range-style"
|
|
91
91
|
[install]=""
|
|
92
92
|
[install completion]=""
|
|
93
93
|
[login]="--api-base-url --api-proxy"
|