@socketsecurity/cli-with-sentry 0.14.57 → 0.14.59
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/bin/cli.js +2 -0
- package/dist/constants.d.ts +2 -2
- package/dist/constants.js +11 -6
- package/dist/constants.js.map +1 -1
- package/dist/instrument-with-sentry.js +2 -2
- package/dist/instrument-with-sentry.js.map +1 -1
- package/dist/module-sync/artifact.d.ts +75 -0
- package/dist/module-sync/cli.js +1063 -802
- package/dist/module-sync/cli.js.map +1 -1
- package/dist/module-sync/index.d.ts +4 -3
- package/dist/module-sync/shadow-bin.js +3 -1
- package/dist/module-sync/shadow-bin.js.map +1 -1
- package/dist/module-sync/shadow-npm-inject.js +1414 -1287
- package/dist/module-sync/shadow-npm-inject.js.map +1 -1
- package/dist/module-sync/shadow-npm-paths.js.map +1 -1
- package/dist/module-sync/socket-package-alert.d.ts +46 -0
- package/dist/module-sync/types.d.ts +11 -3
- package/dist/require/cli.js +1063 -802
- package/dist/require/cli.js.map +1 -1
- package/package.json +12 -10
- package/dist/module-sync/color-or-markdown.d.ts +0 -16
- package/dist/module-sync/socket-url.d.ts +0 -3
package/dist/module-sync/cli.js
CHANGED
|
@@ -28,6 +28,7 @@ var shadowNpmInject = require('./shadow-npm-inject.js');
|
|
|
28
28
|
var constants = require('./constants.js');
|
|
29
29
|
var meow = _socketInterop(require('meow'));
|
|
30
30
|
var objects = require('@socketsecurity/registry/lib/objects');
|
|
31
|
+
var path$1 = require('@socketsecurity/registry/lib/path');
|
|
31
32
|
var regexps = require('@socketsecurity/registry/lib/regexps');
|
|
32
33
|
var commonTags = _socketInterop(require('common-tags'));
|
|
33
34
|
var fs$1 = require('node:fs/promises');
|
|
@@ -42,27 +43,30 @@ var util = require('node:util');
|
|
|
42
43
|
var registry = require('@socketsecurity/registry');
|
|
43
44
|
var npm = require('@socketsecurity/registry/lib/npm');
|
|
44
45
|
var packages = require('@socketsecurity/registry/lib/packages');
|
|
45
|
-
var
|
|
46
|
-
var
|
|
47
|
-
var
|
|
46
|
+
var lockfileFile = _socketInterop(require('@pnpm/lockfile-file'));
|
|
47
|
+
var lockfile_detectDepTypes = _socketInterop(require('@pnpm/lockfile.detect-dep-types'));
|
|
48
|
+
var debug = require('@socketsecurity/registry/lib/debug');
|
|
48
49
|
var spawn = require('@socketsecurity/registry/lib/spawn');
|
|
49
|
-
var
|
|
50
|
-
var semver = _socketInterop(require('semver'));
|
|
51
|
-
var tinyglobby = _socketInterop(require('tinyglobby'));
|
|
52
|
-
var promises = require('@socketsecurity/registry/lib/promises');
|
|
50
|
+
var shadowNpmPaths = require('./shadow-npm-paths.js');
|
|
53
51
|
var browserslist = _socketInterop(require('browserslist'));
|
|
52
|
+
var semver = _socketInterop(require('semver'));
|
|
54
53
|
var which = _socketInterop(require('which'));
|
|
55
54
|
var index_cjs = require('@socketregistry/hyrious__bun.lockb/index.cjs');
|
|
56
55
|
var sorts = require('@socketsecurity/registry/lib/sorts');
|
|
57
56
|
var strings = require('@socketsecurity/registry/lib/strings');
|
|
57
|
+
var registryConstants = require('@socketsecurity/registry/lib/constants');
|
|
58
|
+
var isInteractive = require('@socketregistry/is-interactive/index.cjs');
|
|
59
|
+
var terminalLink = _socketInterop(require('terminal-link'));
|
|
60
|
+
var npa = _socketInterop(require('npm-package-arg'));
|
|
61
|
+
var tinyglobby = _socketInterop(require('tinyglobby'));
|
|
62
|
+
var promises = require('@socketsecurity/registry/lib/promises');
|
|
58
63
|
var yaml = _socketInterop(require('yaml'));
|
|
59
|
-
var debug = require('@socketsecurity/registry/lib/debug');
|
|
60
|
-
var shadowNpmPaths = require('./shadow-npm-paths.js');
|
|
61
64
|
var betterAjvErrors = _socketInterop(require('@apideck/better-ajv-errors'));
|
|
62
65
|
var config$A = require('@socketsecurity/config');
|
|
63
66
|
var assert = require('node:assert');
|
|
64
67
|
var readline = require('node:readline/promises');
|
|
65
68
|
var open = _socketInterop(require('open'));
|
|
69
|
+
var BoxWidget = _socketInterop(require('blessed/lib/widgets/box'));
|
|
66
70
|
var TableWidget = _socketInterop(require('blessed-contrib/lib/widget/table'));
|
|
67
71
|
var readline$1 = require('node:readline');
|
|
68
72
|
|
|
@@ -324,7 +328,7 @@ class Core {
|
|
|
324
328
|
}) {
|
|
325
329
|
const introducedBy = [];
|
|
326
330
|
if (pkg.direct) {
|
|
327
|
-
|
|
331
|
+
const manifests = pkg.manifestFiles.map(({
|
|
328
332
|
file
|
|
329
333
|
}) => file).join(';');
|
|
330
334
|
introducedBy.push(['direct', manifests]);
|
|
@@ -335,7 +339,7 @@ class Core {
|
|
|
335
339
|
continue;
|
|
336
340
|
}
|
|
337
341
|
const topPurl = `${topPackage.type}/${topPackage.name}@${topPackage.version}`;
|
|
338
|
-
|
|
342
|
+
const manifests = topPackage.manifestFiles.map(({
|
|
339
343
|
file
|
|
340
344
|
}) => file).join(';');
|
|
341
345
|
introducedBy.push([topPurl, manifests]);
|
|
@@ -767,7 +771,7 @@ function processSecurityComment({
|
|
|
767
771
|
const result = [];
|
|
768
772
|
let start = false;
|
|
769
773
|
let ignoreAll = false;
|
|
770
|
-
|
|
774
|
+
const ignoredPackages = [];
|
|
771
775
|
for (const ignoreComment of ignoreComments) {
|
|
772
776
|
const parsed = parseIgnoreCommand(ignoreComment.body?.split('\n').at(0) ?? '');
|
|
773
777
|
if (parsed.ignoreAll) {
|
|
@@ -791,7 +795,7 @@ function processSecurityComment({
|
|
|
791
795
|
const [_, _title, packageLink, _introducedBy, _manifest, _ci] = line.split('|');
|
|
792
796
|
|
|
793
797
|
// Parsing package link [npm/pkg](url)
|
|
794
|
-
|
|
798
|
+
const [_ecosystem, pkg] = packageLink.slice(1, packageLink.indexOf(']')).split('/', 2);
|
|
795
799
|
const [pkgName, pkgVersion] = pkg.split('@');
|
|
796
800
|
|
|
797
801
|
// Checking if this package should be ignored
|
|
@@ -1114,8 +1118,8 @@ function createSources(alert) {
|
|
|
1114
1118
|
manifests.push(addStr);
|
|
1115
1119
|
}
|
|
1116
1120
|
}
|
|
1117
|
-
|
|
1118
|
-
|
|
1121
|
+
const manifestList = manifests.join('');
|
|
1122
|
+
const sourceList = sources.join('');
|
|
1119
1123
|
const manifestStr = `<ul>${manifestList}</ul>`;
|
|
1120
1124
|
const sourcesStr = `<ul>${sourceList}</ul>`;
|
|
1121
1125
|
return [manifestStr, sourcesStr];
|
|
@@ -1260,8 +1264,8 @@ async function runAction(githubEventBefore, githubEventAfter) {
|
|
|
1260
1264
|
const securityComment = securityCommentTemplate(diff);
|
|
1261
1265
|
let newSecurityComment = true;
|
|
1262
1266
|
let newOverviewComment = true;
|
|
1263
|
-
|
|
1264
|
-
|
|
1267
|
+
const updateOldSecurityComment = comments.security !== undefined;
|
|
1268
|
+
const updateOldOverviewComment = comments.overview !== undefined;
|
|
1265
1269
|
if (diff.newAlerts.length === 0) {
|
|
1266
1270
|
if (!updateOldSecurityComment) {
|
|
1267
1271
|
newSecurityComment = false;
|
|
@@ -1403,8 +1407,7 @@ const validationFlags = {
|
|
|
1403
1407
|
|
|
1404
1408
|
const {
|
|
1405
1409
|
DRY_RUN_LABEL: DRY_RUN_LABEL$1,
|
|
1406
|
-
REDACTED
|
|
1407
|
-
SOCKET_CLI_SHOW_BANNER
|
|
1410
|
+
REDACTED
|
|
1408
1411
|
} = constants;
|
|
1409
1412
|
async function meowWithSubcommands(subcommands, options) {
|
|
1410
1413
|
const {
|
|
@@ -1438,11 +1441,7 @@ async function meowWithSubcommands(subcommands, options) {
|
|
|
1438
1441
|
};
|
|
1439
1442
|
// ...else we provide basic instructions and help.
|
|
1440
1443
|
|
|
1441
|
-
|
|
1442
|
-
// Lazily access constants.ENV[SOCKET_CLI_SHOW_BANNER].
|
|
1443
|
-
if (constants.ENV[SOCKET_CLI_SHOW_BANNER]) {
|
|
1444
|
-
logger.logger.log(getAsciiHeader(name));
|
|
1445
|
-
}
|
|
1444
|
+
emitBanner(name);
|
|
1446
1445
|
const cli = meow(`
|
|
1447
1446
|
Usage
|
|
1448
1447
|
$ ${name} <command>
|
|
@@ -1496,11 +1495,7 @@ function meowOrExit({
|
|
|
1496
1495
|
parentName
|
|
1497
1496
|
}) {
|
|
1498
1497
|
const command = `${parentName} ${config.commandName}`;
|
|
1499
|
-
|
|
1500
|
-
// Lazily access constants.ENV[SOCKET_CLI_SHOW_BANNER].
|
|
1501
|
-
if (constants.ENV[SOCKET_CLI_SHOW_BANNER]) {
|
|
1502
|
-
logger.logger.log(getAsciiHeader(command));
|
|
1503
|
-
}
|
|
1498
|
+
emitBanner(command);
|
|
1504
1499
|
|
|
1505
1500
|
// This exits if .printHelp() is called either by meow itself or by us.
|
|
1506
1501
|
const cli = meow({
|
|
@@ -1517,13 +1512,24 @@ function meowOrExit({
|
|
|
1517
1512
|
}
|
|
1518
1513
|
return cli;
|
|
1519
1514
|
}
|
|
1515
|
+
function emitBanner(name) {
|
|
1516
|
+
// Print a banner at the top of each command.
|
|
1517
|
+
// This helps with brand recognition and marketing.
|
|
1518
|
+
// It also helps with debugging since it contains version and command details.
|
|
1519
|
+
// Note: print over stderr to preserve stdout for flags like --json and
|
|
1520
|
+
// --markdown. If we don't do this, you can't use --json in particular
|
|
1521
|
+
// and pipe the result to other tools. By emiting the banner over stderr
|
|
1522
|
+
// you can do something like `socket scan view xyz | jq | process`.
|
|
1523
|
+
// The spinner also emits over stderr for example.
|
|
1524
|
+
logger.logger.error(getAsciiHeader(name));
|
|
1525
|
+
}
|
|
1520
1526
|
function getAsciiHeader(command) {
|
|
1521
1527
|
const cliVersion = // The '@rollup/plugin-replace' will replace "process.env['SOCKET_CLI_VERSION_HASH']".
|
|
1522
|
-
"0.14.
|
|
1528
|
+
"0.14.59:e40b009:5200cfd8:pub";
|
|
1523
1529
|
const nodeVersion = process.version;
|
|
1524
1530
|
const apiToken = shadowNpmInject.getSetting('apiToken');
|
|
1525
1531
|
const shownToken = apiToken ? getLastFiveOfApiToken(apiToken) : 'no';
|
|
1526
|
-
const relCwd = process.cwd().replace(new RegExp(`^${regexps.escapeRegExp(constants.homePath)}`, 'i'), '~/');
|
|
1532
|
+
const relCwd = path$1.normalizePath(process.cwd().replace(new RegExp(`^${regexps.escapeRegExp(constants.homePath)}(?:${path.sep}|$)`, 'i'), '~/'));
|
|
1527
1533
|
const body = `
|
|
1528
1534
|
_____ _ _ /---------------
|
|
1529
1535
|
| __|___ ___| |_ ___| |_ | Socket.dev CLI ver ${cliVersion}
|
|
@@ -1722,7 +1728,7 @@ async function outputAnalyticsWithToken({
|
|
|
1722
1728
|
// A message should already have been printed if we have no data here
|
|
1723
1729
|
if (!data) return;
|
|
1724
1730
|
if (outputKind === 'json') {
|
|
1725
|
-
|
|
1731
|
+
const serialized = renderJson(data);
|
|
1726
1732
|
if (!serialized) return;
|
|
1727
1733
|
if (filePath && filePath !== '-') {
|
|
1728
1734
|
try {
|
|
@@ -2194,6 +2200,9 @@ const config$x = {
|
|
|
2194
2200
|
Usage
|
|
2195
2201
|
$ ${command} <org slug>
|
|
2196
2202
|
|
|
2203
|
+
This feature requires an Enterprise Plan. To learn more about getting access
|
|
2204
|
+
to this feature and many more, please visit https://socket.dev/pricing
|
|
2205
|
+
|
|
2197
2206
|
Options
|
|
2198
2207
|
${getFlagListOutput(config.flags, 6)}
|
|
2199
2208
|
|
|
@@ -2249,22 +2258,22 @@ async function run$x(argv, importMeta, {
|
|
|
2249
2258
|
}
|
|
2250
2259
|
|
|
2251
2260
|
const {
|
|
2252
|
-
NPM: NPM$
|
|
2261
|
+
NPM: NPM$f,
|
|
2253
2262
|
NPX: NPX$3,
|
|
2254
|
-
PNPM: PNPM$
|
|
2263
|
+
PNPM: PNPM$a
|
|
2255
2264
|
} = constants;
|
|
2256
|
-
const nodejsPlatformTypes = new Set(['javascript', 'js', 'nodejs', NPM$
|
|
2265
|
+
const nodejsPlatformTypes = new Set(['javascript', 'js', 'nodejs', NPM$f, PNPM$a, 'ts', 'tsx', 'typescript']);
|
|
2257
2266
|
async function runCycloneDX(yargv) {
|
|
2258
2267
|
let cleanupPackageLock = false;
|
|
2259
2268
|
if (yargv.type !== 'yarn' && nodejsPlatformTypes.has(yargv.type) && fs.existsSync('./yarn.lock')) {
|
|
2260
2269
|
if (fs.existsSync('./package-lock.json')) {
|
|
2261
|
-
yargv.type = NPM$
|
|
2270
|
+
yargv.type = NPM$f;
|
|
2262
2271
|
} else {
|
|
2263
2272
|
// Use synp to create a package-lock.json from the yarn.lock,
|
|
2264
2273
|
// based on the node_modules folder, for a more accurate SBOM.
|
|
2265
2274
|
try {
|
|
2266
2275
|
await shadowBin(NPX$3, ['synp@1.9.14', '--', '--source-file', './yarn.lock'], 2);
|
|
2267
|
-
yargv.type = NPM$
|
|
2276
|
+
yargv.type = NPM$f;
|
|
2268
2277
|
cleanupPackageLock = true;
|
|
2269
2278
|
} catch {}
|
|
2270
2279
|
}
|
|
@@ -2784,99 +2793,105 @@ const cmdDiffScan = {
|
|
|
2784
2793
|
}
|
|
2785
2794
|
};
|
|
2786
2795
|
|
|
2787
|
-
// import { detect } from '../../utils/package-environment-detector'
|
|
2788
|
-
|
|
2789
2796
|
const {
|
|
2790
|
-
NPM: NPM$
|
|
2797
|
+
NPM: NPM$e
|
|
2791
2798
|
} = constants;
|
|
2792
2799
|
function isTopLevel(tree, node) {
|
|
2793
2800
|
return tree.children.get(node.name) === node;
|
|
2794
2801
|
}
|
|
2795
|
-
async function
|
|
2796
|
-
// Lazily access constants.spinner.
|
|
2802
|
+
async function npmFix(_pkgEnvDetails, cwd, options) {
|
|
2797
2803
|
const {
|
|
2798
2804
|
spinner
|
|
2799
|
-
} =
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
});
|
|
2805
|
-
// const agentDetails = await detect()
|
|
2806
|
-
|
|
2805
|
+
} = {
|
|
2806
|
+
__proto__: null,
|
|
2807
|
+
...options
|
|
2808
|
+
};
|
|
2809
|
+
spinner?.start();
|
|
2807
2810
|
const arb = new shadowNpmInject.SafeArborist({
|
|
2808
2811
|
path: cwd,
|
|
2809
2812
|
...shadowNpmInject.SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES
|
|
2810
2813
|
});
|
|
2811
2814
|
await arb.reify();
|
|
2812
|
-
const
|
|
2815
|
+
const alertsMap = await shadowNpmInject.getAlertsMapFromArborist(arb, {
|
|
2813
2816
|
consolidate: true,
|
|
2814
|
-
|
|
2815
|
-
|
|
2817
|
+
include: {
|
|
2818
|
+
existing: true,
|
|
2819
|
+
unfixable: false,
|
|
2820
|
+
upgrade: false
|
|
2821
|
+
}
|
|
2816
2822
|
});
|
|
2817
|
-
const infoByPkg = shadowNpmInject.
|
|
2823
|
+
const infoByPkg = shadowNpmInject.getCveInfoByAlertsMap(alertsMap);
|
|
2824
|
+
if (!infoByPkg) {
|
|
2825
|
+
spinner?.stop();
|
|
2826
|
+
return;
|
|
2827
|
+
}
|
|
2818
2828
|
await arb.buildIdealTree();
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
}
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2829
|
+
const editablePkgJson = await packages.readPackageJson(cwd, {
|
|
2830
|
+
editable: true
|
|
2831
|
+
});
|
|
2832
|
+
for (const {
|
|
2833
|
+
0: name,
|
|
2834
|
+
1: infos
|
|
2835
|
+
} of infoByPkg) {
|
|
2836
|
+
const revertToIdealTree = arb.idealTree;
|
|
2837
|
+
arb.idealTree = null;
|
|
2838
|
+
// eslint-disable-next-line no-await-in-loop
|
|
2839
|
+
await arb.buildIdealTree();
|
|
2840
|
+
const tree = arb.idealTree;
|
|
2841
|
+
const hasUpgrade = !!registry.getManifestData(NPM$e, name);
|
|
2842
|
+
if (hasUpgrade) {
|
|
2843
|
+
spinner?.info(`Skipping ${name}. Socket Optimize package exists.`);
|
|
2844
|
+
continue;
|
|
2845
|
+
}
|
|
2846
|
+
const nodes = shadowNpmInject.findPackageNodes(tree, name);
|
|
2847
|
+
const packument = nodes.length && infos.length ?
|
|
2848
|
+
// eslint-disable-next-line no-await-in-loop
|
|
2849
|
+
await packages.fetchPackagePackument(name) : null;
|
|
2850
|
+
if (!packument) {
|
|
2851
|
+
continue;
|
|
2852
|
+
}
|
|
2853
|
+
for (let i = 0, {
|
|
2854
|
+
length: nodesLength
|
|
2855
|
+
} = nodes; i < nodesLength; i += 1) {
|
|
2856
|
+
const node = nodes[i];
|
|
2857
|
+
for (let j = 0, {
|
|
2858
|
+
length: infosLength
|
|
2859
|
+
} = infos; j < infosLength; j += 1) {
|
|
2860
|
+
const {
|
|
2861
|
+
firstPatchedVersionIdentifier,
|
|
2862
|
+
vulnerableVersionRange
|
|
2863
|
+
} = infos[j];
|
|
2864
|
+
const {
|
|
2865
|
+
version: oldVersion
|
|
2866
|
+
} = node;
|
|
2867
|
+
if (shadowNpmInject.updateNode(node, packument, vulnerableVersionRange)) {
|
|
2868
|
+
try {
|
|
2869
|
+
// eslint-disable-next-line no-await-in-loop
|
|
2870
|
+
await npm.runScript('test', [], {
|
|
2871
|
+
spinner,
|
|
2872
|
+
stdio: 'ignore'
|
|
2873
|
+
});
|
|
2874
|
+
spinner?.info(`Patched ${name} ${oldVersion} -> ${node.version}`);
|
|
2875
|
+
if (isTopLevel(tree, node)) {
|
|
2876
|
+
for (const depField of ['dependencies', 'optionalDependencies', 'peerDependencies']) {
|
|
2877
|
+
const {
|
|
2878
|
+
content: pkgJson
|
|
2879
|
+
} = editablePkgJson;
|
|
2880
|
+
const oldVersion = pkgJson[depField]?.[name];
|
|
2881
|
+
if (oldVersion) {
|
|
2882
|
+
const decorator = /^[~^]/.exec(oldVersion)?.[0] ?? '';
|
|
2883
|
+
pkgJson[depField][name] = `${decorator}${node.version}`;
|
|
2869
2884
|
}
|
|
2870
|
-
// eslint-disable-next-line no-await-in-loop
|
|
2871
|
-
await editablePkgJson.save();
|
|
2872
|
-
} catch {
|
|
2873
|
-
spinner.error(`Reverting ${name} to ${oldVersion}`);
|
|
2874
|
-
arb.idealTree = revertToIdealTree;
|
|
2875
2885
|
}
|
|
2876
|
-
} else {
|
|
2877
|
-
spinner.error(`Could not patch ${name} ${oldVersion}`);
|
|
2878
2886
|
}
|
|
2887
|
+
// eslint-disable-next-line no-await-in-loop
|
|
2888
|
+
await editablePkgJson.save();
|
|
2889
|
+
} catch {
|
|
2890
|
+
spinner?.error(`Reverting ${name} to ${oldVersion}`);
|
|
2891
|
+
arb.idealTree = revertToIdealTree;
|
|
2879
2892
|
}
|
|
2893
|
+
} else {
|
|
2894
|
+
spinner?.error(`Could not patch ${name} ${oldVersion}`);
|
|
2880
2895
|
}
|
|
2881
2896
|
}
|
|
2882
2897
|
}
|
|
@@ -2886,161 +2901,687 @@ async function runFix() {
|
|
|
2886
2901
|
});
|
|
2887
2902
|
arb2.idealTree = arb.idealTree;
|
|
2888
2903
|
await arb2.reify();
|
|
2889
|
-
spinner
|
|
2904
|
+
spinner?.stop();
|
|
2890
2905
|
}
|
|
2891
2906
|
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
`
|
|
2909
|
-
|
|
2910
|
-
const
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
importMeta,
|
|
2922
|
-
parentName
|
|
2923
|
-
});
|
|
2924
|
-
if (cli.flags['dryRun']) {
|
|
2925
|
-
logger.logger.log(DRY_RUN_BAIL_TEXT$s);
|
|
2926
|
-
return;
|
|
2907
|
+
async function getAlertsMapFromPnpmLockfile(lockfile, options) {
|
|
2908
|
+
const {
|
|
2909
|
+
spinner
|
|
2910
|
+
} = {
|
|
2911
|
+
__proto__: null,
|
|
2912
|
+
...options
|
|
2913
|
+
};
|
|
2914
|
+
const depTypes = lockfile_detectDepTypes.detectDepTypes(lockfile);
|
|
2915
|
+
const pkgIds = Object.keys(depTypes);
|
|
2916
|
+
let {
|
|
2917
|
+
length: remaining
|
|
2918
|
+
} = pkgIds;
|
|
2919
|
+
const alertsByPkgId = new Map();
|
|
2920
|
+
if (!remaining) {
|
|
2921
|
+
return alertsByPkgId;
|
|
2922
|
+
}
|
|
2923
|
+
const getText = () => `Looking up data for ${remaining} packages`;
|
|
2924
|
+
spinner?.start(getText());
|
|
2925
|
+
const toAlertsMapOptions = {
|
|
2926
|
+
overrides: lockfile.overrides,
|
|
2927
|
+
...options
|
|
2928
|
+
};
|
|
2929
|
+
for await (const artifact of shadowNpmInject.batchScan(pkgIds)) {
|
|
2930
|
+
await shadowNpmInject.addArtifactToAlertsMap(artifact, alertsByPkgId, toAlertsMapOptions);
|
|
2931
|
+
remaining -= 1;
|
|
2932
|
+
if (spinner && remaining > 0) {
|
|
2933
|
+
spinner.start();
|
|
2934
|
+
spinner.setText(getText());
|
|
2935
|
+
}
|
|
2927
2936
|
}
|
|
2928
|
-
|
|
2937
|
+
spinner?.stop();
|
|
2938
|
+
return alertsByPkgId;
|
|
2929
2939
|
}
|
|
2930
2940
|
|
|
2931
|
-
function
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2941
|
+
function cmdFlagsToString(args) {
|
|
2942
|
+
const result = [];
|
|
2943
|
+
for (let i = 0, {
|
|
2944
|
+
length
|
|
2945
|
+
} = args; i < length; i += 1) {
|
|
2946
|
+
if (args[i].startsWith('--')) {
|
|
2947
|
+
// Check if the next item exists and is NOT another flag.
|
|
2948
|
+
if (i + 1 < length && !args[i + 1].startsWith('--')) {
|
|
2949
|
+
result.push(`${args[i]}=${args[i + 1]}`);
|
|
2950
|
+
i += 1;
|
|
2951
|
+
} else {
|
|
2952
|
+
result.push(args[i]);
|
|
2953
|
+
}
|
|
2935
2954
|
}
|
|
2936
2955
|
}
|
|
2937
|
-
return
|
|
2956
|
+
return result.join(' ');
|
|
2938
2957
|
}
|
|
2939
|
-
function
|
|
2940
|
-
const
|
|
2941
|
-
|
|
2942
|
-
result[key] = input[key];
|
|
2943
|
-
}
|
|
2944
|
-
return result;
|
|
2958
|
+
function cmdPrefixMessage(cmdName, text) {
|
|
2959
|
+
const cmdPrefix = cmdName ? `${cmdName}: ` : '';
|
|
2960
|
+
return `${cmdPrefix}${text}`;
|
|
2945
2961
|
}
|
|
2946
2962
|
|
|
2947
|
-
|
|
2948
|
-
|
|
2963
|
+
const {
|
|
2964
|
+
SOCKET_CLI_SENTRY_BUILD,
|
|
2965
|
+
SOCKET_IPC_HANDSHAKE
|
|
2966
|
+
} = constants;
|
|
2967
|
+
function safeNpmInstall(options) {
|
|
2949
2968
|
const {
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2969
|
+
agentExecPath = shadowNpmPaths.getNpmBinPath(),
|
|
2970
|
+
args = [],
|
|
2971
|
+
ipc,
|
|
2972
|
+
spinner,
|
|
2973
|
+
...spawnOptions
|
|
2974
|
+
} = {
|
|
2975
|
+
__proto__: null,
|
|
2976
|
+
...options
|
|
2977
|
+
};
|
|
2978
|
+
const useIpc = objects.isObject(ipc);
|
|
2979
|
+
const useDebug = debug.isDebug();
|
|
2980
|
+
const terminatorPos = args.indexOf('--');
|
|
2981
|
+
const npmArgs = (terminatorPos === -1 ? args : args.slice(0, terminatorPos)).filter(a => !npm.isAuditFlag(a) && !npm.isFundFlag(a) && !npm.isProgressFlag(a));
|
|
2982
|
+
const otherArgs = terminatorPos === -1 ? [] : args.slice(terminatorPos);
|
|
2983
|
+
const isSilent = !useDebug && !npmArgs.some(npm.isLoglevelFlag);
|
|
2984
|
+
const logLevelArgs = isSilent ? ['--loglevel', 'error'] : [];
|
|
2985
|
+
const spawnPromise = spawn.spawn(
|
|
2986
|
+
// Lazily access constants.execPath.
|
|
2987
|
+
constants.execPath, [
|
|
2988
|
+
// Lazily access constants.nodeHardenFlags.
|
|
2989
|
+
...constants.nodeHardenFlags,
|
|
2990
|
+
// Lazily access constants.nodeNoWarningsFlags.
|
|
2991
|
+
...constants.nodeNoWarningsFlags,
|
|
2992
|
+
// Lazily access constants.ENV[SOCKET_CLI_SENTRY_BUILD].
|
|
2993
|
+
...(constants.ENV[SOCKET_CLI_SENTRY_BUILD] ? ['--require',
|
|
2994
|
+
// Lazily access constants.distInstrumentWithSentryPath.
|
|
2995
|
+
constants.distInstrumentWithSentryPath] : []), '--require',
|
|
2996
|
+
// Lazily access constants.distShadowNpmInjectPath.
|
|
2997
|
+
constants.distShadowNpmInjectPath, agentExecPath, 'install',
|
|
2998
|
+
// Avoid code paths for 'audit' and 'fund'.
|
|
2999
|
+
'--no-audit', '--no-fund',
|
|
3000
|
+
// Add `--no-progress` flag to fix input being swallowed by the spinner
|
|
3001
|
+
// when running the command with recent versions of npm.
|
|
3002
|
+
'--no-progress',
|
|
3003
|
+
// Add '--loglevel=error' if a loglevel flag is not provided and the
|
|
3004
|
+
// SOCKET_CLI_DEBUG environment variable is not truthy.
|
|
3005
|
+
...logLevelArgs, ...npmArgs, ...otherArgs], {
|
|
3006
|
+
spinner,
|
|
3007
|
+
// Set stdio to include 'ipc'.
|
|
3008
|
+
// See https://github.com/nodejs/node/blob/v23.6.0/lib/child_process.js#L161-L166
|
|
3009
|
+
// and https://github.com/nodejs/node/blob/v23.6.0/lib/internal/child_process.js#L238.
|
|
3010
|
+
stdio: useIpc ? [0, 1, 2, 'ipc'] : 'inherit',
|
|
3011
|
+
...spawnOptions,
|
|
3012
|
+
env: {
|
|
3013
|
+
...process$1.env,
|
|
3014
|
+
...spawnOptions.env
|
|
3015
|
+
}
|
|
3016
|
+
});
|
|
3017
|
+
if (useIpc) {
|
|
3018
|
+
spawnPromise.process.send({
|
|
3019
|
+
[SOCKET_IPC_HANDSHAKE]: ipc
|
|
3020
|
+
});
|
|
2957
3021
|
}
|
|
2958
|
-
|
|
2959
|
-
return `${values.join(', ')}${separator}${finalValue}`;
|
|
3022
|
+
return spawnPromise;
|
|
2960
3023
|
}
|
|
2961
3024
|
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
3025
|
+
const {
|
|
3026
|
+
NPM: NPM$d
|
|
3027
|
+
} = constants;
|
|
3028
|
+
function runAgentInstall(pkgEnvDetails, options) {
|
|
3029
|
+
const {
|
|
3030
|
+
agent,
|
|
3031
|
+
agentExecPath
|
|
3032
|
+
} = pkgEnvDetails;
|
|
3033
|
+
// All package managers support the "install" command.
|
|
3034
|
+
if (agent === NPM$d) {
|
|
3035
|
+
return safeNpmInstall({
|
|
3036
|
+
agentExecPath,
|
|
3037
|
+
...options
|
|
3038
|
+
});
|
|
2971
3039
|
}
|
|
2972
|
-
|
|
3040
|
+
const {
|
|
3041
|
+
args = [],
|
|
3042
|
+
spinner,
|
|
3043
|
+
...spawnOptions
|
|
3044
|
+
} = {
|
|
3045
|
+
__proto__: null,
|
|
3046
|
+
...options
|
|
3047
|
+
};
|
|
3048
|
+
return spawn.spawn(agentExecPath, ['install', ...args], {
|
|
3049
|
+
spinner,
|
|
3050
|
+
stdio: debug.isDebug() ? 'inherit' : 'ignore',
|
|
3051
|
+
...spawnOptions,
|
|
3052
|
+
env: {
|
|
3053
|
+
...process.env,
|
|
3054
|
+
NODE_OPTIONS: cmdFlagsToString([
|
|
3055
|
+
// Lazily access constants.nodeHardenFlags.
|
|
3056
|
+
...constants.nodeHardenFlags,
|
|
3057
|
+
// Lazily access constants.nodeNoWarningsFlags.
|
|
3058
|
+
...constants.nodeNoWarningsFlags]),
|
|
3059
|
+
...spawnOptions.env
|
|
3060
|
+
}
|
|
3061
|
+
});
|
|
2973
3062
|
}
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
3063
|
+
|
|
3064
|
+
const {
|
|
3065
|
+
NPM: NPM$c,
|
|
3066
|
+
OVERRIDES: OVERRIDES$2,
|
|
3067
|
+
PNPM: PNPM$9
|
|
3068
|
+
} = constants;
|
|
3069
|
+
async function pnpmFix(pkgEnvDetails, cwd, options) {
|
|
3070
|
+
const {
|
|
3071
|
+
spinner
|
|
3072
|
+
} = {
|
|
3073
|
+
__proto__: null,
|
|
3074
|
+
...options
|
|
3075
|
+
};
|
|
3076
|
+
spinner?.start();
|
|
3077
|
+
const lockfile = await lockfileFile.readWantedLockfile(cwd, {
|
|
3078
|
+
ignoreIncompatible: false
|
|
3079
|
+
});
|
|
3080
|
+
if (!lockfile) {
|
|
3081
|
+
spinner?.stop();
|
|
3082
|
+
return;
|
|
3083
|
+
}
|
|
3084
|
+
const alertsMap = await getAlertsMapFromPnpmLockfile(lockfile, {
|
|
3085
|
+
consolidate: true,
|
|
3086
|
+
include: {
|
|
3087
|
+
existing: true,
|
|
3088
|
+
unfixable: false,
|
|
3089
|
+
upgrade: false
|
|
2979
3090
|
}
|
|
3091
|
+
});
|
|
3092
|
+
const infoByPkg = shadowNpmInject.getCveInfoByAlertsMap(alertsMap);
|
|
3093
|
+
if (!infoByPkg) {
|
|
3094
|
+
spinner?.stop();
|
|
3095
|
+
return;
|
|
2980
3096
|
}
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
3097
|
+
const arb = new shadowNpmInject.SafeArborist({
|
|
3098
|
+
path: cwd,
|
|
3099
|
+
...shadowNpmInject.SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES
|
|
3100
|
+
});
|
|
3101
|
+
await arb.loadActual();
|
|
3102
|
+
const editablePkgJson = await packages.readPackageJson(cwd, {
|
|
3103
|
+
editable: true
|
|
3104
|
+
});
|
|
3105
|
+
const {
|
|
3106
|
+
content: pkgJson
|
|
3107
|
+
} = editablePkgJson;
|
|
3108
|
+
for (const {
|
|
3109
|
+
0: name,
|
|
3110
|
+
1: infos
|
|
3111
|
+
} of infoByPkg) {
|
|
3112
|
+
const tree = arb.actualTree;
|
|
3113
|
+
const hasUpgrade = !!registry.getManifestData(NPM$c, name);
|
|
3114
|
+
if (hasUpgrade) {
|
|
3115
|
+
spinner?.info(`Skipping ${name}. Socket Optimize package exists.`);
|
|
2995
3116
|
continue;
|
|
2996
3117
|
}
|
|
2997
|
-
|
|
2998
|
-
|
|
3118
|
+
const nodes = shadowNpmInject.findPackageNodes(tree, name);
|
|
3119
|
+
const packument = nodes.length && infos.length ?
|
|
3120
|
+
// eslint-disable-next-line no-await-in-loop
|
|
3121
|
+
await packages.fetchPackagePackument(name) : null;
|
|
3122
|
+
if (!packument) {
|
|
3123
|
+
continue;
|
|
2999
3124
|
}
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
}
|
|
3125
|
+
for (let i = 0, {
|
|
3126
|
+
length: nodesLength
|
|
3127
|
+
} = nodes; i < nodesLength; i += 1) {
|
|
3128
|
+
const node = nodes[i];
|
|
3129
|
+
for (let j = 0, {
|
|
3130
|
+
length: infosLength
|
|
3131
|
+
} = infos; j < infosLength; j += 1) {
|
|
3132
|
+
const {
|
|
3133
|
+
firstPatchedVersionIdentifier,
|
|
3134
|
+
vulnerableVersionRange
|
|
3135
|
+
} = infos[j];
|
|
3136
|
+
const {
|
|
3137
|
+
version: oldVersion
|
|
3138
|
+
} = node;
|
|
3139
|
+
const availableVersions = Object.keys(packument.versions);
|
|
3140
|
+
// Find the highest non-vulnerable version within the same major range
|
|
3141
|
+
const targetVersion = shadowNpmInject.findBestPatchVersion(node, availableVersions, vulnerableVersionRange);
|
|
3142
|
+
const targetPackument = targetVersion ? packument.versions[targetVersion] : undefined;
|
|
3143
|
+
if (targetPackument) {
|
|
3144
|
+
const oldPnpm = pkgJson[PNPM$9];
|
|
3145
|
+
const oldOverrides = oldPnpm?.[OVERRIDES$2];
|
|
3146
|
+
try {
|
|
3147
|
+
editablePkgJson.update({
|
|
3148
|
+
[PNPM$9]: {
|
|
3149
|
+
...oldPnpm,
|
|
3150
|
+
[OVERRIDES$2]: {
|
|
3151
|
+
[`${node.name}@${vulnerableVersionRange}`]: `^${targetVersion}`,
|
|
3152
|
+
...oldOverrides
|
|
3153
|
+
}
|
|
3154
|
+
}
|
|
3155
|
+
});
|
|
3156
|
+
spinner?.info(`Patched ${name} ${oldVersion} -> ${node.version}`);
|
|
3003
3157
|
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3158
|
+
// eslint-disable-next-line no-await-in-loop
|
|
3159
|
+
await editablePkgJson.save();
|
|
3160
|
+
// eslint-disable-next-line no-await-in-loop
|
|
3161
|
+
await runAgentInstall(pkgEnvDetails, {
|
|
3162
|
+
spinner
|
|
3163
|
+
});
|
|
3164
|
+
} catch {
|
|
3165
|
+
spinner?.error(`Reverting ${name} to ${oldVersion}`);
|
|
3166
|
+
}
|
|
3167
|
+
} else {
|
|
3168
|
+
spinner?.error(`Could not patch ${name} ${oldVersion}`);
|
|
3169
|
+
}
|
|
3170
|
+
}
|
|
3171
|
+
}
|
|
3013
3172
|
}
|
|
3014
|
-
|
|
3015
|
-
return {
|
|
3016
|
-
data: result.data,
|
|
3017
|
-
severityCount,
|
|
3018
|
-
score: scoreResult.data
|
|
3019
|
-
};
|
|
3173
|
+
spinner?.stop();
|
|
3020
3174
|
}
|
|
3021
3175
|
|
|
3022
3176
|
const {
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3177
|
+
BINARY_LOCK_EXT,
|
|
3178
|
+
BUN: BUN$5,
|
|
3179
|
+
LOCK_EXT: LOCK_EXT$1,
|
|
3180
|
+
NPM: NPM$b,
|
|
3181
|
+
NPM_BUGGY_OVERRIDES_PATCHED_VERSION: NPM_BUGGY_OVERRIDES_PATCHED_VERSION$1,
|
|
3182
|
+
PNPM: PNPM$8,
|
|
3183
|
+
VLT: VLT$5,
|
|
3184
|
+
YARN,
|
|
3185
|
+
YARN_BERRY: YARN_BERRY$5,
|
|
3186
|
+
YARN_CLASSIC: YARN_CLASSIC$6
|
|
3187
|
+
} = constants;
|
|
3188
|
+
const AGENTS = [BUN$5, NPM$b, PNPM$8, YARN_BERRY$5, YARN_CLASSIC$6, VLT$5];
|
|
3189
|
+
const binByAgent = {
|
|
3190
|
+
__proto__: null,
|
|
3191
|
+
[BUN$5]: BUN$5,
|
|
3192
|
+
[NPM$b]: NPM$b,
|
|
3193
|
+
[PNPM$8]: PNPM$8,
|
|
3194
|
+
[YARN_BERRY$5]: YARN,
|
|
3195
|
+
[YARN_CLASSIC$6]: YARN,
|
|
3196
|
+
[VLT$5]: VLT$5
|
|
3197
|
+
};
|
|
3198
|
+
async function getAgentExecPath(agent) {
|
|
3199
|
+
const binName = binByAgent[agent];
|
|
3200
|
+
return (await which(binName, {
|
|
3201
|
+
nothrow: true
|
|
3202
|
+
})) ?? binName;
|
|
3203
|
+
}
|
|
3204
|
+
async function getAgentVersion(agentExecPath, cwd) {
|
|
3205
|
+
let result;
|
|
3206
|
+
try {
|
|
3207
|
+
result = semver.coerce(
|
|
3208
|
+
// All package managers support the "--version" flag.
|
|
3209
|
+
(await spawn.spawn(agentExecPath, ['--version'], {
|
|
3210
|
+
cwd
|
|
3211
|
+
})).stdout) ?? undefined;
|
|
3212
|
+
} catch {}
|
|
3213
|
+
return result;
|
|
3214
|
+
}
|
|
3215
|
+
|
|
3216
|
+
// The order of LOCKS properties IS significant as it affects iteration order.
|
|
3217
|
+
const LOCKS = {
|
|
3218
|
+
[`bun${LOCK_EXT$1}`]: BUN$5,
|
|
3219
|
+
[`bun${BINARY_LOCK_EXT}`]: BUN$5,
|
|
3220
|
+
// If both package-lock.json and npm-shrinkwrap.json are present in the root
|
|
3221
|
+
// of a project, npm-shrinkwrap.json will take precedence and package-lock.json
|
|
3222
|
+
// will be ignored.
|
|
3223
|
+
// https://docs.npmjs.com/cli/v10/configuring-npm/package-lock-json#package-lockjson-vs-npm-shrinkwrapjson
|
|
3224
|
+
'npm-shrinkwrap.json': NPM$b,
|
|
3225
|
+
'package-lock.json': NPM$b,
|
|
3226
|
+
'pnpm-lock.yaml': PNPM$8,
|
|
3227
|
+
'pnpm-lock.yml': PNPM$8,
|
|
3228
|
+
[`yarn${LOCK_EXT$1}`]: YARN_CLASSIC$6,
|
|
3229
|
+
'vlt-lock.json': VLT$5,
|
|
3230
|
+
// Lastly, look for a hidden lock file which is present if .npmrc has package-lock=false:
|
|
3231
|
+
// https://docs.npmjs.com/cli/v10/configuring-npm/package-lock-json#hidden-lockfiles
|
|
3232
|
+
//
|
|
3233
|
+
// Unlike the other LOCKS keys this key contains a directory AND filename so
|
|
3234
|
+
// it has to be handled differently.
|
|
3235
|
+
'node_modules/.package-lock.json': NPM$b
|
|
3236
|
+
};
|
|
3237
|
+
const readLockFileByAgent = (() => {
|
|
3238
|
+
function wrapReader(reader) {
|
|
3239
|
+
return async (...args) => {
|
|
3240
|
+
try {
|
|
3241
|
+
return await reader(...args);
|
|
3242
|
+
} catch {}
|
|
3243
|
+
return undefined;
|
|
3244
|
+
};
|
|
3245
|
+
}
|
|
3246
|
+
const binaryReader = wrapReader(shadowNpmInject.readFileBinary);
|
|
3247
|
+
const defaultReader = wrapReader(async lockPath => await shadowNpmInject.readFileUtf8(lockPath));
|
|
3248
|
+
return {
|
|
3249
|
+
[BUN$5]: wrapReader(async (lockPath, agentExecPath) => {
|
|
3250
|
+
const ext = path.extname(lockPath);
|
|
3251
|
+
if (ext === LOCK_EXT$1) {
|
|
3252
|
+
return await defaultReader(lockPath);
|
|
3253
|
+
}
|
|
3254
|
+
if (ext === BINARY_LOCK_EXT) {
|
|
3255
|
+
const lockBuffer = await binaryReader(lockPath);
|
|
3256
|
+
if (lockBuffer) {
|
|
3257
|
+
try {
|
|
3258
|
+
return index_cjs.parse(lockBuffer);
|
|
3259
|
+
} catch {}
|
|
3260
|
+
}
|
|
3261
|
+
// To print a Yarn lockfile to your console without writing it to disk
|
|
3262
|
+
// use `bun bun.lockb`.
|
|
3263
|
+
// https://bun.sh/guides/install/yarnlock
|
|
3264
|
+
return (await spawn.spawn(agentExecPath, [lockPath])).stdout.trim();
|
|
3265
|
+
}
|
|
3266
|
+
return undefined;
|
|
3267
|
+
}),
|
|
3268
|
+
[NPM$b]: defaultReader,
|
|
3269
|
+
[PNPM$8]: defaultReader,
|
|
3270
|
+
[VLT$5]: defaultReader,
|
|
3271
|
+
[YARN_BERRY$5]: defaultReader,
|
|
3272
|
+
[YARN_CLASSIC$6]: defaultReader
|
|
3273
|
+
};
|
|
3274
|
+
})();
|
|
3275
|
+
async function detectPackageEnvironment({
|
|
3276
|
+
cwd = process$1.cwd(),
|
|
3277
|
+
onUnknown
|
|
3278
|
+
} = {}) {
|
|
3279
|
+
let lockPath = await shadowNpmInject.findUp(Object.keys(LOCKS), {
|
|
3280
|
+
cwd
|
|
3281
|
+
});
|
|
3282
|
+
let lockName = lockPath ? path.basename(lockPath) : undefined;
|
|
3283
|
+
const isHiddenLockFile = lockName === '.package-lock.json';
|
|
3284
|
+
const pkgJsonPath = lockPath ? path.resolve(lockPath, `${isHiddenLockFile ? '../' : ''}../package.json`) : await shadowNpmInject.findUp('package.json', {
|
|
3285
|
+
cwd
|
|
3286
|
+
});
|
|
3287
|
+
const pkgPath = pkgJsonPath && fs.existsSync(pkgJsonPath) ? path.dirname(pkgJsonPath) : undefined;
|
|
3288
|
+
const editablePkgJson = pkgPath ? await packages.readPackageJson(pkgPath, {
|
|
3289
|
+
editable: true
|
|
3290
|
+
}) : undefined;
|
|
3291
|
+
const pkgJson = editablePkgJson?.content;
|
|
3292
|
+
// Read Corepack `packageManager` field in package.json:
|
|
3293
|
+
// https://nodejs.org/api/packages.html#packagemanager
|
|
3294
|
+
const pkgManager = strings.isNonEmptyString(pkgJson?.packageManager) ? pkgJson.packageManager : undefined;
|
|
3295
|
+
let agent;
|
|
3296
|
+
let agentVersion;
|
|
3297
|
+
if (pkgManager) {
|
|
3298
|
+
const atSignIndex = pkgManager.lastIndexOf('@');
|
|
3299
|
+
if (atSignIndex !== -1) {
|
|
3300
|
+
const name = pkgManager.slice(0, atSignIndex);
|
|
3301
|
+
const version = pkgManager.slice(atSignIndex + 1);
|
|
3302
|
+
if (version && AGENTS.includes(name)) {
|
|
3303
|
+
agent = name;
|
|
3304
|
+
agentVersion = semver.coerce(version) ?? undefined;
|
|
3305
|
+
}
|
|
3306
|
+
}
|
|
3307
|
+
}
|
|
3308
|
+
if (agent === undefined && !isHiddenLockFile && typeof pkgJsonPath === 'string' && typeof lockName === 'string') {
|
|
3309
|
+
agent = LOCKS[lockName];
|
|
3310
|
+
}
|
|
3311
|
+
if (agent === undefined) {
|
|
3312
|
+
agent = NPM$b;
|
|
3313
|
+
onUnknown?.(pkgManager);
|
|
3314
|
+
}
|
|
3315
|
+
const agentExecPath = await getAgentExecPath(agent);
|
|
3316
|
+
const npmExecPath = agent === NPM$b ? agentExecPath : await getAgentExecPath(NPM$b);
|
|
3317
|
+
if (agentVersion === undefined) {
|
|
3318
|
+
agentVersion = await getAgentVersion(agentExecPath, cwd);
|
|
3319
|
+
}
|
|
3320
|
+
if (agent === YARN_CLASSIC$6 && (agentVersion?.major ?? 0) > 1) {
|
|
3321
|
+
agent = YARN_BERRY$5;
|
|
3322
|
+
}
|
|
3323
|
+
const targets = {
|
|
3324
|
+
browser: false,
|
|
3325
|
+
node: true
|
|
3326
|
+
};
|
|
3327
|
+
let lockSrc;
|
|
3328
|
+
// Lazily access constants.maintainedNodeVersions.
|
|
3329
|
+
let minimumNodeVersion = constants.maintainedNodeVersions.last;
|
|
3330
|
+
if (pkgJson) {
|
|
3331
|
+
const browserField = pkgJson.browser;
|
|
3332
|
+
if (strings.isNonEmptyString(browserField) || objects.isObjectObject(browserField)) {
|
|
3333
|
+
targets.browser = true;
|
|
3334
|
+
}
|
|
3335
|
+
const nodeRange = pkgJson.engines?.['node'];
|
|
3336
|
+
if (strings.isNonEmptyString(nodeRange)) {
|
|
3337
|
+
const coerced = semver.coerce(nodeRange);
|
|
3338
|
+
if (coerced && semver.lt(coerced, minimumNodeVersion)) {
|
|
3339
|
+
minimumNodeVersion = coerced.version;
|
|
3340
|
+
}
|
|
3341
|
+
}
|
|
3342
|
+
const browserslistQuery = pkgJson['browserslist'];
|
|
3343
|
+
if (Array.isArray(browserslistQuery)) {
|
|
3344
|
+
const browserslistTargets = browserslist(browserslistQuery).map(s => s.toLowerCase()).sort(sorts.naturalCompare);
|
|
3345
|
+
const browserslistNodeTargets = browserslistTargets.filter(v => v.startsWith('node ')).map(v => v.slice(5 /*'node '.length*/));
|
|
3346
|
+
if (!targets.browser && browserslistTargets.length) {
|
|
3347
|
+
targets.browser = browserslistTargets.length !== browserslistNodeTargets.length;
|
|
3348
|
+
}
|
|
3349
|
+
if (browserslistNodeTargets.length) {
|
|
3350
|
+
const coerced = semver.coerce(browserslistNodeTargets[0]);
|
|
3351
|
+
if (coerced && semver.lt(coerced, minimumNodeVersion)) {
|
|
3352
|
+
minimumNodeVersion = coerced.version;
|
|
3353
|
+
}
|
|
3354
|
+
}
|
|
3355
|
+
}
|
|
3356
|
+
// Lazily access constants.maintainedNodeVersions.
|
|
3357
|
+
targets.node = constants.maintainedNodeVersions.some(v => semver.satisfies(v, `>=${minimumNodeVersion}`));
|
|
3358
|
+
lockSrc = typeof lockPath === 'string' ? await readLockFileByAgent[agent](lockPath, agentExecPath) : undefined;
|
|
3359
|
+
} else {
|
|
3360
|
+
lockName = undefined;
|
|
3361
|
+
lockPath = undefined;
|
|
3362
|
+
}
|
|
3363
|
+
const pkgSupported = targets.browser || targets.node;
|
|
3364
|
+
const npmBuggyOverrides = agent === NPM$b && !!agentVersion && semver.lt(agentVersion, NPM_BUGGY_OVERRIDES_PATCHED_VERSION$1);
|
|
3365
|
+
return {
|
|
3366
|
+
agent,
|
|
3367
|
+
agentExecPath,
|
|
3368
|
+
agentVersion,
|
|
3369
|
+
lockName,
|
|
3370
|
+
lockPath,
|
|
3371
|
+
lockSrc,
|
|
3372
|
+
minimumNodeVersion,
|
|
3373
|
+
npmExecPath,
|
|
3374
|
+
pkgJson: editablePkgJson,
|
|
3375
|
+
pkgPath,
|
|
3376
|
+
pkgSupported,
|
|
3377
|
+
features: {
|
|
3378
|
+
npmBuggyOverrides
|
|
3379
|
+
},
|
|
3380
|
+
targets
|
|
3381
|
+
};
|
|
3382
|
+
}
|
|
3383
|
+
async function detectAndValidatePackageEnvironment(cwd, options) {
|
|
3384
|
+
const {
|
|
3385
|
+
cmdName = '',
|
|
3386
|
+
logger,
|
|
3387
|
+
prod
|
|
3388
|
+
} = {
|
|
3389
|
+
__proto__: null,
|
|
3390
|
+
...options
|
|
3391
|
+
};
|
|
3392
|
+
const details = await detectPackageEnvironment({
|
|
3393
|
+
cwd,
|
|
3394
|
+
onUnknown(pkgManager) {
|
|
3395
|
+
logger?.warn(cmdPrefixMessage(cmdName, `Unknown package manager${pkgManager ? ` ${pkgManager}` : ''}, defaulting to npm`));
|
|
3396
|
+
}
|
|
3397
|
+
});
|
|
3398
|
+
if (!details.pkgSupported) {
|
|
3399
|
+
logger?.fail(cmdPrefixMessage(cmdName, 'No supported Node or browser range detected'));
|
|
3400
|
+
return;
|
|
3401
|
+
}
|
|
3402
|
+
if (details.agent === VLT$5) {
|
|
3403
|
+
logger?.fail(cmdPrefixMessage(cmdName, `${details.agent} does not support overrides. Soon, though ⚡`));
|
|
3404
|
+
return;
|
|
3405
|
+
}
|
|
3406
|
+
const lockName = details.lockName ?? 'lock file';
|
|
3407
|
+
if (details.lockName === undefined || details.lockSrc === undefined) {
|
|
3408
|
+
logger?.fail(cmdPrefixMessage(cmdName, `No ${lockName} found`));
|
|
3409
|
+
return;
|
|
3410
|
+
}
|
|
3411
|
+
if (details.lockSrc.trim() === '') {
|
|
3412
|
+
logger?.fail(cmdPrefixMessage(cmdName, `${lockName} is empty`));
|
|
3413
|
+
return;
|
|
3414
|
+
}
|
|
3415
|
+
if (details.pkgPath === undefined) {
|
|
3416
|
+
logger?.fail(cmdPrefixMessage(cmdName, 'No package.json found'));
|
|
3417
|
+
return;
|
|
3418
|
+
}
|
|
3419
|
+
if (prod && (details.agent === BUN$5 || details.agent === YARN_BERRY$5)) {
|
|
3420
|
+
logger?.fail(cmdPrefixMessage(cmdName, `--prod not supported for ${details.agent}${details.agentVersion ? `@${details.agentVersion.version}` : ''}`));
|
|
3421
|
+
return;
|
|
3422
|
+
}
|
|
3423
|
+
if (details.lockPath && path.relative(cwd, details.lockPath).startsWith('.')) {
|
|
3424
|
+
logger?.warn(cmdPrefixMessage(cmdName, `Package ${lockName} found at ${details.lockPath}`));
|
|
3425
|
+
}
|
|
3426
|
+
return details;
|
|
3427
|
+
}
|
|
3428
|
+
|
|
3429
|
+
const {
|
|
3430
|
+
NPM: NPM$a,
|
|
3431
|
+
PNPM: PNPM$7
|
|
3432
|
+
} = constants;
|
|
3433
|
+
const CMD_NAME$1 = 'socket fix';
|
|
3434
|
+
async function runFix() {
|
|
3435
|
+
// Lazily access constants.spinner.
|
|
3436
|
+
const {
|
|
3437
|
+
spinner
|
|
3438
|
+
} = constants;
|
|
3439
|
+
spinner.start();
|
|
3440
|
+
const cwd = process.cwd();
|
|
3441
|
+
const pkgEnvDetails = await detectAndValidatePackageEnvironment(cwd, {
|
|
3442
|
+
cmdName: CMD_NAME$1,
|
|
3443
|
+
logger: logger.logger
|
|
3444
|
+
});
|
|
3445
|
+
if (!pkgEnvDetails) {
|
|
3446
|
+
spinner.stop();
|
|
3447
|
+
return;
|
|
3448
|
+
}
|
|
3449
|
+
switch (pkgEnvDetails.agent) {
|
|
3450
|
+
case NPM$a:
|
|
3451
|
+
{
|
|
3452
|
+
await npmFix(pkgEnvDetails, cwd);
|
|
3453
|
+
break;
|
|
3454
|
+
}
|
|
3455
|
+
case PNPM$7:
|
|
3456
|
+
{
|
|
3457
|
+
await pnpmFix(pkgEnvDetails, cwd);
|
|
3458
|
+
break;
|
|
3459
|
+
}
|
|
3460
|
+
}
|
|
3461
|
+
spinner.successAndStop('Socket.dev fix successful');
|
|
3462
|
+
}
|
|
3463
|
+
|
|
3464
|
+
const {
|
|
3465
|
+
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$s
|
|
3466
|
+
} = constants;
|
|
3467
|
+
const config$t = {
|
|
3468
|
+
commandName: 'fix',
|
|
3469
|
+
description: 'Fix "fixable" Socket alerts',
|
|
3470
|
+
hidden: true,
|
|
3471
|
+
flags: {
|
|
3472
|
+
...commonFlags
|
|
3473
|
+
},
|
|
3474
|
+
help: (command, config) => `
|
|
3475
|
+
Usage
|
|
3476
|
+
$ ${command}
|
|
3477
|
+
|
|
3478
|
+
Options
|
|
3479
|
+
${getFlagListOutput(config.flags, 6)}
|
|
3480
|
+
`
|
|
3481
|
+
};
|
|
3482
|
+
const cmdFix = {
|
|
3483
|
+
description: config$t.description,
|
|
3484
|
+
hidden: config$t.hidden,
|
|
3485
|
+
run: run$t
|
|
3486
|
+
};
|
|
3487
|
+
async function run$t(argv, importMeta, {
|
|
3488
|
+
parentName
|
|
3489
|
+
}) {
|
|
3490
|
+
const cli = meowOrExit({
|
|
3491
|
+
argv,
|
|
3492
|
+
config: config$t,
|
|
3493
|
+
importMeta,
|
|
3494
|
+
parentName
|
|
3495
|
+
});
|
|
3496
|
+
if (cli.flags['dryRun']) {
|
|
3497
|
+
logger.logger.log(DRY_RUN_BAIL_TEXT$s);
|
|
3498
|
+
return;
|
|
3499
|
+
}
|
|
3500
|
+
await runFix();
|
|
3501
|
+
}
|
|
3502
|
+
|
|
3503
|
+
async function fetchPackageInfo(pkgName, pkgVersion, includeAllIssues) {
|
|
3504
|
+
const socketSdk = await shadowNpmInject.setupSdk(shadowNpmInject.getPublicToken());
|
|
3505
|
+
const result = await handleApiCall(socketSdk.getIssuesByNPMPackage(pkgName, pkgVersion), 'looking up package');
|
|
3506
|
+
const scoreResult = await handleApiCall(socketSdk.getScoreByNPMPackage(pkgName, pkgVersion), 'looking up package score');
|
|
3507
|
+
if (result.success === false) {
|
|
3508
|
+
return handleUnsuccessfulApiResponse('getIssuesByNPMPackage', result);
|
|
3509
|
+
}
|
|
3510
|
+
if (scoreResult.success === false) {
|
|
3511
|
+
return handleUnsuccessfulApiResponse('getScoreByNPMPackage', scoreResult);
|
|
3512
|
+
}
|
|
3513
|
+
const severityCount = shadowNpmInject.getSeverityCount(result.data, includeAllIssues ? undefined : 'high');
|
|
3514
|
+
return {
|
|
3515
|
+
data: result.data,
|
|
3516
|
+
severityCount,
|
|
3517
|
+
score: scoreResult.data
|
|
3518
|
+
};
|
|
3519
|
+
}
|
|
3520
|
+
|
|
3521
|
+
const {
|
|
3522
|
+
NPM: NPM$9
|
|
3523
|
+
} = registryConstants;
|
|
3524
|
+
function formatScore(score) {
|
|
3525
|
+
if (score > 80) {
|
|
3526
|
+
return colors.green(`${score}`);
|
|
3527
|
+
} else if (score < 80 && score > 60) {
|
|
3528
|
+
return colors.yellow(`${score}`);
|
|
3529
|
+
}
|
|
3530
|
+
return colors.red(`${score}`);
|
|
3531
|
+
}
|
|
3532
|
+
function logPackageIssuesDetails(packageData, outputMarkdown) {
|
|
3533
|
+
const issueDetails = packageData.filter(d => d.value?.severity === shadowNpmInject.SEVERITY.critical || d.value?.severity === shadowNpmInject.SEVERITY.high);
|
|
3534
|
+
const uniqueIssueDetails = issueDetails.reduce((acc, issue) => {
|
|
3535
|
+
const {
|
|
3536
|
+
type
|
|
3537
|
+
} = issue;
|
|
3538
|
+
if (type) {
|
|
3539
|
+
const details = acc.get(type);
|
|
3540
|
+
if (details) {
|
|
3541
|
+
details.count += 1;
|
|
3542
|
+
} else {
|
|
3543
|
+
acc.set(type, {
|
|
3544
|
+
label: issue.value?.label ?? '',
|
|
3545
|
+
count: 1
|
|
3546
|
+
});
|
|
3547
|
+
}
|
|
3548
|
+
}
|
|
3549
|
+
return acc;
|
|
3550
|
+
}, new Map());
|
|
3551
|
+
const format = new shadowNpmInject.ColorOrMarkdown(outputMarkdown);
|
|
3552
|
+
for (const [type, details] of uniqueIssueDetails.entries()) {
|
|
3553
|
+
const issueWithLink = format.hyperlink(details.label, shadowNpmInject.getSocketDevAlertUrl(type), {
|
|
3554
|
+
fallbackToUrl: true
|
|
3555
|
+
});
|
|
3556
|
+
if (details.count === 1) {
|
|
3557
|
+
logger.logger.log(`- ${issueWithLink}`);
|
|
3558
|
+
} else {
|
|
3559
|
+
logger.logger.log(`- ${issueWithLink}: ${details.count}`);
|
|
3560
|
+
}
|
|
3561
|
+
}
|
|
3562
|
+
}
|
|
3563
|
+
function logPackageInfo({
|
|
3564
|
+
data,
|
|
3565
|
+
score,
|
|
3566
|
+
severityCount
|
|
3567
|
+
}, {
|
|
3568
|
+
name,
|
|
3569
|
+
outputKind,
|
|
3570
|
+
pkgName,
|
|
3571
|
+
pkgVersion
|
|
3572
|
+
}) {
|
|
3573
|
+
if (outputKind === 'json') {
|
|
3036
3574
|
logger.logger.log(JSON.stringify(data, undefined, 2));
|
|
3037
3575
|
return;
|
|
3038
3576
|
}
|
|
3039
3577
|
if (outputKind === 'markdown') {
|
|
3040
|
-
logger.logger.log(
|
|
3041
|
-
|
|
3578
|
+
logger.logger.log(commonTags.stripIndents`
|
|
3579
|
+
# Package report for ${pkgName}
|
|
3580
|
+
|
|
3581
|
+
Package report card:
|
|
3582
|
+
`);
|
|
3042
3583
|
} else {
|
|
3043
|
-
logger.logger.log(
|
|
3584
|
+
logger.logger.log(`Package report card for ${pkgName}:`);
|
|
3044
3585
|
}
|
|
3045
3586
|
const scoreResult = {
|
|
3046
3587
|
'Supply Chain Risk': Math.floor(score.supplyChainRisk.score * 100),
|
|
@@ -3049,72 +3590,35 @@ function formatPackageInfo({
|
|
|
3049
3590
|
Vulnerabilities: Math.floor(score.vulnerability.score * 100),
|
|
3050
3591
|
License: Math.floor(score.license.score * 100)
|
|
3051
3592
|
};
|
|
3593
|
+
logger.logger.log('\n');
|
|
3052
3594
|
Object.entries(scoreResult).map(score => logger.logger.log(`- ${score[0]}: ${formatScore(score[1])}`));
|
|
3053
3595
|
logger.logger.log('\n');
|
|
3054
|
-
if (
|
|
3596
|
+
if (objects.hasKeys(severityCount)) {
|
|
3055
3597
|
if (outputKind === 'markdown') {
|
|
3056
3598
|
logger.logger.log('# Issues\n');
|
|
3057
3599
|
}
|
|
3058
|
-
logger.logger.log(`Package has these issues: ${formatSeverityCount(severityCount)}\n`);
|
|
3059
|
-
|
|
3600
|
+
logger.logger.log(`Package has these issues: ${shadowNpmInject.formatSeverityCount(severityCount)}\n`);
|
|
3601
|
+
logPackageIssuesDetails(data, outputKind === 'markdown');
|
|
3060
3602
|
} else {
|
|
3061
3603
|
logger.logger.log('Package has no issues');
|
|
3062
3604
|
}
|
|
3063
3605
|
const format = new shadowNpmInject.ColorOrMarkdown(outputKind === 'markdown');
|
|
3064
|
-
const url = shadowNpmInject.getSocketDevPackageOverviewUrl(NPM$
|
|
3065
|
-
logger.logger.log('\n');
|
|
3066
|
-
if (pkgVersion === 'latest') {
|
|
3067
|
-
logger.logger.log(`Detailed info on socket.dev: ${format.hyperlink(`${pkgName}`, url, {
|
|
3068
|
-
fallbackToUrl: true
|
|
3069
|
-
})}`);
|
|
3070
|
-
} else {
|
|
3071
|
-
logger.logger.log(`Detailed info on socket.dev: ${format.hyperlink(`${pkgName} v${pkgVersion}`, url, {
|
|
3072
|
-
fallbackToUrl: true
|
|
3073
|
-
})}`);
|
|
3074
|
-
}
|
|
3075
|
-
if (outputKind !== 'markdown') {
|
|
3076
|
-
logger.logger.log(colors.dim(`\nOr rerun ${colors.italic(name)} using the ${colors.italic('--json')} flag to get full JSON output`));
|
|
3077
|
-
} else {
|
|
3078
|
-
logger.logger.log('');
|
|
3079
|
-
}
|
|
3080
|
-
}
|
|
3081
|
-
function formatPackageIssuesDetails(packageData, outputMarkdown) {
|
|
3082
|
-
const issueDetails = packageData.filter(d => d.value?.severity === 'high' || d.value?.severity === 'critical');
|
|
3083
|
-
const uniqueIssues = issueDetails.reduce((acc, issue) => {
|
|
3084
|
-
const {
|
|
3085
|
-
type
|
|
3086
|
-
} = issue;
|
|
3087
|
-
if (type) {
|
|
3088
|
-
if (acc[type] === undefined) {
|
|
3089
|
-
acc[type] = {
|
|
3090
|
-
label: issue.value?.label,
|
|
3091
|
-
count: 1
|
|
3092
|
-
};
|
|
3093
|
-
} else {
|
|
3094
|
-
acc[type].count += 1;
|
|
3095
|
-
}
|
|
3096
|
-
}
|
|
3097
|
-
return acc;
|
|
3098
|
-
}, {});
|
|
3099
|
-
const format = new shadowNpmInject.ColorOrMarkdown(outputMarkdown);
|
|
3100
|
-
for (const issue of Object.keys(uniqueIssues)) {
|
|
3101
|
-
const issueWithLink = format.hyperlink(`${uniqueIssues[issue]?.label}`, shadowNpmInject.getSocketDevAlertUrl(issue), {
|
|
3606
|
+
const url = shadowNpmInject.getSocketDevPackageOverviewUrl(NPM$9, pkgName, pkgVersion);
|
|
3607
|
+
logger.logger.log('\n');
|
|
3608
|
+
if (pkgVersion === 'latest') {
|
|
3609
|
+
logger.logger.log(`Detailed info on socket.dev: ${format.hyperlink(`${pkgName}`, url, {
|
|
3102
3610
|
fallbackToUrl: true
|
|
3103
|
-
});
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
}
|
|
3611
|
+
})}`);
|
|
3612
|
+
} else {
|
|
3613
|
+
logger.logger.log(`Detailed info on socket.dev: ${format.hyperlink(`${pkgName} v${pkgVersion}`, url, {
|
|
3614
|
+
fallbackToUrl: true
|
|
3615
|
+
})}`);
|
|
3109
3616
|
}
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
} else if (score < 80 && score > 60) {
|
|
3115
|
-
return colors.yellow(`${score}`);
|
|
3617
|
+
if (outputKind !== 'markdown') {
|
|
3618
|
+
logger.logger.log(colors.dim(`\nOr rerun ${colors.italic(name)} using the ${colors.italic('--json')} flag to get full JSON output`));
|
|
3619
|
+
} else {
|
|
3620
|
+
logger.logger.log('');
|
|
3116
3621
|
}
|
|
3117
|
-
return colors.red(`${score}`);
|
|
3118
3622
|
}
|
|
3119
3623
|
|
|
3120
3624
|
async function getPackageInfo({
|
|
@@ -3133,13 +3637,13 @@ async function getPackageInfo({
|
|
|
3133
3637
|
const packageData = await fetchPackageInfo(pkgName, pkgVersion, includeAllIssues);
|
|
3134
3638
|
spinner.successAndStop('Data fetched');
|
|
3135
3639
|
if (packageData) {
|
|
3136
|
-
|
|
3640
|
+
logPackageInfo(packageData, {
|
|
3137
3641
|
name: commandName,
|
|
3138
3642
|
outputKind,
|
|
3139
3643
|
pkgName,
|
|
3140
3644
|
pkgVersion
|
|
3141
3645
|
});
|
|
3142
|
-
if (strict &&
|
|
3646
|
+
if (strict && objects.hasKeys(packageData.severityCount)) {
|
|
3143
3647
|
// Let NodeJS exit gracefully but with exit(1)
|
|
3144
3648
|
process$1.exitCode = 1;
|
|
3145
3649
|
}
|
|
@@ -3341,8 +3845,8 @@ async function run$r(argv, importMeta, {
|
|
|
3341
3845
|
importMeta,
|
|
3342
3846
|
parentName
|
|
3343
3847
|
});
|
|
3344
|
-
|
|
3345
|
-
|
|
3848
|
+
const apiBaseUrl = cli.flags['apiBaseUrl'];
|
|
3849
|
+
const apiProxy = cli.flags['apiProxy'];
|
|
3346
3850
|
if (cli.flags['dryRun']) {
|
|
3347
3851
|
logger.logger.log(DRY_RUN_BAIL_TEXT$q);
|
|
3348
3852
|
return;
|
|
@@ -3811,6 +4315,9 @@ const config$o = {
|
|
|
3811
4315
|
|
|
3812
4316
|
Support is beta. Please report issues or give us feedback on what's missing.
|
|
3813
4317
|
|
|
4318
|
+
This is only for SBT. If your Scala setup uses gradle, please see the help
|
|
4319
|
+
sections for \`socket manifest gradle\` or \`socket cdxgen\`.
|
|
4320
|
+
|
|
3814
4321
|
Examples
|
|
3815
4322
|
|
|
3816
4323
|
$ ${command} ./build.sbt
|
|
@@ -4184,21 +4691,21 @@ async function run$l(argv, importMeta, {
|
|
|
4184
4691
|
}
|
|
4185
4692
|
|
|
4186
4693
|
const {
|
|
4187
|
-
NPM: NPM$
|
|
4694
|
+
NPM: NPM$8
|
|
4188
4695
|
} = constants;
|
|
4189
4696
|
async function wrapNpm(argv) {
|
|
4190
4697
|
// Lazily access constants.distShadowNpmBinPath.
|
|
4191
4698
|
const shadowBin = require(constants.distShadowNpmBinPath);
|
|
4192
|
-
await shadowBin(NPM$
|
|
4699
|
+
await shadowBin(NPM$8, argv);
|
|
4193
4700
|
}
|
|
4194
4701
|
|
|
4195
4702
|
const {
|
|
4196
4703
|
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$k,
|
|
4197
|
-
NPM: NPM$
|
|
4704
|
+
NPM: NPM$7
|
|
4198
4705
|
} = constants;
|
|
4199
4706
|
const config$k = {
|
|
4200
4707
|
commandName: 'npm',
|
|
4201
|
-
description: `${NPM$
|
|
4708
|
+
description: `${NPM$7} wrapper functionality`,
|
|
4202
4709
|
hidden: false,
|
|
4203
4710
|
flags: {},
|
|
4204
4711
|
help: (command, _config) => `
|
|
@@ -4312,273 +4819,20 @@ async function run$i(argv, importMeta, {
|
|
|
4312
4819
|
}
|
|
4313
4820
|
|
|
4314
4821
|
const {
|
|
4315
|
-
BUN: BUN$
|
|
4316
|
-
NPM: NPM$
|
|
4317
|
-
PNPM: PNPM$7,
|
|
4318
|
-
VLT: VLT$6,
|
|
4319
|
-
YARN_BERRY: YARN_BERRY$6,
|
|
4320
|
-
YARN_CLASSIC: YARN_CLASSIC$6
|
|
4321
|
-
} = constants;
|
|
4322
|
-
function matchHumanStdout(stdout, name) {
|
|
4323
|
-
return stdout.includes(` ${name}@`);
|
|
4324
|
-
}
|
|
4325
|
-
function matchQueryStdout(stdout, name) {
|
|
4326
|
-
return stdout.includes(`"${name}"`);
|
|
4327
|
-
}
|
|
4328
|
-
const depsIncludesByAgent = new Map([[BUN$6, matchHumanStdout], [NPM$9, matchQueryStdout], [PNPM$7, matchQueryStdout], [VLT$6, matchQueryStdout], [YARN_BERRY$6, matchHumanStdout], [YARN_CLASSIC$6, matchHumanStdout]]);
|
|
4329
|
-
|
|
4330
|
-
const {
|
|
4331
|
-
BINARY_LOCK_EXT,
|
|
4332
|
-
BUN: BUN$5,
|
|
4333
|
-
LOCK_EXT: LOCK_EXT$1,
|
|
4334
|
-
NPM: NPM$8,
|
|
4822
|
+
BUN: BUN$4,
|
|
4823
|
+
NPM: NPM$6,
|
|
4335
4824
|
PNPM: PNPM$6,
|
|
4336
|
-
VLT: VLT$
|
|
4337
|
-
|
|
4338
|
-
YARN_BERRY: YARN_BERRY$5,
|
|
4825
|
+
VLT: VLT$4,
|
|
4826
|
+
YARN_BERRY: YARN_BERRY$4,
|
|
4339
4827
|
YARN_CLASSIC: YARN_CLASSIC$5
|
|
4340
4828
|
} = constants;
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
__proto__: null,
|
|
4344
|
-
[BUN$5]: BUN$5,
|
|
4345
|
-
[NPM$8]: NPM$8,
|
|
4346
|
-
[PNPM$6]: PNPM$6,
|
|
4347
|
-
[YARN_BERRY$5]: YARN,
|
|
4348
|
-
[YARN_CLASSIC$5]: YARN,
|
|
4349
|
-
[VLT$5]: VLT$5
|
|
4350
|
-
};
|
|
4351
|
-
async function getAgentExecPath(agent) {
|
|
4352
|
-
const binName = binByAgent[agent];
|
|
4353
|
-
return (await which(binName, {
|
|
4354
|
-
nothrow: true
|
|
4355
|
-
})) ?? binName;
|
|
4356
|
-
}
|
|
4357
|
-
async function getAgentVersion(agentExecPath, cwd) {
|
|
4358
|
-
let result;
|
|
4359
|
-
try {
|
|
4360
|
-
result = semver.coerce(
|
|
4361
|
-
// All package managers support the "--version" flag.
|
|
4362
|
-
(await spawn.spawn(agentExecPath, ['--version'], {
|
|
4363
|
-
cwd
|
|
4364
|
-
})).stdout) ?? undefined;
|
|
4365
|
-
} catch {}
|
|
4366
|
-
return result;
|
|
4367
|
-
}
|
|
4368
|
-
|
|
4369
|
-
// The order of LOCKS properties IS significant as it affects iteration order.
|
|
4370
|
-
const LOCKS = {
|
|
4371
|
-
[`bun${LOCK_EXT$1}`]: BUN$5,
|
|
4372
|
-
[`bun${BINARY_LOCK_EXT}`]: BUN$5,
|
|
4373
|
-
// If both package-lock.json and npm-shrinkwrap.json are present in the root
|
|
4374
|
-
// of a project, npm-shrinkwrap.json will take precedence and package-lock.json
|
|
4375
|
-
// will be ignored.
|
|
4376
|
-
// https://docs.npmjs.com/cli/v10/configuring-npm/package-lock-json#package-lockjson-vs-npm-shrinkwrapjson
|
|
4377
|
-
'npm-shrinkwrap.json': NPM$8,
|
|
4378
|
-
'package-lock.json': NPM$8,
|
|
4379
|
-
'pnpm-lock.yaml': PNPM$6,
|
|
4380
|
-
'pnpm-lock.yml': PNPM$6,
|
|
4381
|
-
[`yarn${LOCK_EXT$1}`]: YARN_CLASSIC$5,
|
|
4382
|
-
'vlt-lock.json': VLT$5,
|
|
4383
|
-
// Lastly, look for a hidden lock file which is present if .npmrc has package-lock=false:
|
|
4384
|
-
// https://docs.npmjs.com/cli/v10/configuring-npm/package-lock-json#hidden-lockfiles
|
|
4385
|
-
//
|
|
4386
|
-
// Unlike the other LOCKS keys this key contains a directory AND filename so
|
|
4387
|
-
// it has to be handled differently.
|
|
4388
|
-
'node_modules/.package-lock.json': NPM$8
|
|
4389
|
-
};
|
|
4390
|
-
const readLockFileByAgent = (() => {
|
|
4391
|
-
function wrapReader(reader) {
|
|
4392
|
-
return async (...args) => {
|
|
4393
|
-
try {
|
|
4394
|
-
return await reader(...args);
|
|
4395
|
-
} catch {}
|
|
4396
|
-
return undefined;
|
|
4397
|
-
};
|
|
4398
|
-
}
|
|
4399
|
-
const binaryReader = wrapReader(shadowNpmInject.readFileBinary);
|
|
4400
|
-
const defaultReader = wrapReader(async lockPath => await shadowNpmInject.readFileUtf8(lockPath));
|
|
4401
|
-
return {
|
|
4402
|
-
[BUN$5]: wrapReader(async (lockPath, agentExecPath) => {
|
|
4403
|
-
const ext = path.extname(lockPath);
|
|
4404
|
-
if (ext === LOCK_EXT$1) {
|
|
4405
|
-
return await defaultReader(lockPath);
|
|
4406
|
-
}
|
|
4407
|
-
if (ext === BINARY_LOCK_EXT) {
|
|
4408
|
-
const lockBuffer = await binaryReader(lockPath);
|
|
4409
|
-
if (lockBuffer) {
|
|
4410
|
-
try {
|
|
4411
|
-
return index_cjs.parse(lockBuffer);
|
|
4412
|
-
} catch {}
|
|
4413
|
-
}
|
|
4414
|
-
// To print a Yarn lockfile to your console without writing it to disk
|
|
4415
|
-
// use `bun bun.lockb`.
|
|
4416
|
-
// https://bun.sh/guides/install/yarnlock
|
|
4417
|
-
return (await spawn.spawn(agentExecPath, [lockPath])).stdout.trim();
|
|
4418
|
-
}
|
|
4419
|
-
return undefined;
|
|
4420
|
-
}),
|
|
4421
|
-
[NPM$8]: defaultReader,
|
|
4422
|
-
[PNPM$6]: defaultReader,
|
|
4423
|
-
[VLT$5]: defaultReader,
|
|
4424
|
-
[YARN_BERRY$5]: defaultReader,
|
|
4425
|
-
[YARN_CLASSIC$5]: defaultReader
|
|
4426
|
-
};
|
|
4427
|
-
})();
|
|
4428
|
-
async function detectPackageEnvironment({
|
|
4429
|
-
cwd = process$1.cwd(),
|
|
4430
|
-
onUnknown
|
|
4431
|
-
} = {}) {
|
|
4432
|
-
let lockPath = await shadowNpmInject.findUp(Object.keys(LOCKS), {
|
|
4433
|
-
cwd
|
|
4434
|
-
});
|
|
4435
|
-
let lockName = lockPath ? path.basename(lockPath) : undefined;
|
|
4436
|
-
const isHiddenLockFile = lockName === '.package-lock.json';
|
|
4437
|
-
const pkgJsonPath = lockPath ? path.resolve(lockPath, `${isHiddenLockFile ? '../' : ''}../package.json`) : await shadowNpmInject.findUp('package.json', {
|
|
4438
|
-
cwd
|
|
4439
|
-
});
|
|
4440
|
-
const pkgPath = pkgJsonPath && fs.existsSync(pkgJsonPath) ? path.dirname(pkgJsonPath) : undefined;
|
|
4441
|
-
const editablePkgJson = pkgPath ? await packages.readPackageJson(pkgPath, {
|
|
4442
|
-
editable: true
|
|
4443
|
-
}) : undefined;
|
|
4444
|
-
const pkgJson = editablePkgJson?.content;
|
|
4445
|
-
// Read Corepack `packageManager` field in package.json:
|
|
4446
|
-
// https://nodejs.org/api/packages.html#packagemanager
|
|
4447
|
-
const pkgManager = strings.isNonEmptyString(pkgJson?.packageManager) ? pkgJson.packageManager : undefined;
|
|
4448
|
-
let agent;
|
|
4449
|
-
let agentVersion;
|
|
4450
|
-
if (pkgManager) {
|
|
4451
|
-
const atSignIndex = pkgManager.lastIndexOf('@');
|
|
4452
|
-
if (atSignIndex !== -1) {
|
|
4453
|
-
const name = pkgManager.slice(0, atSignIndex);
|
|
4454
|
-
const version = pkgManager.slice(atSignIndex + 1);
|
|
4455
|
-
if (version && AGENTS.includes(name)) {
|
|
4456
|
-
agent = name;
|
|
4457
|
-
agentVersion = semver.coerce(version) ?? undefined;
|
|
4458
|
-
}
|
|
4459
|
-
}
|
|
4460
|
-
}
|
|
4461
|
-
if (agent === undefined && !isHiddenLockFile && typeof pkgJsonPath === 'string' && typeof lockName === 'string') {
|
|
4462
|
-
agent = LOCKS[lockName];
|
|
4463
|
-
}
|
|
4464
|
-
if (agent === undefined) {
|
|
4465
|
-
agent = NPM$8;
|
|
4466
|
-
onUnknown?.(pkgManager);
|
|
4467
|
-
}
|
|
4468
|
-
const agentExecPath = await getAgentExecPath(agent);
|
|
4469
|
-
const npmExecPath = agent === NPM$8 ? agentExecPath : await getAgentExecPath(NPM$8);
|
|
4470
|
-
if (agentVersion === undefined) {
|
|
4471
|
-
agentVersion = await getAgentVersion(agentExecPath, cwd);
|
|
4472
|
-
}
|
|
4473
|
-
if (agent === YARN_CLASSIC$5 && (agentVersion?.major ?? 0) > 1) {
|
|
4474
|
-
agent = YARN_BERRY$5;
|
|
4475
|
-
}
|
|
4476
|
-
const targets = {
|
|
4477
|
-
browser: false,
|
|
4478
|
-
node: true
|
|
4479
|
-
};
|
|
4480
|
-
let lockSrc;
|
|
4481
|
-
// Lazily access constants.maintainedNodeVersions.
|
|
4482
|
-
let minimumNodeVersion = constants.maintainedNodeVersions.previous;
|
|
4483
|
-
if (pkgJson) {
|
|
4484
|
-
const browserField = pkgJson.browser;
|
|
4485
|
-
if (strings.isNonEmptyString(browserField) || objects.isObjectObject(browserField)) {
|
|
4486
|
-
targets.browser = true;
|
|
4487
|
-
}
|
|
4488
|
-
const nodeRange = pkgJson.engines?.['node'];
|
|
4489
|
-
if (strings.isNonEmptyString(nodeRange)) {
|
|
4490
|
-
const coerced = semver.coerce(nodeRange);
|
|
4491
|
-
if (coerced && semver.lt(coerced, minimumNodeVersion)) {
|
|
4492
|
-
minimumNodeVersion = coerced.version;
|
|
4493
|
-
}
|
|
4494
|
-
}
|
|
4495
|
-
const browserslistQuery = pkgJson['browserslist'];
|
|
4496
|
-
if (Array.isArray(browserslistQuery)) {
|
|
4497
|
-
const browserslistTargets = browserslist(browserslistQuery).map(s => s.toLowerCase()).sort(sorts.naturalCompare);
|
|
4498
|
-
const browserslistNodeTargets = browserslistTargets.filter(v => v.startsWith('node ')).map(v => v.slice(5 /*'node '.length*/));
|
|
4499
|
-
if (!targets.browser && browserslistTargets.length) {
|
|
4500
|
-
targets.browser = browserslistTargets.length !== browserslistNodeTargets.length;
|
|
4501
|
-
}
|
|
4502
|
-
if (browserslistNodeTargets.length) {
|
|
4503
|
-
const coerced = semver.coerce(browserslistNodeTargets[0]);
|
|
4504
|
-
if (coerced && semver.lt(coerced, minimumNodeVersion)) {
|
|
4505
|
-
minimumNodeVersion = coerced.version;
|
|
4506
|
-
}
|
|
4507
|
-
}
|
|
4508
|
-
}
|
|
4509
|
-
// Lazily access constants.maintainedNodeVersions.
|
|
4510
|
-
targets.node = constants.maintainedNodeVersions.some(v => semver.satisfies(v, `>=${minimumNodeVersion}`));
|
|
4511
|
-
lockSrc = typeof lockPath === 'string' ? await readLockFileByAgent[agent](lockPath, agentExecPath) : undefined;
|
|
4512
|
-
} else {
|
|
4513
|
-
lockName = undefined;
|
|
4514
|
-
lockPath = undefined;
|
|
4515
|
-
}
|
|
4516
|
-
return {
|
|
4517
|
-
agent,
|
|
4518
|
-
agentExecPath,
|
|
4519
|
-
agentVersion,
|
|
4520
|
-
lockName,
|
|
4521
|
-
lockPath,
|
|
4522
|
-
lockSrc,
|
|
4523
|
-
minimumNodeVersion,
|
|
4524
|
-
npmExecPath,
|
|
4525
|
-
pkgJson: editablePkgJson,
|
|
4526
|
-
pkgPath,
|
|
4527
|
-
supported: targets.browser || targets.node,
|
|
4528
|
-
targets
|
|
4529
|
-
};
|
|
4829
|
+
function matchLsCmdViewHumanStdout(stdout, name) {
|
|
4830
|
+
return stdout.includes(` ${name}@`);
|
|
4530
4831
|
}
|
|
4531
|
-
|
|
4532
|
-
|
|
4533
|
-
BUN: BUN$4,
|
|
4534
|
-
VLT: VLT$4,
|
|
4535
|
-
YARN_BERRY: YARN_BERRY$4
|
|
4536
|
-
} = constants;
|
|
4537
|
-
const COMMAND_TITLE$2 = 'Socket Optimize';
|
|
4538
|
-
async function detectAndValidatePackageEnvironment(cwd, options) {
|
|
4539
|
-
const {
|
|
4540
|
-
logger,
|
|
4541
|
-
prod
|
|
4542
|
-
} = {
|
|
4543
|
-
__proto__: null,
|
|
4544
|
-
...options
|
|
4545
|
-
};
|
|
4546
|
-
const details = await detectPackageEnvironment({
|
|
4547
|
-
cwd,
|
|
4548
|
-
onUnknown(pkgManager) {
|
|
4549
|
-
logger?.warn(`${COMMAND_TITLE$2}: Unknown package manager${pkgManager ? ` ${pkgManager}` : ''}, defaulting to npm`);
|
|
4550
|
-
}
|
|
4551
|
-
});
|
|
4552
|
-
if (!details.supported) {
|
|
4553
|
-
logger?.fail(`${COMMAND_TITLE$2}: No supported Node or browser range detected`);
|
|
4554
|
-
return;
|
|
4555
|
-
}
|
|
4556
|
-
if (details.agent === VLT$4) {
|
|
4557
|
-
logger?.fail(`${COMMAND_TITLE$2}: ${details.agent} does not support overrides. Soon, though ⚡`);
|
|
4558
|
-
return;
|
|
4559
|
-
}
|
|
4560
|
-
const lockName = details.lockName ?? 'lock file';
|
|
4561
|
-
if (details.lockName === undefined || details.lockSrc === undefined) {
|
|
4562
|
-
logger?.fail(`${COMMAND_TITLE$2}: No ${lockName} found`);
|
|
4563
|
-
return;
|
|
4564
|
-
}
|
|
4565
|
-
if (details.lockSrc.trim() === '') {
|
|
4566
|
-
logger?.fail(`${COMMAND_TITLE$2}: ${lockName} is empty`);
|
|
4567
|
-
return;
|
|
4568
|
-
}
|
|
4569
|
-
if (details.pkgPath === undefined) {
|
|
4570
|
-
logger?.fail(`${COMMAND_TITLE$2}: No package.json found`);
|
|
4571
|
-
return;
|
|
4572
|
-
}
|
|
4573
|
-
if (prod && (details.agent === BUN$4 || details.agent === YARN_BERRY$4)) {
|
|
4574
|
-
logger?.fail(`${COMMAND_TITLE$2}: --prod not supported for ${details.agent}${details.agentVersion ? `@${details.agentVersion.toString()}` : ''}`);
|
|
4575
|
-
return;
|
|
4576
|
-
}
|
|
4577
|
-
if (details.lockPath && path.relative(cwd, details.lockPath).startsWith('.')) {
|
|
4578
|
-
logger?.warn(`${COMMAND_TITLE$2}: Package ${lockName} found at ${details.lockPath}`);
|
|
4579
|
-
}
|
|
4580
|
-
return details;
|
|
4832
|
+
function matchQueryCmdStdout(stdout, name) {
|
|
4833
|
+
return stdout.includes(`"${name}"`);
|
|
4581
4834
|
}
|
|
4835
|
+
const depsIncludesByAgent = new Map([[BUN$4, matchLsCmdViewHumanStdout], [NPM$6, matchQueryCmdStdout], [PNPM$6, matchQueryCmdStdout], [VLT$4, matchQueryCmdStdout], [YARN_BERRY$4, matchLsCmdViewHumanStdout], [YARN_CLASSIC$5, matchLsCmdViewHumanStdout]]);
|
|
4582
4836
|
|
|
4583
4837
|
function getDependencyEntries(pkgJson) {
|
|
4584
4838
|
const {
|
|
@@ -4606,7 +4860,7 @@ function getDependencyEntries(pkgJson) {
|
|
|
4606
4860
|
|
|
4607
4861
|
const {
|
|
4608
4862
|
BUN: BUN$3,
|
|
4609
|
-
NPM: NPM$
|
|
4863
|
+
NPM: NPM$5,
|
|
4610
4864
|
OVERRIDES: OVERRIDES$1,
|
|
4611
4865
|
PNPM: PNPM$5,
|
|
4612
4866
|
RESOLUTIONS: RESOLUTIONS$1,
|
|
@@ -4627,7 +4881,7 @@ function getOverridesDataBun(pkgJson) {
|
|
|
4627
4881
|
function getOverridesDataNpm(pkgJson) {
|
|
4628
4882
|
const overrides = pkgJson?.[OVERRIDES$1] ?? {};
|
|
4629
4883
|
return {
|
|
4630
|
-
type: NPM$
|
|
4884
|
+
type: NPM$5,
|
|
4631
4885
|
overrides
|
|
4632
4886
|
};
|
|
4633
4887
|
}
|
|
@@ -4668,7 +4922,7 @@ function getOverridesDataClassic(pkgJson) {
|
|
|
4668
4922
|
overrides
|
|
4669
4923
|
};
|
|
4670
4924
|
}
|
|
4671
|
-
const overridesDataByAgent = new Map([[BUN$3, getOverridesDataBun], [NPM$
|
|
4925
|
+
const overridesDataByAgent = new Map([[BUN$3, getOverridesDataBun], [NPM$5, getOverridesDataNpm], [PNPM$5, getOverridesDataPnpm], [VLT$3, getOverridesDataVlt], [YARN_BERRY$3, getOverridesDataYarn], [YARN_CLASSIC$4, getOverridesDataClassic]]);
|
|
4672
4926
|
|
|
4673
4927
|
const {
|
|
4674
4928
|
PNPM: PNPM$4
|
|
@@ -4716,26 +4970,26 @@ function workspacePatternToGlobPattern(workspace) {
|
|
|
4716
4970
|
const {
|
|
4717
4971
|
BUN: BUN$2,
|
|
4718
4972
|
LOCK_EXT,
|
|
4719
|
-
NPM: NPM$
|
|
4973
|
+
NPM: NPM$4,
|
|
4720
4974
|
PNPM: PNPM$3,
|
|
4721
4975
|
VLT: VLT$2,
|
|
4722
4976
|
YARN_BERRY: YARN_BERRY$2,
|
|
4723
4977
|
YARN_CLASSIC: YARN_CLASSIC$3
|
|
4724
4978
|
} = constants;
|
|
4725
|
-
function
|
|
4979
|
+
function includesNpm(lockSrc, name) {
|
|
4726
4980
|
// Detects the package name in the following cases:
|
|
4727
4981
|
// "name":
|
|
4728
4982
|
return lockSrc.includes(`"${name}":`);
|
|
4729
4983
|
}
|
|
4730
|
-
function
|
|
4984
|
+
function includesBun(lockSrc, name, lockName) {
|
|
4731
4985
|
// This is a bit counterintuitive. When lockName ends with a .lockb
|
|
4732
4986
|
// we treat it as a yarn.lock. When lockName ends with a .lock we
|
|
4733
4987
|
// treat it as a package-lock.json. The bun.lock format is not identical
|
|
4734
4988
|
// package-lock.json, however it close enough for npmLockIncludes to work.
|
|
4735
|
-
const
|
|
4736
|
-
return
|
|
4989
|
+
const lockfileScanner = lockName?.endsWith(LOCK_EXT) ? includesNpm : includesYarn;
|
|
4990
|
+
return lockfileScanner(lockSrc, name);
|
|
4737
4991
|
}
|
|
4738
|
-
function
|
|
4992
|
+
function includesPnpm(lockSrc, name) {
|
|
4739
4993
|
const escapedName = regexps.escapeRegExp(name);
|
|
4740
4994
|
return new RegExp(
|
|
4741
4995
|
// Detects the package name in the following cases:
|
|
@@ -4745,12 +4999,12 @@ function lockIncludesPnpm(lockSrc, name) {
|
|
|
4745
4999
|
// name@
|
|
4746
5000
|
`(?<=^\\s*)(?:(['/])${escapedName}\\1|${escapedName}(?=[:@]))`, 'm').test(lockSrc);
|
|
4747
5001
|
}
|
|
4748
|
-
function
|
|
5002
|
+
function includesVlt(lockSrc, name) {
|
|
4749
5003
|
// Detects the package name in the following cases:
|
|
4750
5004
|
// "name"
|
|
4751
5005
|
return lockSrc.includes(`"${name}"`);
|
|
4752
5006
|
}
|
|
4753
|
-
function
|
|
5007
|
+
function includesYarn(lockSrc, name) {
|
|
4754
5008
|
const escapedName = regexps.escapeRegExp(name);
|
|
4755
5009
|
return new RegExp(
|
|
4756
5010
|
// Detects the package name in the following cases:
|
|
@@ -4760,11 +5014,11 @@ function lockIncludesYarn(lockSrc, name) {
|
|
|
4760
5014
|
// , name@
|
|
4761
5015
|
`(?<=(?:^\\s*|,\\s*)"?)${escapedName}(?=@)`, 'm').test(lockSrc);
|
|
4762
5016
|
}
|
|
4763
|
-
const
|
|
5017
|
+
const lockfileIncludesByAgent = new Map([[BUN$2, includesBun], [NPM$4, includesNpm], [PNPM$3, includesPnpm], [VLT$2, includesVlt], [YARN_BERRY$2, includesYarn], [YARN_CLASSIC$3, includesYarn]]);
|
|
4764
5018
|
|
|
4765
5019
|
const {
|
|
4766
5020
|
BUN: BUN$1,
|
|
4767
|
-
NPM: NPM$
|
|
5021
|
+
NPM: NPM$3,
|
|
4768
5022
|
PNPM: PNPM$2,
|
|
4769
5023
|
VLT: VLT$1,
|
|
4770
5024
|
YARN_BERRY: YARN_BERRY$1,
|
|
@@ -4800,11 +5054,11 @@ function cleanupQueryStdout(stdout) {
|
|
|
4800
5054
|
}
|
|
4801
5055
|
return JSON.stringify([...names], null, 2);
|
|
4802
5056
|
}
|
|
4803
|
-
function
|
|
5057
|
+
function parsableToQueryStdout(stdout) {
|
|
4804
5058
|
if (stdout === '') {
|
|
4805
5059
|
return '';
|
|
4806
5060
|
}
|
|
4807
|
-
// Convert the
|
|
5061
|
+
// Convert the parsable stdout into a json array of unique names.
|
|
4808
5062
|
// The matchAll regexp looks for a forward (posix) or backward (win32) slash
|
|
4809
5063
|
// and matches one or more non-slashes until the newline.
|
|
4810
5064
|
const names = new Set(stdout.matchAll(/(?<=[/\\])[^/\\]+(?=\n)/g));
|
|
@@ -4834,7 +5088,7 @@ async function lsNpm(agentExecPath, cwd) {
|
|
|
4834
5088
|
}
|
|
4835
5089
|
async function lsPnpm(agentExecPath, cwd, options) {
|
|
4836
5090
|
const npmExecPath = options?.npmExecPath;
|
|
4837
|
-
if (npmExecPath && npmExecPath !== NPM$
|
|
5091
|
+
if (npmExecPath && npmExecPath !== NPM$3) {
|
|
4838
5092
|
const result = await npmQuery(npmExecPath, cwd);
|
|
4839
5093
|
if (result) {
|
|
4840
5094
|
return result;
|
|
@@ -4842,15 +5096,19 @@ async function lsPnpm(agentExecPath, cwd, options) {
|
|
|
4842
5096
|
}
|
|
4843
5097
|
let stdout = '';
|
|
4844
5098
|
try {
|
|
4845
|
-
stdout = (await spawn.spawn(agentExecPath,
|
|
5099
|
+
stdout = (await spawn.spawn(agentExecPath,
|
|
5100
|
+
// Pnpm uses the alternative spelling of parsable.
|
|
5101
|
+
// https://en.wiktionary.org/wiki/parsable
|
|
5102
|
+
['ls', '--parseable', '--prod', '--depth', 'Infinity'], {
|
|
4846
5103
|
cwd
|
|
4847
5104
|
})).stdout;
|
|
4848
5105
|
} catch {}
|
|
4849
|
-
return
|
|
5106
|
+
return parsableToQueryStdout(stdout);
|
|
4850
5107
|
}
|
|
4851
5108
|
async function lsVlt(agentExecPath, cwd) {
|
|
4852
5109
|
let stdout = '';
|
|
4853
5110
|
try {
|
|
5111
|
+
// See https://docs.vlt.sh/cli/commands/list#options.
|
|
4854
5112
|
stdout = (await spawn.spawn(agentExecPath, ['ls', '--view', 'human', ':not(.dev)'], {
|
|
4855
5113
|
cwd
|
|
4856
5114
|
})).stdout;
|
|
@@ -4881,20 +5139,39 @@ async function lsYarnClassic(agentExecPath, cwd) {
|
|
|
4881
5139
|
} catch {}
|
|
4882
5140
|
return '';
|
|
4883
5141
|
}
|
|
4884
|
-
const lsByAgent =
|
|
4885
|
-
|
|
4886
|
-
|
|
4887
|
-
|
|
4888
|
-
|
|
4889
|
-
|
|
4890
|
-
|
|
4891
|
-
|
|
4892
|
-
|
|
4893
|
-
|
|
5142
|
+
const lsByAgent = new Map([[BUN$1, lsBun], [NPM$3, lsNpm], [PNPM$2, lsPnpm], [VLT$1, lsVlt], [YARN_BERRY$1, lsYarnBerry], [YARN_CLASSIC$2, lsYarnClassic]]);
|
|
5143
|
+
|
|
5144
|
+
const {
|
|
5145
|
+
NPM_BUGGY_OVERRIDES_PATCHED_VERSION
|
|
5146
|
+
} = constants;
|
|
5147
|
+
async function updateLockfile(pkgEnvDetails, options) {
|
|
5148
|
+
const {
|
|
5149
|
+
cmdName = '',
|
|
5150
|
+
logger,
|
|
5151
|
+
spinner
|
|
5152
|
+
} = {
|
|
5153
|
+
__proto__: null,
|
|
5154
|
+
...options
|
|
5155
|
+
};
|
|
5156
|
+
spinner?.start(`Updating ${pkgEnvDetails.lockName}...`);
|
|
5157
|
+
try {
|
|
5158
|
+
await runAgentInstall(pkgEnvDetails, {
|
|
5159
|
+
spinner
|
|
5160
|
+
});
|
|
5161
|
+
spinner?.stop();
|
|
5162
|
+
if (pkgEnvDetails.features.npmBuggyOverrides) {
|
|
5163
|
+
logger?.log(`💡 Re-run ${cmdName ? `${cmdName} ` : ''}whenever ${pkgEnvDetails.lockName} changes.\n This can be skipped for ${pkgEnvDetails.agent} >=${NPM_BUGGY_OVERRIDES_PATCHED_VERSION}.`);
|
|
5164
|
+
}
|
|
5165
|
+
} catch (e) {
|
|
5166
|
+
spinner?.stop();
|
|
5167
|
+
logger?.fail(cmdPrefixMessage(cmdName, `${pkgEnvDetails.agent} install failed to update ${pkgEnvDetails.lockName}`));
|
|
5168
|
+
logger?.error(e);
|
|
5169
|
+
}
|
|
5170
|
+
}
|
|
4894
5171
|
|
|
4895
5172
|
const {
|
|
4896
5173
|
BUN,
|
|
4897
|
-
NPM: NPM$
|
|
5174
|
+
NPM: NPM$2,
|
|
4898
5175
|
OVERRIDES,
|
|
4899
5176
|
PNPM: PNPM$1,
|
|
4900
5177
|
RESOLUTIONS,
|
|
@@ -4914,7 +5191,9 @@ function getHighestEntryIndex(entries, keys) {
|
|
|
4914
5191
|
return getEntryIndexes(entries, keys).at(-1) ?? -1;
|
|
4915
5192
|
}
|
|
4916
5193
|
function updatePkgJson(editablePkgJson, field, value) {
|
|
4917
|
-
const
|
|
5194
|
+
const {
|
|
5195
|
+
content: pkgJson
|
|
5196
|
+
} = editablePkgJson;
|
|
4918
5197
|
const oldValue = pkgJson[field];
|
|
4919
5198
|
if (oldValue) {
|
|
4920
5199
|
// The field already exists so we simply update the field value.
|
|
@@ -4998,177 +5277,15 @@ function updateResolutions(editablePkgJson, overrides) {
|
|
|
4998
5277
|
function pnpmUpdatePkgJson(editablePkgJson, overrides) {
|
|
4999
5278
|
updatePkgJson(editablePkgJson, PNPM_FIELD_NAME, overrides);
|
|
5000
5279
|
}
|
|
5001
|
-
const updateManifestByAgent = new Map([[BUN, updateResolutions], [NPM$
|
|
5002
|
-
|
|
5003
|
-
const {
|
|
5004
|
-
SOCKET_IPC_HANDSHAKE
|
|
5005
|
-
} = constants;
|
|
5006
|
-
function safeNpmInstall(options) {
|
|
5007
|
-
const {
|
|
5008
|
-
args = [],
|
|
5009
|
-
ipc,
|
|
5010
|
-
spinner,
|
|
5011
|
-
...spawnOptions
|
|
5012
|
-
} = {
|
|
5013
|
-
__proto__: null,
|
|
5014
|
-
...options
|
|
5015
|
-
};
|
|
5016
|
-
const terminatorPos = args.indexOf('--');
|
|
5017
|
-
const npmArgs = (terminatorPos === -1 ? args : args.slice(0, terminatorPos)).filter(a => !npm.isAuditFlag(a) && !npm.isFundFlag(a) && !npm.isProgressFlag(a));
|
|
5018
|
-
const otherArgs = terminatorPos === -1 ? [] : args.slice(terminatorPos);
|
|
5019
|
-
const useIpc = objects.isObject(ipc);
|
|
5020
|
-
const useDebug = debug.isDebug();
|
|
5021
|
-
const isSilent = !useDebug && !npmArgs.some(npm.isLoglevelFlag);
|
|
5022
|
-
const spawnPromise = spawn.spawn(
|
|
5023
|
-
// Lazily access constants.execPath.
|
|
5024
|
-
constants.execPath, [
|
|
5025
|
-
// Lazily access constants.nodeNoWarningsFlags.
|
|
5026
|
-
...constants.nodeNoWarningsFlags, '--require',
|
|
5027
|
-
// Lazily access constants.distShadowNpmInjectPath.
|
|
5028
|
-
constants.distShadowNpmInjectPath, shadowNpmPaths.getNpmBinPath(), 'install',
|
|
5029
|
-
// Even though the '--silent' flag is passed npm will still run through
|
|
5030
|
-
// code paths for 'audit' and 'fund' unless '--no-audit' and '--no-fund'
|
|
5031
|
-
// flags are passed.
|
|
5032
|
-
'--no-audit', '--no-fund',
|
|
5033
|
-
// Add `--no-progress` and `--silent` flags to fix input being swallowed
|
|
5034
|
-
// by the spinner when running the command with recent versions of npm.
|
|
5035
|
-
'--no-progress',
|
|
5036
|
-
// Add the '--silent' flag if a loglevel flag is not provided and the
|
|
5037
|
-
// SOCKET_CLI_DEBUG environment variable is not truthy.
|
|
5038
|
-
...(isSilent ? ['--silent'] : []), ...npmArgs, ...otherArgs], {
|
|
5039
|
-
spinner,
|
|
5040
|
-
// Set stdio to include 'ipc'.
|
|
5041
|
-
// See https://github.com/nodejs/node/blob/v23.6.0/lib/child_process.js#L161-L166
|
|
5042
|
-
// and https://github.com/nodejs/node/blob/v23.6.0/lib/internal/child_process.js#L238.
|
|
5043
|
-
stdio: isSilent ?
|
|
5044
|
-
// 'ignore'
|
|
5045
|
-
useIpc ? ['ignore', 'ignore', 'ignore', 'ipc'] : 'ignore' :
|
|
5046
|
-
// 'inherit'
|
|
5047
|
-
useIpc ? [0, 1, 2, 'ipc'] : 'inherit',
|
|
5048
|
-
...spawnOptions,
|
|
5049
|
-
env: {
|
|
5050
|
-
...process$1.env,
|
|
5051
|
-
...spawnOptions.env
|
|
5052
|
-
}
|
|
5053
|
-
});
|
|
5054
|
-
if (useIpc) {
|
|
5055
|
-
spawnPromise.process.send({
|
|
5056
|
-
[SOCKET_IPC_HANDSHAKE]: ipc
|
|
5057
|
-
});
|
|
5058
|
-
}
|
|
5059
|
-
return spawnPromise;
|
|
5060
|
-
}
|
|
5061
|
-
|
|
5062
|
-
const {
|
|
5063
|
-
NPM: NPM$3,
|
|
5064
|
-
abortSignal
|
|
5065
|
-
} = constants;
|
|
5066
|
-
function runAgentInstall(agent, agentExecPath, options) {
|
|
5067
|
-
// All package managers support the "install" command.
|
|
5068
|
-
if (agent === NPM$3) {
|
|
5069
|
-
return safeNpmInstall(options);
|
|
5070
|
-
}
|
|
5071
|
-
const {
|
|
5072
|
-
args = [],
|
|
5073
|
-
spinner,
|
|
5074
|
-
...spawnOptions
|
|
5075
|
-
} = {
|
|
5076
|
-
__proto__: null,
|
|
5077
|
-
...options
|
|
5078
|
-
};
|
|
5079
|
-
const isSilent = !debug.isDebug();
|
|
5080
|
-
return spawn.spawn(agentExecPath, ['install', ...args], {
|
|
5081
|
-
signal: abortSignal,
|
|
5082
|
-
spinner,
|
|
5083
|
-
stdio: isSilent ? 'ignore' : 'inherit',
|
|
5084
|
-
...spawnOptions,
|
|
5085
|
-
env: {
|
|
5086
|
-
...process.env,
|
|
5087
|
-
...spawnOptions.env
|
|
5088
|
-
}
|
|
5089
|
-
});
|
|
5090
|
-
}
|
|
5091
|
-
|
|
5092
|
-
const {
|
|
5093
|
-
NPM: NPM$2
|
|
5094
|
-
} = constants;
|
|
5095
|
-
const COMMAND_TITLE$1 = 'Socket Optimize';
|
|
5096
|
-
async function updatePackageLockJson(pkgEnvDetails, options) {
|
|
5097
|
-
const {
|
|
5098
|
-
logger,
|
|
5099
|
-
spinner
|
|
5100
|
-
} = {
|
|
5101
|
-
__proto__: null,
|
|
5102
|
-
...options
|
|
5103
|
-
};
|
|
5104
|
-
spinner?.start(`Updating ${pkgEnvDetails.lockName}...`);
|
|
5105
|
-
try {
|
|
5106
|
-
await runAgentInstall(pkgEnvDetails.agent, pkgEnvDetails.agentExecPath, {
|
|
5107
|
-
spinner
|
|
5108
|
-
});
|
|
5109
|
-
spinner?.stop();
|
|
5110
|
-
if (pkgEnvDetails.agent === NPM$2) {
|
|
5111
|
-
logger?.log(`💡 Re-run ${COMMAND_TITLE$1} whenever ${pkgEnvDetails.lockName} changes.\n This can be skipped once npm v11.2.0 is released.`);
|
|
5112
|
-
}
|
|
5113
|
-
} catch (e) {
|
|
5114
|
-
spinner?.stop();
|
|
5115
|
-
logger?.fail(`${COMMAND_TITLE$1}: ${pkgEnvDetails.agent} install failed to update ${pkgEnvDetails.lockName}`);
|
|
5116
|
-
logger?.error(e);
|
|
5117
|
-
}
|
|
5118
|
-
}
|
|
5280
|
+
const updateManifestByAgent = new Map([[BUN, updateResolutions], [NPM$2, updateOverrides], [PNPM$1, pnpmUpdatePkgJson], [VLT, updateOverrides], [YARN_BERRY, updateResolutions], [YARN_CLASSIC$1, updateResolutions]]);
|
|
5119
5281
|
|
|
5120
5282
|
const {
|
|
5121
5283
|
NPM: NPM$1,
|
|
5122
5284
|
PNPM,
|
|
5123
5285
|
YARN_CLASSIC
|
|
5124
5286
|
} = constants;
|
|
5125
|
-
const
|
|
5287
|
+
const CMD_NAME = 'socket optimize';
|
|
5126
5288
|
const manifestNpmOverrides = registry.getManifestData(NPM$1);
|
|
5127
|
-
async function applyOptimization(cwd, pin, prod) {
|
|
5128
|
-
const pkgEnvDetails = await detectAndValidatePackageEnvironment(cwd, {
|
|
5129
|
-
logger: logger.logger,
|
|
5130
|
-
prod
|
|
5131
|
-
});
|
|
5132
|
-
if (!pkgEnvDetails) {
|
|
5133
|
-
return;
|
|
5134
|
-
}
|
|
5135
|
-
// Lazily access constants.spinner.
|
|
5136
|
-
const {
|
|
5137
|
-
spinner
|
|
5138
|
-
} = constants;
|
|
5139
|
-
spinner.start('Socket optimizing...');
|
|
5140
|
-
const state = await addOverrides(pkgEnvDetails.pkgPath, pkgEnvDetails, {
|
|
5141
|
-
logger: logger.logger,
|
|
5142
|
-
pin,
|
|
5143
|
-
prod,
|
|
5144
|
-
spinner
|
|
5145
|
-
});
|
|
5146
|
-
spinner.stop();
|
|
5147
|
-
const addedCount = state.added.size;
|
|
5148
|
-
const updatedCount = state.updated.size;
|
|
5149
|
-
const pkgJsonChanged = addedCount > 0 || updatedCount > 0;
|
|
5150
|
-
if (pkgJsonChanged) {
|
|
5151
|
-
if (updatedCount > 0) {
|
|
5152
|
-
logger.logger?.log(`${createActionMessage('Updated', updatedCount, state.updatedInWorkspaces.size)}${addedCount ? '.' : '🚀'}`);
|
|
5153
|
-
}
|
|
5154
|
-
if (addedCount > 0) {
|
|
5155
|
-
logger.logger?.log(`${createActionMessage('Added', addedCount, state.addedInWorkspaces.size)} 🚀`);
|
|
5156
|
-
}
|
|
5157
|
-
} else {
|
|
5158
|
-
logger.logger?.log('Congratulations! Already Socket.dev optimized 🎉');
|
|
5159
|
-
}
|
|
5160
|
-
if (pkgEnvDetails.agent === NPM$1 || pkgJsonChanged) {
|
|
5161
|
-
// Always update package-lock.json until the npm overrides PR lands:
|
|
5162
|
-
// https://github.com/npm/cli/pull/8089
|
|
5163
|
-
await updatePackageLockJson(pkgEnvDetails, {
|
|
5164
|
-
logger: logger.logger,
|
|
5165
|
-
spinner
|
|
5166
|
-
});
|
|
5167
|
-
}
|
|
5168
|
-
}
|
|
5169
|
-
function createActionMessage(verb, overrideCount, workspaceCount) {
|
|
5170
|
-
return `${verb} ${overrideCount} Socket.dev optimized ${words.pluralize('override', overrideCount)}${workspaceCount ? ` in ${workspaceCount} ${words.pluralize('workspace', workspaceCount)}` : ''}`;
|
|
5171
|
-
}
|
|
5172
5289
|
async function addOverrides(pkgPath, pkgEnvDetails, options) {
|
|
5173
5290
|
const {
|
|
5174
5291
|
agent,
|
|
@@ -5212,16 +5329,16 @@ async function addOverrides(pkgPath, pkgEnvDetails, options) {
|
|
|
5212
5329
|
const isWorkspace = !!workspaceGlobs;
|
|
5213
5330
|
if (isWorkspace && agent === PNPM && npmExecPath === NPM$1 && !state.warnedPnpmWorkspaceRequiresNpm) {
|
|
5214
5331
|
state.warnedPnpmWorkspaceRequiresNpm = true;
|
|
5215
|
-
logger?.warn(
|
|
5332
|
+
logger?.warn(cmdPrefixMessage(CMD_NAME, 'pnpm workspace support requires `npm ls`, falling back to `pnpm list`'));
|
|
5216
5333
|
}
|
|
5217
|
-
const thingToScan = isLockScanned ? lockSrc : await lsByAgent
|
|
5334
|
+
const thingToScan = isLockScanned ? lockSrc : await lsByAgent.get(agent)(agentExecPath, pkgPath, {
|
|
5218
5335
|
npmExecPath
|
|
5219
5336
|
});
|
|
5220
5337
|
// The AgentDepsIncludesFn and AgentLockIncludesFn types overlap in their
|
|
5221
5338
|
// first two parameters. AgentLockIncludesFn accepts an optional third
|
|
5222
5339
|
// parameter which AgentDepsIncludesFn will ignore so we cast thingScanner
|
|
5223
5340
|
// as an AgentLockIncludesFn type.
|
|
5224
|
-
const thingScanner = isLockScanned ?
|
|
5341
|
+
const thingScanner = isLockScanned ? lockfileIncludesByAgent.get(agent) : depsIncludesByAgent.get(agent);
|
|
5225
5342
|
const depEntries = getDependencyEntries(pkgJson);
|
|
5226
5343
|
const overridesDataObjects = [];
|
|
5227
5344
|
if (pkgJson['private'] || isWorkspace) {
|
|
@@ -5347,6 +5464,51 @@ async function addOverrides(pkgPath, pkgEnvDetails, options) {
|
|
|
5347
5464
|
}
|
|
5348
5465
|
return state;
|
|
5349
5466
|
}
|
|
5467
|
+
function createActionMessage(verb, overrideCount, workspaceCount) {
|
|
5468
|
+
return `${verb} ${overrideCount} Socket.dev optimized ${words.pluralize('override', overrideCount)}${workspaceCount ? ` in ${workspaceCount} ${words.pluralize('workspace', workspaceCount)}` : ''}`;
|
|
5469
|
+
}
|
|
5470
|
+
async function applyOptimization(cwd, pin, prod) {
|
|
5471
|
+
const pkgEnvDetails = await detectAndValidatePackageEnvironment(cwd, {
|
|
5472
|
+
cmdName: CMD_NAME,
|
|
5473
|
+
logger: logger.logger,
|
|
5474
|
+
prod
|
|
5475
|
+
});
|
|
5476
|
+
if (!pkgEnvDetails) {
|
|
5477
|
+
return;
|
|
5478
|
+
}
|
|
5479
|
+
// Lazily access constants.spinner.
|
|
5480
|
+
const {
|
|
5481
|
+
spinner
|
|
5482
|
+
} = constants;
|
|
5483
|
+
spinner.start('Socket optimizing...');
|
|
5484
|
+
const state = await addOverrides(pkgEnvDetails.pkgPath, pkgEnvDetails, {
|
|
5485
|
+
logger: logger.logger,
|
|
5486
|
+
pin,
|
|
5487
|
+
prod,
|
|
5488
|
+
spinner
|
|
5489
|
+
});
|
|
5490
|
+
spinner.stop();
|
|
5491
|
+
const addedCount = state.added.size;
|
|
5492
|
+
const updatedCount = state.updated.size;
|
|
5493
|
+
const pkgJsonChanged = addedCount > 0 || updatedCount > 0;
|
|
5494
|
+
if (pkgJsonChanged) {
|
|
5495
|
+
if (updatedCount > 0) {
|
|
5496
|
+
logger.logger?.log(`${createActionMessage('Updated', updatedCount, state.updatedInWorkspaces.size)}${addedCount ? '.' : '🚀'}`);
|
|
5497
|
+
}
|
|
5498
|
+
if (addedCount > 0) {
|
|
5499
|
+
logger.logger?.log(`${createActionMessage('Added', addedCount, state.addedInWorkspaces.size)} 🚀`);
|
|
5500
|
+
}
|
|
5501
|
+
} else {
|
|
5502
|
+
logger.logger?.log('Congratulations! Already Socket.dev optimized 🎉');
|
|
5503
|
+
}
|
|
5504
|
+
if (pkgJsonChanged || pkgEnvDetails.features.npmBuggyOverrides) {
|
|
5505
|
+
await updateLockfile(pkgEnvDetails, {
|
|
5506
|
+
cmdName: CMD_NAME,
|
|
5507
|
+
logger: logger.logger,
|
|
5508
|
+
spinner
|
|
5509
|
+
});
|
|
5510
|
+
}
|
|
5511
|
+
}
|
|
5350
5512
|
|
|
5351
5513
|
const {
|
|
5352
5514
|
DRY_RUN_BAIL_TEXT: DRY_RUN_BAIL_TEXT$h
|
|
@@ -5727,8 +5889,8 @@ async function fetchReportData(reportId, includeAllIssues, strict) {
|
|
|
5727
5889
|
spinner.error('Report result deemed unhealthy for project');
|
|
5728
5890
|
}
|
|
5729
5891
|
} else if (!result.data.healthy) {
|
|
5730
|
-
const severityCount = getSeverityCount(result.data.issues, includeAllIssues ? undefined : 'high');
|
|
5731
|
-
const issueSummary = formatSeverityCount(severityCount);
|
|
5892
|
+
const severityCount = shadowNpmInject.getSeverityCount(result.data.issues, includeAllIssues ? undefined : 'high');
|
|
5893
|
+
const issueSummary = shadowNpmInject.formatSeverityCount(severityCount);
|
|
5732
5894
|
spinner.success(`Report has these issues: ${issueSummary}`);
|
|
5733
5895
|
} else {
|
|
5734
5896
|
spinner.success('Report has no issues');
|
|
@@ -7029,7 +7191,7 @@ async function run$6(argv, importMeta, {
|
|
|
7029
7191
|
});
|
|
7030
7192
|
const [orgSlug = '', ...targets] = cli.input;
|
|
7031
7193
|
const cwd = cli.flags['cwd'] && cli.flags['cwd'] !== 'process.cwd()' ? String(cli.flags['cwd']) : process$1.cwd();
|
|
7032
|
-
|
|
7194
|
+
const {
|
|
7033
7195
|
branch: branchName,
|
|
7034
7196
|
repo: repoName
|
|
7035
7197
|
} = cli.flags;
|
|
@@ -7624,11 +7786,36 @@ const cmdScan = {
|
|
|
7624
7786
|
}
|
|
7625
7787
|
};
|
|
7626
7788
|
|
|
7789
|
+
// Note: Widgets does not seem to actually work as code :'(
|
|
7790
|
+
|
|
7627
7791
|
async function getThreatFeed({
|
|
7792
|
+
direction,
|
|
7793
|
+
ecosystem,
|
|
7794
|
+
filter,
|
|
7795
|
+
outputKind,
|
|
7796
|
+
page,
|
|
7797
|
+
perPage
|
|
7798
|
+
}) {
|
|
7799
|
+
const apiToken = shadowNpmInject.getDefaultToken();
|
|
7800
|
+
if (!apiToken) {
|
|
7801
|
+
throw new shadowNpmInject.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
|
|
7802
|
+
}
|
|
7803
|
+
await getThreatFeedWithToken({
|
|
7804
|
+
apiToken,
|
|
7805
|
+
direction,
|
|
7806
|
+
ecosystem,
|
|
7807
|
+
filter,
|
|
7808
|
+
outputKind,
|
|
7809
|
+
page,
|
|
7810
|
+
perPage
|
|
7811
|
+
});
|
|
7812
|
+
}
|
|
7813
|
+
async function getThreatFeedWithToken({
|
|
7628
7814
|
apiToken,
|
|
7629
7815
|
direction,
|
|
7816
|
+
ecosystem,
|
|
7630
7817
|
filter,
|
|
7631
|
-
|
|
7818
|
+
outputKind,
|
|
7632
7819
|
page,
|
|
7633
7820
|
perPage
|
|
7634
7821
|
}) {
|
|
@@ -7636,17 +7823,12 @@ async function getThreatFeed({
|
|
|
7636
7823
|
const {
|
|
7637
7824
|
spinner
|
|
7638
7825
|
} = constants;
|
|
7639
|
-
|
|
7640
|
-
|
|
7641
|
-
|
|
7642
|
-
page,
|
|
7643
|
-
direction,
|
|
7644
|
-
filter
|
|
7645
|
-
}).join('&');
|
|
7646
|
-
const response = await queryAPI(`threat-feed?${formattedQueryParams}`, apiToken);
|
|
7826
|
+
const queryParams = new URLSearchParams([['direction', direction], ['ecosystem', ecosystem], ['filter', filter], ['page', page], ['per_page', String(perPage)]]);
|
|
7827
|
+
spinner.start('Fetching Threat Feed data...');
|
|
7828
|
+
const response = await queryAPI(`threat-feed?${queryParams}`, apiToken);
|
|
7647
7829
|
const data = await response.json();
|
|
7648
|
-
spinner.stop();
|
|
7649
|
-
if (
|
|
7830
|
+
spinner.stop('Threat feed data fetched');
|
|
7831
|
+
if (outputKind === 'json') {
|
|
7650
7832
|
logger.logger.log(data);
|
|
7651
7833
|
return;
|
|
7652
7834
|
}
|
|
@@ -7659,47 +7841,98 @@ async function getThreatFeed({
|
|
|
7659
7841
|
interactive: 'true',
|
|
7660
7842
|
label: 'Threat feed',
|
|
7661
7843
|
width: '100%',
|
|
7662
|
-
height: '
|
|
7844
|
+
height: '70%',
|
|
7845
|
+
// Changed from 100% to 70%
|
|
7663
7846
|
border: {
|
|
7664
7847
|
type: 'line',
|
|
7665
7848
|
fg: 'cyan'
|
|
7666
7849
|
},
|
|
7667
|
-
|
|
7668
|
-
//
|
|
7669
|
-
|
|
7850
|
+
columnWidth: [10, 30, 20, 18, 15, 200],
|
|
7851
|
+
// TODO: the truncation doesn't seem to work too well yet but when we add
|
|
7852
|
+
// `pad` alignment fails, when we extend columnSpacing alignment fails
|
|
7853
|
+
columnSpacing: 1,
|
|
7854
|
+
truncate: '_'
|
|
7855
|
+
});
|
|
7856
|
+
|
|
7857
|
+
// Create details box at the bottom
|
|
7858
|
+
const detailsBox = new BoxWidget({
|
|
7859
|
+
bottom: 0,
|
|
7860
|
+
height: '30%',
|
|
7861
|
+
width: '100%',
|
|
7862
|
+
border: {
|
|
7863
|
+
type: 'line',
|
|
7864
|
+
fg: 'cyan'
|
|
7865
|
+
},
|
|
7866
|
+
label: 'Details',
|
|
7867
|
+
content: 'Use arrow keys to navigate. Press Enter to select a threat. Press q to exit.',
|
|
7868
|
+
style: {
|
|
7869
|
+
fg: 'white'
|
|
7870
|
+
}
|
|
7670
7871
|
});
|
|
7671
7872
|
|
|
7672
7873
|
// allow control the table with the keyboard
|
|
7673
7874
|
table.focus();
|
|
7674
7875
|
screen.append(table);
|
|
7876
|
+
screen.append(detailsBox);
|
|
7675
7877
|
const formattedOutput = formatResults(data.results);
|
|
7878
|
+
const descriptions = data.results.map(d => d.description);
|
|
7676
7879
|
table.setData({
|
|
7677
|
-
headers: ['Ecosystem', 'Name', 'Version', 'Threat type', 'Detected at', 'Details'],
|
|
7880
|
+
headers: [' Ecosystem', ' Name', ' Version', ' Threat type', ' Detected at', ' Details'],
|
|
7678
7881
|
data: formattedOutput
|
|
7679
7882
|
});
|
|
7883
|
+
|
|
7884
|
+
// Update details box when selection changes
|
|
7885
|
+
table.rows.on('select item', () => {
|
|
7886
|
+
const selectedIndex = table.rows.selected;
|
|
7887
|
+
if (selectedIndex !== undefined && selectedIndex >= 0) {
|
|
7888
|
+
const selectedRow = formattedOutput[selectedIndex];
|
|
7889
|
+
if (selectedRow) {
|
|
7890
|
+
// Note: the spacing works around issues with the table; it refuses to pad!
|
|
7891
|
+
detailsBox.setContent(`Ecosystem: ${selectedRow[0]}\n` + `Name: ${selectedRow[1]}\n` + `Version:${selectedRow[2]}\n` + `Threat type:${selectedRow[3]}\n` + `Detected at:${selectedRow[4]}\n` + `Details: ${selectedRow[5]}\n` + `Description: ${descriptions[selectedIndex]}`);
|
|
7892
|
+
screen.render();
|
|
7893
|
+
}
|
|
7894
|
+
}
|
|
7895
|
+
});
|
|
7680
7896
|
screen.render();
|
|
7681
7897
|
screen.key(['escape', 'q', 'C-c'], () => process$1.exit(0));
|
|
7898
|
+
screen.key(['return'], () => {
|
|
7899
|
+
const selectedIndex = table.rows.selected;
|
|
7900
|
+
screen.destroy();
|
|
7901
|
+
const selectedRow = formattedOutput[selectedIndex];
|
|
7902
|
+
console.log(selectedRow);
|
|
7903
|
+
});
|
|
7682
7904
|
}
|
|
7683
7905
|
function formatResults(data) {
|
|
7684
7906
|
return data.map(d => {
|
|
7685
7907
|
const ecosystem = d.purl.split('pkg:')[1].split('/')[0];
|
|
7686
7908
|
const name = d.purl.split('/')[1].split('@')[0];
|
|
7687
7909
|
const version = d.purl.split('@')[1];
|
|
7688
|
-
const
|
|
7689
|
-
|
|
7690
|
-
|
|
7691
|
-
|
|
7692
|
-
return [ecosystem, decodeURIComponent(name), version, d.threatType, hourDiff, d.locationHtmlUrl];
|
|
7910
|
+
const timeDiff = msAtHome(d.createdAt);
|
|
7911
|
+
|
|
7912
|
+
// Note: the spacing works around issues with the table; it refuses to pad!
|
|
7913
|
+
return [ecosystem, decodeURIComponent(name), ` ${version}`, ` ${d.threatType}`, ` ${timeDiff}`, d.locationHtmlUrl];
|
|
7693
7914
|
});
|
|
7694
7915
|
}
|
|
7695
|
-
function
|
|
7696
|
-
|
|
7697
|
-
|
|
7698
|
-
|
|
7699
|
-
|
|
7700
|
-
|
|
7701
|
-
|
|
7702
|
-
|
|
7916
|
+
function msAtHome(isoTimeStamp) {
|
|
7917
|
+
const timeStart = Date.parse(isoTimeStamp);
|
|
7918
|
+
const timeEnd = Date.now();
|
|
7919
|
+
const rtf = new Intl.RelativeTimeFormat('en', {
|
|
7920
|
+
numeric: 'always',
|
|
7921
|
+
style: 'short'
|
|
7922
|
+
});
|
|
7923
|
+
const delta = timeEnd - timeStart;
|
|
7924
|
+
if (delta < 60 * 60 * 1000) {
|
|
7925
|
+
return rtf.format(-Math.round(delta / (60 * 1000)), 'minute');
|
|
7926
|
+
// return Math.round(delta / (60 * 1000)) + ' min ago'
|
|
7927
|
+
} else if (delta < 24 * 60 * 60 * 1000) {
|
|
7928
|
+
return rtf.format(-(delta / (60 * 60 * 1000)).toFixed(1), 'hour');
|
|
7929
|
+
// return (delta / (60 * 60 * 1000)).toFixed(1) + ' hr ago'
|
|
7930
|
+
} else if (delta < 7 * 24 * 60 * 60 * 1000) {
|
|
7931
|
+
return rtf.format(-(delta / (24 * 60 * 60 * 1000)).toFixed(1), 'day');
|
|
7932
|
+
// return (delta / (24 * 60 * 60 * 1000)).toFixed(1) + ' day ago'
|
|
7933
|
+
} else {
|
|
7934
|
+
return isoTimeStamp.slice(0, 10);
|
|
7935
|
+
}
|
|
7703
7936
|
}
|
|
7704
7937
|
|
|
7705
7938
|
const {
|
|
@@ -7707,7 +7940,7 @@ const {
|
|
|
7707
7940
|
} = constants;
|
|
7708
7941
|
const config$1 = {
|
|
7709
7942
|
commandName: 'threat-feed',
|
|
7710
|
-
description: '
|
|
7943
|
+
description: '[beta] View the threat feed',
|
|
7711
7944
|
hidden: false,
|
|
7712
7945
|
flags: {
|
|
7713
7946
|
...commonFlags,
|
|
@@ -7730,6 +7963,12 @@ const config$1 = {
|
|
|
7730
7963
|
default: 'desc',
|
|
7731
7964
|
description: 'Order asc or desc by the createdAt attribute.'
|
|
7732
7965
|
},
|
|
7966
|
+
eco: {
|
|
7967
|
+
type: 'string',
|
|
7968
|
+
shortFlag: 'e',
|
|
7969
|
+
default: '',
|
|
7970
|
+
description: 'Only show threats for a particular ecosystem'
|
|
7971
|
+
},
|
|
7733
7972
|
filter: {
|
|
7734
7973
|
type: 'string',
|
|
7735
7974
|
shortFlag: 'f',
|
|
@@ -7741,9 +7980,35 @@ const config$1 = {
|
|
|
7741
7980
|
Usage
|
|
7742
7981
|
$ ${command}
|
|
7743
7982
|
|
|
7983
|
+
This feature requires a Threat Feed license. Please contact
|
|
7984
|
+
sales@socket.dev if you are interested in purchasing this access.
|
|
7985
|
+
|
|
7744
7986
|
Options
|
|
7745
7987
|
${getFlagListOutput(config.flags, 6)}
|
|
7746
7988
|
|
|
7989
|
+
Valid filters:
|
|
7990
|
+
|
|
7991
|
+
- anom Anomaly
|
|
7992
|
+
- c Do not filter
|
|
7993
|
+
- fp False Positives
|
|
7994
|
+
- joke Joke / Fake
|
|
7995
|
+
- mal Malware and Possible Malware [default]
|
|
7996
|
+
- secret Secrets
|
|
7997
|
+
- spy Telemetry
|
|
7998
|
+
- tp False Positives and Unreviewed
|
|
7999
|
+
- typo Typo-squat
|
|
8000
|
+
- u Unreviewed
|
|
8001
|
+
- vuln Vulnerability
|
|
8002
|
+
|
|
8003
|
+
Valid ecosystems:
|
|
8004
|
+
|
|
8005
|
+
- gem
|
|
8006
|
+
- golang
|
|
8007
|
+
- maven
|
|
8008
|
+
- npm
|
|
8009
|
+
- nuget
|
|
8010
|
+
- pypi
|
|
8011
|
+
|
|
7747
8012
|
Examples
|
|
7748
8013
|
$ ${command}
|
|
7749
8014
|
$ ${command} --perPage=5 --page=2 --direction=asc --filter=joke
|
|
@@ -7767,17 +8032,13 @@ async function run$1(argv, importMeta, {
|
|
|
7767
8032
|
logger.logger.log(DRY_RUN_BAIL_TEXT$1);
|
|
7768
8033
|
return;
|
|
7769
8034
|
}
|
|
7770
|
-
const apiToken = shadowNpmInject.getDefaultToken();
|
|
7771
|
-
if (!apiToken) {
|
|
7772
|
-
throw new shadowNpmInject.AuthError('User must be authenticated to run this command. To log in, run the command `socket login` and enter your API key.');
|
|
7773
|
-
}
|
|
7774
8035
|
await getThreatFeed({
|
|
7775
|
-
apiToken,
|
|
7776
8036
|
direction: String(cli.flags['direction'] || 'desc'),
|
|
8037
|
+
ecosystem: String(cli.flags['eco'] || ''),
|
|
7777
8038
|
filter: String(cli.flags['filter'] || 'mal'),
|
|
7778
|
-
|
|
7779
|
-
page: String(cli.flags['
|
|
7780
|
-
perPage: Number(cli.flags['
|
|
8039
|
+
outputKind: cli.flags['json'] ? 'json' : cli.flags['markdown'] ? 'markdown' : 'print',
|
|
8040
|
+
page: String(cli.flags['page'] || '1'),
|
|
8041
|
+
perPage: Number(cli.flags['perPage']) || 30
|
|
7781
8042
|
});
|
|
7782
8043
|
}
|
|
7783
8044
|
|
|
@@ -7979,14 +8240,14 @@ async function run(argv, importMeta, {
|
|
|
7979
8240
|
}
|
|
7980
8241
|
|
|
7981
8242
|
const {
|
|
7982
|
-
|
|
8243
|
+
SOCKET_CLI_BIN_NAME,
|
|
7983
8244
|
rootPkgJsonPath
|
|
7984
8245
|
} = constants;
|
|
7985
8246
|
|
|
7986
8247
|
// TODO: Add autocompletion using https://socket.dev/npm/package/omelette
|
|
7987
8248
|
void (async () => {
|
|
7988
8249
|
await updateNotifier({
|
|
7989
|
-
name:
|
|
8250
|
+
name: SOCKET_CLI_BIN_NAME,
|
|
7990
8251
|
version: require(rootPkgJsonPath).version,
|
|
7991
8252
|
ttl: 86_400_000 /* 24 hours in milliseconds */
|
|
7992
8253
|
});
|
|
@@ -8023,7 +8284,7 @@ void (async () => {
|
|
|
8023
8284
|
}
|
|
8024
8285
|
},
|
|
8025
8286
|
argv: process$1.argv.slice(2),
|
|
8026
|
-
name:
|
|
8287
|
+
name: SOCKET_CLI_BIN_NAME,
|
|
8027
8288
|
importMeta: {
|
|
8028
8289
|
url: `${node_url.pathToFileURL(__filename)}`
|
|
8029
8290
|
}
|
|
@@ -8047,12 +8308,12 @@ void (async () => {
|
|
|
8047
8308
|
} else {
|
|
8048
8309
|
errorTitle = 'Unexpected error with no details';
|
|
8049
8310
|
}
|
|
8050
|
-
logger.logger.fail(`${colors.bgRed(colors.white(errorTitle
|
|
8311
|
+
logger.logger.fail(`${colors.bgRed(colors.white(`${errorTitle}:`))} ${errorMessage}`);
|
|
8051
8312
|
if (errorBody) {
|
|
8052
8313
|
logger.logger.error(`\n${errorBody}`);
|
|
8053
8314
|
}
|
|
8054
8315
|
await shadowNpmInject.captureException(e);
|
|
8055
8316
|
}
|
|
8056
8317
|
})();
|
|
8057
|
-
//# debugId=
|
|
8318
|
+
//# debugId=c1c67343-d5ad-409c-8f8e-9236e0fb545a
|
|
8058
8319
|
//# sourceMappingURL=cli.js.map
|