@socketsecurity/cli-with-sentry 0.14.130 → 0.14.132
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 +37 -44
- package/bin/npx-cli.js +1 -3
- package/dist/{module-sync/cli.js → cli.js} +55 -36
- package/dist/cli.js.map +1 -0
- package/dist/constants.js +8 -25
- package/dist/constants.js.map +1 -1
- package/dist/instrument-with-sentry.js +3 -14
- package/dist/instrument-with-sentry.js.map +1 -1
- package/dist/{module-sync/shadow-bin.js → shadow-bin.js} +52 -1
- package/dist/shadow-bin.js.map +1 -0
- package/dist/{module-sync/shadow-npm-inject.js → shadow-npm-inject.js} +60 -16
- package/dist/shadow-npm-inject.js.map +1 -0
- package/dist/shadow-npm-paths.js.map +1 -0
- package/dist/{module-sync/vendor.js → vendor.js} +10320 -4778
- package/dist/vendor.js.map +1 -0
- package/package.json +16 -26
- package/dist/constants.d.ts +0 -285
- package/dist/instrument-with-sentry.d.ts +0 -1
- package/dist/module-sync/arborist-helpers.d.ts +0 -68
- package/dist/module-sync/artifact.d.ts +0 -63
- package/dist/module-sync/cli.d.ts +0 -2
- package/dist/module-sync/cli.js.map +0 -1
- package/dist/module-sync/cmd.d.ts +0 -4
- package/dist/module-sync/config.d.ts +0 -44
- package/dist/module-sync/constants.js +0 -3
- package/dist/module-sync/edge.d.ts +0 -78
- package/dist/module-sync/errors.d.ts +0 -29
- package/dist/module-sync/fs.d.ts +0 -63
- package/dist/module-sync/index.d.ts +0 -34
- package/dist/module-sync/node.d.ts +0 -121
- package/dist/module-sync/override-set.d.ts +0 -43
- package/dist/module-sync/package-environment.d.ts +0 -83
- package/dist/module-sync/path-resolve.d.ts +0 -15
- package/dist/module-sync/sdk.d.ts +0 -9
- package/dist/module-sync/semver.d.ts +0 -17
- package/dist/module-sync/shadow-bin.d.ts +0 -5
- package/dist/module-sync/shadow-bin.js.map +0 -1
- package/dist/module-sync/shadow-npm-inject.d.ts +0 -1
- package/dist/module-sync/shadow-npm-inject.js.map +0 -1
- package/dist/module-sync/shadow-npm-paths.d.ts +0 -27
- package/dist/module-sync/shadow-npm-paths.js.map +0 -1
- package/dist/module-sync/socket-package-alert.d.ts +0 -104
- package/dist/module-sync/vendor.d.ts +0 -0
- package/dist/module-sync/vendor.js.map +0 -1
- package/dist/require/cli.d.ts +0 -2
- package/dist/require/cli.js +0 -12340
- package/dist/require/cli.js.map +0 -1
- package/dist/require/constants.js +0 -3
- package/dist/require/shadow-bin.d.ts +0 -5
- package/dist/require/shadow-bin.js +0 -110
- package/dist/require/shadow-bin.js.map +0 -1
- package/dist/require/shadow-npm-inject.d.ts +0 -1
- package/dist/require/shadow-npm-inject.js +0 -2596
- package/dist/require/shadow-npm-inject.js.map +0 -1
- package/dist/require/shadow-npm-paths.d.ts +0 -27
- package/dist/require/shadow-npm-paths.js +0 -292
- package/dist/require/shadow-npm-paths.js.map +0 -1
- package/dist/require/vendor.js +0 -3
- /package/dist/{module-sync/shadow-npm-paths.js → shadow-npm-paths.js} +0 -0
|
@@ -1,2596 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const shadowNpmPaths = require('./shadow-npm-paths.js')
|
|
4
|
-
const process$1 = require('node:process')
|
|
5
|
-
const vendor = require('./vendor.js')
|
|
6
|
-
const logger = require('@socketsecurity/registry/lib/logger')
|
|
7
|
-
const constants = require('./constants.js')
|
|
8
|
-
const arrays = require('@socketsecurity/registry/lib/arrays')
|
|
9
|
-
const packageurlJs = require('@socketregistry/packageurl-js')
|
|
10
|
-
const registry = require('@socketsecurity/registry')
|
|
11
|
-
const debug = require('@socketsecurity/registry/lib/debug')
|
|
12
|
-
const objects = require('@socketsecurity/registry/lib/objects')
|
|
13
|
-
const isInteractive = require('@socketregistry/is-interactive/index.cjs')
|
|
14
|
-
const registryConstants = require('@socketsecurity/registry/lib/constants')
|
|
15
|
-
const prompts = require('@socketsecurity/registry/lib/prompts')
|
|
16
|
-
const strings = require('@socketsecurity/registry/lib/strings')
|
|
17
|
-
const sdk = require('@socketsecurity/sdk')
|
|
18
|
-
const fs = require('node:fs')
|
|
19
|
-
const os = require('node:os')
|
|
20
|
-
const path = require('node:path')
|
|
21
|
-
const fs$1 = require('@socketsecurity/registry/lib/fs')
|
|
22
|
-
const packages = require('@socketsecurity/registry/lib/packages')
|
|
23
|
-
const promises = require('node:timers/promises')
|
|
24
|
-
const sorts = require('@socketsecurity/registry/lib/sorts')
|
|
25
|
-
const indentString = require('@socketregistry/indent-string/index.cjs')
|
|
26
|
-
|
|
27
|
-
const { NPM: NPM$3, PNPM } = constants
|
|
28
|
-
const PNPM_WORKSPACE = `${PNPM}-workspace`
|
|
29
|
-
const ignoredDirs = [
|
|
30
|
-
// Taken from ignore-by-default:
|
|
31
|
-
// https://github.com/novemberborn/ignore-by-default/blob/v2.1.0/index.js
|
|
32
|
-
'.git',
|
|
33
|
-
// Git repository files, see <https://git-scm.com/>
|
|
34
|
-
'.log',
|
|
35
|
-
// Log files emitted by tools such as `tsserver`, see <https://github.com/Microsoft/TypeScript/wiki/Standalone-Server-%28tsserver%29>
|
|
36
|
-
'.nyc_output',
|
|
37
|
-
// Temporary directory where nyc stores coverage data, see <https://github.com/bcoe/nyc>
|
|
38
|
-
'.sass-cache',
|
|
39
|
-
// Cache folder for node-sass, see <https://github.com/sass/node-sass>
|
|
40
|
-
'.yarn',
|
|
41
|
-
// Where node modules are installed when using Yarn, see <https://yarnpkg.com/>
|
|
42
|
-
'bower_components',
|
|
43
|
-
// Where Bower packages are installed, see <http://bower.io/>
|
|
44
|
-
'coverage',
|
|
45
|
-
// Standard output directory for code coverage reports, see <https://github.com/gotwarlost/istanbul>
|
|
46
|
-
'node_modules',
|
|
47
|
-
// Where Node modules are installed, see <https://nodejs.org/>
|
|
48
|
-
// Taken from globby:
|
|
49
|
-
// https://github.com/sindresorhus/globby/blob/v14.0.2/ignore.js#L11-L16
|
|
50
|
-
'flow-typed'
|
|
51
|
-
]
|
|
52
|
-
const ignoredDirPatterns = ignoredDirs.map(i => `**/${i}`)
|
|
53
|
-
async function getWorkspaceGlobs(agent, cwd = process$1.cwd()) {
|
|
54
|
-
let workspacePatterns
|
|
55
|
-
if (agent === PNPM) {
|
|
56
|
-
for (const workspacePath of [
|
|
57
|
-
path.join(cwd, `${PNPM_WORKSPACE}.yaml`),
|
|
58
|
-
path.join(cwd, `${PNPM_WORKSPACE}.yml`)
|
|
59
|
-
]) {
|
|
60
|
-
// eslint-disable-next-line no-await-in-loop
|
|
61
|
-
const yml = await safeReadFile(workspacePath)
|
|
62
|
-
if (yml) {
|
|
63
|
-
try {
|
|
64
|
-
workspacePatterns = vendor.distExports$1.parse(yml)?.packages
|
|
65
|
-
} catch {}
|
|
66
|
-
if (workspacePatterns) {
|
|
67
|
-
break
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
} else {
|
|
72
|
-
workspacePatterns = (
|
|
73
|
-
await packages.readPackageJson(cwd, {
|
|
74
|
-
throws: false
|
|
75
|
-
})
|
|
76
|
-
)?.['workspaces']
|
|
77
|
-
}
|
|
78
|
-
return Array.isArray(workspacePatterns)
|
|
79
|
-
? workspacePatterns
|
|
80
|
-
.filter(strings.isNonEmptyString)
|
|
81
|
-
.map(workspacePatternToGlobPattern)
|
|
82
|
-
: []
|
|
83
|
-
}
|
|
84
|
-
function ignoreFileLinesToGlobPatterns(lines, filepath, cwd) {
|
|
85
|
-
const base = path.relative(cwd, path.dirname(filepath)).replace(/\\/g, '/')
|
|
86
|
-
const patterns = []
|
|
87
|
-
for (let i = 0, { length } = lines; i < length; i += 1) {
|
|
88
|
-
const pattern = lines[i].trim()
|
|
89
|
-
if (pattern.length > 0 && pattern.charCodeAt(0) !== 35 /*'#'*/) {
|
|
90
|
-
patterns.push(
|
|
91
|
-
ignorePatternToMinimatch(
|
|
92
|
-
pattern.length && pattern.charCodeAt(0) === 33 /*'!'*/
|
|
93
|
-
? `!${path.posix.join(base, pattern.slice(1))}`
|
|
94
|
-
: path.posix.join(base, pattern)
|
|
95
|
-
)
|
|
96
|
-
)
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
return patterns
|
|
100
|
-
}
|
|
101
|
-
function ignoreFileToGlobPatterns(content, filepath, cwd) {
|
|
102
|
-
return ignoreFileLinesToGlobPatterns(content.split(/\r?\n/), filepath, cwd)
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Based on `@eslint/compat` convertIgnorePatternToMinimatch.
|
|
106
|
-
// Apache v2.0 licensed
|
|
107
|
-
// Copyright Nicholas C. Zakas
|
|
108
|
-
// https://github.com/eslint/rewrite/blob/compat-v1.2.1/packages/compat/src/ignore-file.js#L28
|
|
109
|
-
function ignorePatternToMinimatch(pattern) {
|
|
110
|
-
const isNegated = pattern.startsWith('!')
|
|
111
|
-
const negatedPrefix = isNegated ? '!' : ''
|
|
112
|
-
const patternToTest = (isNegated ? pattern.slice(1) : pattern).trimEnd()
|
|
113
|
-
// Special cases.
|
|
114
|
-
if (
|
|
115
|
-
patternToTest === '' ||
|
|
116
|
-
patternToTest === '**' ||
|
|
117
|
-
patternToTest === '/**' ||
|
|
118
|
-
patternToTest === '**'
|
|
119
|
-
) {
|
|
120
|
-
return `${negatedPrefix}${patternToTest}`
|
|
121
|
-
}
|
|
122
|
-
const firstIndexOfSlash = patternToTest.indexOf('/')
|
|
123
|
-
const matchEverywherePrefix =
|
|
124
|
-
firstIndexOfSlash === -1 || firstIndexOfSlash === patternToTest.length - 1
|
|
125
|
-
? '**/'
|
|
126
|
-
: ''
|
|
127
|
-
const patternWithoutLeadingSlash =
|
|
128
|
-
firstIndexOfSlash === 0 ? patternToTest.slice(1) : patternToTest
|
|
129
|
-
// Escape `{` and `(` because in gitignore patterns they are just
|
|
130
|
-
// literal characters without any specific syntactic meaning,
|
|
131
|
-
// while in minimatch patterns they can form brace expansion or extglob syntax.
|
|
132
|
-
//
|
|
133
|
-
// For example, gitignore pattern `src/{a,b}.js` ignores file `src/{a,b}.js`.
|
|
134
|
-
// But, the same minimatch pattern `src/{a,b}.js` ignores files `src/a.js` and `src/b.js`.
|
|
135
|
-
// Minimatch pattern `src/\{a,b}.js` is equivalent to gitignore pattern `src/{a,b}.js`.
|
|
136
|
-
const escapedPatternWithoutLeadingSlash =
|
|
137
|
-
patternWithoutLeadingSlash.replaceAll(
|
|
138
|
-
/(?=((?:\\.|[^{(])*))\1([{(])/guy,
|
|
139
|
-
'$1\\$2'
|
|
140
|
-
)
|
|
141
|
-
const matchInsideSuffix = patternToTest.endsWith('/**') ? '/*' : ''
|
|
142
|
-
return `${negatedPrefix}${matchEverywherePrefix}${escapedPatternWithoutLeadingSlash}${matchInsideSuffix}`
|
|
143
|
-
}
|
|
144
|
-
function workspacePatternToGlobPattern(workspace) {
|
|
145
|
-
const { length } = workspace
|
|
146
|
-
if (!length) {
|
|
147
|
-
return ''
|
|
148
|
-
}
|
|
149
|
-
// If the workspace ends with "/"
|
|
150
|
-
if (workspace.charCodeAt(length - 1) === 47 /*'/'*/) {
|
|
151
|
-
return `${workspace}/*/package.json`
|
|
152
|
-
}
|
|
153
|
-
// If the workspace ends with "/**"
|
|
154
|
-
if (
|
|
155
|
-
workspace.charCodeAt(length - 1) === 42 /*'*'*/ &&
|
|
156
|
-
workspace.charCodeAt(length - 2) === 42 /*'*'*/ &&
|
|
157
|
-
workspace.charCodeAt(length - 3) === 47 /*'/'*/
|
|
158
|
-
) {
|
|
159
|
-
return `${workspace}/*/**/package.json`
|
|
160
|
-
}
|
|
161
|
-
// Things like "packages/a" or "packages/*"
|
|
162
|
-
return `${workspace}/package.json`
|
|
163
|
-
}
|
|
164
|
-
async function filterGlobResultToSupportedFiles(entries, supportedFiles) {
|
|
165
|
-
const patterns = ['golang', NPM$3, 'maven', 'pypi', 'gem', 'nuget'].reduce(
|
|
166
|
-
(r, n) => {
|
|
167
|
-
const supported = supportedFiles[n]
|
|
168
|
-
r.push(
|
|
169
|
-
...(supported
|
|
170
|
-
? Object.values(supported).map(p => `**/${p.pattern}`)
|
|
171
|
-
: [])
|
|
172
|
-
)
|
|
173
|
-
return r
|
|
174
|
-
},
|
|
175
|
-
[]
|
|
176
|
-
)
|
|
177
|
-
return entries.filter(p => vendor.micromatchExports.some(p, patterns))
|
|
178
|
-
}
|
|
179
|
-
async function globWithGitIgnore(patterns, options) {
|
|
180
|
-
const {
|
|
181
|
-
cwd = process$1.cwd(),
|
|
182
|
-
socketConfig,
|
|
183
|
-
...additionalOptions
|
|
184
|
-
} = {
|
|
185
|
-
__proto__: null,
|
|
186
|
-
...options
|
|
187
|
-
}
|
|
188
|
-
const projectIgnorePaths = socketConfig?.projectIgnorePaths
|
|
189
|
-
const ignoreFiles = await vendor.distExports.glob(['**/.gitignore'], {
|
|
190
|
-
absolute: true,
|
|
191
|
-
cwd,
|
|
192
|
-
expandDirectories: true
|
|
193
|
-
})
|
|
194
|
-
const ignores = [
|
|
195
|
-
...ignoredDirPatterns,
|
|
196
|
-
...(Array.isArray(projectIgnorePaths)
|
|
197
|
-
? ignoreFileLinesToGlobPatterns(
|
|
198
|
-
projectIgnorePaths,
|
|
199
|
-
path.join(cwd, '.gitignore'),
|
|
200
|
-
cwd
|
|
201
|
-
)
|
|
202
|
-
: []),
|
|
203
|
-
...(
|
|
204
|
-
await Promise.all(
|
|
205
|
-
ignoreFiles.map(async filepath =>
|
|
206
|
-
ignoreFileToGlobPatterns(
|
|
207
|
-
await fs.promises.readFile(filepath, 'utf8'),
|
|
208
|
-
filepath,
|
|
209
|
-
cwd
|
|
210
|
-
)
|
|
211
|
-
)
|
|
212
|
-
)
|
|
213
|
-
).flat()
|
|
214
|
-
]
|
|
215
|
-
const hasNegatedPattern = ignores.some(p => p.charCodeAt(0) === 33 /*'!'*/)
|
|
216
|
-
const globOptions = {
|
|
217
|
-
absolute: true,
|
|
218
|
-
cwd,
|
|
219
|
-
expandDirectories: false,
|
|
220
|
-
ignore: hasNegatedPattern ? [] : ignores,
|
|
221
|
-
...additionalOptions
|
|
222
|
-
}
|
|
223
|
-
const result = await vendor.distExports.glob(patterns, globOptions)
|
|
224
|
-
if (!hasNegatedPattern) {
|
|
225
|
-
return result
|
|
226
|
-
}
|
|
227
|
-
const { absolute } = globOptions
|
|
228
|
-
|
|
229
|
-
// Note: the input files must be INSIDE the cwd. If you get strange looking
|
|
230
|
-
// relative path errors here, most likely your path is outside the given cwd.
|
|
231
|
-
const filtered = vendor
|
|
232
|
-
.ignoreExports()
|
|
233
|
-
.add(ignores)
|
|
234
|
-
.filter(absolute ? result.map(p => path.relative(cwd, p)) : result)
|
|
235
|
-
return absolute ? filtered.map(p => path.resolve(cwd, p)) : filtered
|
|
236
|
-
}
|
|
237
|
-
async function globNodeModules(cwd = process$1.cwd()) {
|
|
238
|
-
return await vendor.distExports.glob('**/node_modules/**', {
|
|
239
|
-
absolute: true,
|
|
240
|
-
cwd
|
|
241
|
-
})
|
|
242
|
-
}
|
|
243
|
-
async function globWorkspace(agent, cwd = process$1.cwd()) {
|
|
244
|
-
const workspaceGlobs = await getWorkspaceGlobs(agent, cwd)
|
|
245
|
-
return workspaceGlobs.length
|
|
246
|
-
? await vendor.distExports.glob(workspaceGlobs, {
|
|
247
|
-
absolute: true,
|
|
248
|
-
cwd,
|
|
249
|
-
ignore: ['**/node_modules/**', '**/bower_components/**']
|
|
250
|
-
})
|
|
251
|
-
: []
|
|
252
|
-
}
|
|
253
|
-
function pathsToGlobPatterns(paths) {
|
|
254
|
-
// TODO: Does not support `~/` paths.
|
|
255
|
-
return paths.map(p => (p === '.' || p === './' ? '**/*' : p))
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
const { abortSignal } = constants
|
|
259
|
-
async function removeNodeModules(cwd = process$1.cwd()) {
|
|
260
|
-
const nodeModulesPaths = await globNodeModules(cwd)
|
|
261
|
-
await Promise.all(nodeModulesPaths.map(p => fs$1.remove(p)))
|
|
262
|
-
}
|
|
263
|
-
async function findUp(name, { cwd = process$1.cwd(), signal = abortSignal }) {
|
|
264
|
-
let dir = path.resolve(cwd)
|
|
265
|
-
const { root } = path.parse(dir)
|
|
266
|
-
const names = [name].flat()
|
|
267
|
-
while (dir && dir !== root) {
|
|
268
|
-
for (const name of names) {
|
|
269
|
-
if (signal?.aborted) {
|
|
270
|
-
return undefined
|
|
271
|
-
}
|
|
272
|
-
const filePath = path.join(dir, name)
|
|
273
|
-
try {
|
|
274
|
-
// eslint-disable-next-line no-await-in-loop
|
|
275
|
-
const stats = await fs.promises.stat(filePath)
|
|
276
|
-
if (stats.isFile()) {
|
|
277
|
-
return filePath
|
|
278
|
-
}
|
|
279
|
-
} catch {}
|
|
280
|
-
}
|
|
281
|
-
dir = path.dirname(dir)
|
|
282
|
-
}
|
|
283
|
-
return undefined
|
|
284
|
-
}
|
|
285
|
-
async function readFileBinary(filepath, options) {
|
|
286
|
-
return await fs.promises.readFile(filepath, {
|
|
287
|
-
signal: abortSignal,
|
|
288
|
-
...options,
|
|
289
|
-
encoding: 'binary'
|
|
290
|
-
})
|
|
291
|
-
}
|
|
292
|
-
async function readFileUtf8(filepath, options) {
|
|
293
|
-
return await fs.promises.readFile(filepath, {
|
|
294
|
-
signal: abortSignal,
|
|
295
|
-
...options,
|
|
296
|
-
encoding: 'utf8'
|
|
297
|
-
})
|
|
298
|
-
}
|
|
299
|
-
async function safeReadFile(filepath, options) {
|
|
300
|
-
try {
|
|
301
|
-
return await fs.promises.readFile(filepath, {
|
|
302
|
-
encoding: 'utf8',
|
|
303
|
-
signal: abortSignal,
|
|
304
|
-
...(typeof options === 'string'
|
|
305
|
-
? {
|
|
306
|
-
encoding: options
|
|
307
|
-
}
|
|
308
|
-
: options)
|
|
309
|
-
})
|
|
310
|
-
} catch {}
|
|
311
|
-
return undefined
|
|
312
|
-
}
|
|
313
|
-
function safeReadFileSync(filepath, options) {
|
|
314
|
-
try {
|
|
315
|
-
return fs.readFileSync(filepath, {
|
|
316
|
-
encoding: 'utf8',
|
|
317
|
-
...(typeof options === 'string'
|
|
318
|
-
? {
|
|
319
|
-
encoding: options
|
|
320
|
-
}
|
|
321
|
-
: options)
|
|
322
|
-
})
|
|
323
|
-
} catch {}
|
|
324
|
-
return undefined
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
const { LOCALAPPDATA, SOCKET_APP_DIR, XDG_DATA_HOME } = constants
|
|
328
|
-
const supportedConfigKeys = new Map([
|
|
329
|
-
['apiBaseUrl', 'Base URL of the API endpoint'],
|
|
330
|
-
['apiProxy', 'A proxy through which to access the API'],
|
|
331
|
-
['apiToken', 'The API token required to access most API endpoints'],
|
|
332
|
-
[
|
|
333
|
-
'defaultOrg',
|
|
334
|
-
'The default org slug to use; usually the org your API token has access to. When set, all orgSlug arguments are implied to be this value.'
|
|
335
|
-
],
|
|
336
|
-
[
|
|
337
|
-
'enforcedOrgs',
|
|
338
|
-
'Orgs in this list have their security policies enforced on this machine'
|
|
339
|
-
]
|
|
340
|
-
])
|
|
341
|
-
const sensitiveConfigKeys = new Set(['apiToken'])
|
|
342
|
-
let _cachedConfig
|
|
343
|
-
// When using --config or SOCKET_CLI_CONFIG, do not persist the config.
|
|
344
|
-
let _readOnlyConfig = false
|
|
345
|
-
function overrideCachedConfig(jsonConfig) {
|
|
346
|
-
debug.debugLog('Overriding entire config, marking config as read-only')
|
|
347
|
-
let config
|
|
348
|
-
try {
|
|
349
|
-
config = JSON.parse(String(jsonConfig))
|
|
350
|
-
if (!config || typeof config !== 'object') {
|
|
351
|
-
// Just throw to reuse the error message. `null` is valid json,
|
|
352
|
-
// so are primitive values. They're not valid config objects :)
|
|
353
|
-
throw new Error()
|
|
354
|
-
}
|
|
355
|
-
} catch {
|
|
356
|
-
return {
|
|
357
|
-
ok: false,
|
|
358
|
-
message:
|
|
359
|
-
"Could not JSON parse the config override. Make sure it's a proper JSON object (double-quoted keys and strings, no unquoted `undefined`) and try again."
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
// @ts-ignore Override an illegal object.
|
|
364
|
-
_cachedConfig = config
|
|
365
|
-
_readOnlyConfig = true
|
|
366
|
-
|
|
367
|
-
// Normalize apiKey to apiToken.
|
|
368
|
-
if (_cachedConfig['apiKey']) {
|
|
369
|
-
if (_cachedConfig['apiToken']) {
|
|
370
|
-
logger.logger.warn(
|
|
371
|
-
'Note: The config override had both apiToken and apiKey. Using the apiToken value. Remove the apiKey to get rid of this message.'
|
|
372
|
-
)
|
|
373
|
-
}
|
|
374
|
-
_cachedConfig['apiToken'] = _cachedConfig['apiKey']
|
|
375
|
-
delete _cachedConfig['apiKey']
|
|
376
|
-
}
|
|
377
|
-
return {
|
|
378
|
-
ok: true,
|
|
379
|
-
message: undefined
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
function overrideConfigApiToken(apiToken) {
|
|
383
|
-
debug.debugLog('Overriding API token, marking config as read-only')
|
|
384
|
-
// Set token to the local cached config and mark it read-only so it doesn't persist
|
|
385
|
-
_cachedConfig = {
|
|
386
|
-
...vendor.configExports,
|
|
387
|
-
...(apiToken === undefined
|
|
388
|
-
? {}
|
|
389
|
-
: {
|
|
390
|
-
apiToken: String(apiToken)
|
|
391
|
-
})
|
|
392
|
-
}
|
|
393
|
-
_readOnlyConfig = true
|
|
394
|
-
}
|
|
395
|
-
function getConfigValues() {
|
|
396
|
-
if (_cachedConfig === undefined) {
|
|
397
|
-
_cachedConfig = {}
|
|
398
|
-
// Order: env var > --config flag > file
|
|
399
|
-
const configPath = getConfigPath()
|
|
400
|
-
if (configPath) {
|
|
401
|
-
const raw = safeReadFileSync(configPath)
|
|
402
|
-
if (raw) {
|
|
403
|
-
try {
|
|
404
|
-
Object.assign(
|
|
405
|
-
_cachedConfig,
|
|
406
|
-
JSON.parse(Buffer.from(raw, 'base64').toString())
|
|
407
|
-
)
|
|
408
|
-
} catch {
|
|
409
|
-
logger.logger.warn(`Failed to parse config at ${configPath}`)
|
|
410
|
-
}
|
|
411
|
-
// Normalize apiKey to apiToken and persist it.
|
|
412
|
-
// This is a one time migration per user.
|
|
413
|
-
if (_cachedConfig['apiKey']) {
|
|
414
|
-
const token = _cachedConfig['apiKey']
|
|
415
|
-
delete _cachedConfig['apiKey']
|
|
416
|
-
updateConfigValue('apiToken', token)
|
|
417
|
-
}
|
|
418
|
-
} else {
|
|
419
|
-
fs.mkdirSync(path.dirname(configPath), {
|
|
420
|
-
recursive: true
|
|
421
|
-
})
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
return _cachedConfig
|
|
426
|
-
}
|
|
427
|
-
let _configPath
|
|
428
|
-
let _warnedConfigPathWin32Missing = false
|
|
429
|
-
function getConfigPath() {
|
|
430
|
-
// Get the OS app data folder:
|
|
431
|
-
// - Win: %LOCALAPPDATA% or fail?
|
|
432
|
-
// - Mac: %XDG_DATA_HOME% or fallback to "~/Library/Application Support/"
|
|
433
|
-
// - Linux: %XDG_DATA_HOME% or fallback to "~/.local/share/"
|
|
434
|
-
// Note: LOCALAPPDATA is typically: C:\Users\USERNAME\AppData
|
|
435
|
-
// Note: XDG stands for "X Desktop Group", nowadays "freedesktop.org"
|
|
436
|
-
// On most systems that path is: $HOME/.local/share
|
|
437
|
-
// Then append `socket/settings`, so:
|
|
438
|
-
// - Win: %LOCALAPPDATA%\socket\settings or return undefined
|
|
439
|
-
// - Mac: %XDG_DATA_HOME%/socket/settings or "~/Library/Application Support/socket/settings"
|
|
440
|
-
// - Linux: %XDG_DATA_HOME%/socket/settings or "~/.local/share/socket/settings"
|
|
441
|
-
|
|
442
|
-
if (_configPath === undefined) {
|
|
443
|
-
// Lazily access constants.WIN32.
|
|
444
|
-
const { WIN32 } = constants
|
|
445
|
-
let dataHome = WIN32
|
|
446
|
-
? // Lazily access constants.ENV[LOCALAPPDATA]
|
|
447
|
-
constants.ENV[LOCALAPPDATA]
|
|
448
|
-
: // Lazily access constants.ENV[XDG_DATA_HOME]
|
|
449
|
-
constants.ENV[XDG_DATA_HOME]
|
|
450
|
-
if (!dataHome) {
|
|
451
|
-
if (WIN32) {
|
|
452
|
-
if (!_warnedConfigPathWin32Missing) {
|
|
453
|
-
_warnedConfigPathWin32Missing = true
|
|
454
|
-
logger.logger.warn(`Missing %${LOCALAPPDATA}%`)
|
|
455
|
-
}
|
|
456
|
-
} else {
|
|
457
|
-
dataHome = path.join(
|
|
458
|
-
os.homedir(),
|
|
459
|
-
...(process$1.platform === 'darwin'
|
|
460
|
-
? ['Library', 'Application Support']
|
|
461
|
-
: ['.local', 'share'])
|
|
462
|
-
)
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
_configPath = dataHome ? path.join(dataHome, SOCKET_APP_DIR) : undefined
|
|
466
|
-
}
|
|
467
|
-
return _configPath
|
|
468
|
-
}
|
|
469
|
-
function normalizeConfigKey(key) {
|
|
470
|
-
// Note: apiKey was the old name of the token. When we load a config with
|
|
471
|
-
// property apiKey, we'll copy that to apiToken and delete the old property.
|
|
472
|
-
const normalizedKey = key === 'apiKey' ? 'apiToken' : key
|
|
473
|
-
if (!supportedConfigKeys.has(normalizedKey)) {
|
|
474
|
-
throw new Error(`Invalid config key: ${normalizedKey}`)
|
|
475
|
-
}
|
|
476
|
-
return normalizedKey
|
|
477
|
-
}
|
|
478
|
-
function findSocketYmlSync(dir = process$1.cwd()) {
|
|
479
|
-
let prevDir = null
|
|
480
|
-
while (dir !== prevDir) {
|
|
481
|
-
let ymlPath = path.join(dir, 'socket.yml')
|
|
482
|
-
let yml = safeReadFileSync(ymlPath)
|
|
483
|
-
if (yml === undefined) {
|
|
484
|
-
ymlPath = path.join(dir, 'socket.yaml')
|
|
485
|
-
yml = safeReadFileSync(ymlPath)
|
|
486
|
-
}
|
|
487
|
-
if (typeof yml === 'string') {
|
|
488
|
-
try {
|
|
489
|
-
return {
|
|
490
|
-
path: ymlPath,
|
|
491
|
-
parsed: vendor.configExports.parseSocketConfig(yml)
|
|
492
|
-
}
|
|
493
|
-
} catch {
|
|
494
|
-
throw new Error(`Found file but was unable to parse ${ymlPath}`)
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
prevDir = dir
|
|
498
|
-
dir = path.join(dir, '..')
|
|
499
|
-
}
|
|
500
|
-
return null
|
|
501
|
-
}
|
|
502
|
-
function getConfigValue(key) {
|
|
503
|
-
const localConfig = getConfigValues()
|
|
504
|
-
return localConfig[normalizeConfigKey(key)]
|
|
505
|
-
}
|
|
506
|
-
function isReadOnlyConfig() {
|
|
507
|
-
return _readOnlyConfig
|
|
508
|
-
}
|
|
509
|
-
let _pendingSave = false
|
|
510
|
-
function updateConfigValue(key, value) {
|
|
511
|
-
const localConfig = getConfigValues()
|
|
512
|
-
localConfig[normalizeConfigKey(key)] = value
|
|
513
|
-
if (_readOnlyConfig) {
|
|
514
|
-
logger.logger.warn(
|
|
515
|
-
'Not persisting config change; current config overridden through env var or flag'
|
|
516
|
-
)
|
|
517
|
-
} else if (!_pendingSave) {
|
|
518
|
-
_pendingSave = true
|
|
519
|
-
process$1.nextTick(() => {
|
|
520
|
-
_pendingSave = false
|
|
521
|
-
const configPath = getConfigPath()
|
|
522
|
-
if (configPath) {
|
|
523
|
-
fs.writeFileSync(
|
|
524
|
-
configPath,
|
|
525
|
-
Buffer.from(JSON.stringify(localConfig)).toString('base64')
|
|
526
|
-
)
|
|
527
|
-
}
|
|
528
|
-
})
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
const {
|
|
533
|
-
kInternalsSymbol: kInternalsSymbol$1,
|
|
534
|
-
[kInternalsSymbol$1]: { getSentry }
|
|
535
|
-
} = constants
|
|
536
|
-
class AuthError extends Error {}
|
|
537
|
-
class InputError extends Error {
|
|
538
|
-
constructor(message, body) {
|
|
539
|
-
super(message)
|
|
540
|
-
this.body = body
|
|
541
|
-
}
|
|
542
|
-
}
|
|
543
|
-
async function captureException(exception, hint) {
|
|
544
|
-
const result = captureExceptionSync(exception, hint)
|
|
545
|
-
// "Sleep" for a second, just in case, hopefully enough time to initiate fetch.
|
|
546
|
-
await promises.setTimeout(1000)
|
|
547
|
-
return result
|
|
548
|
-
}
|
|
549
|
-
function captureExceptionSync(exception, hint) {
|
|
550
|
-
const Sentry = getSentry()
|
|
551
|
-
if (!Sentry) {
|
|
552
|
-
return ''
|
|
553
|
-
}
|
|
554
|
-
debug.debugLog('captureException: Sending exception to Sentry')
|
|
555
|
-
return Sentry.captureException(exception, hint)
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
const {
|
|
559
|
-
SOCKET_CLI_NO_API_TOKEN,
|
|
560
|
-
SOCKET_SECURITY_API_BASE_URL,
|
|
561
|
-
SOCKET_SECURITY_API_PROXY,
|
|
562
|
-
SOCKET_SECURITY_API_TOKEN
|
|
563
|
-
} = constants
|
|
564
|
-
|
|
565
|
-
// The API server that should be used for operations.
|
|
566
|
-
function getDefaultApiBaseUrl() {
|
|
567
|
-
const baseUrl =
|
|
568
|
-
// Lazily access constants.ENV[SOCKET_SECURITY_API_BASE_URL].
|
|
569
|
-
constants.ENV[SOCKET_SECURITY_API_BASE_URL] || getConfigValue('apiBaseUrl')
|
|
570
|
-
return strings.isNonEmptyString(baseUrl) ? baseUrl : undefined
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
// The API server that should be used for operations.
|
|
574
|
-
function getDefaultHttpProxy() {
|
|
575
|
-
const apiProxy =
|
|
576
|
-
// Lazily access constants.ENV[SOCKET_SECURITY_API_PROXY].
|
|
577
|
-
constants.ENV[SOCKET_SECURITY_API_PROXY] || getConfigValue('apiProxy')
|
|
578
|
-
return strings.isNonEmptyString(apiProxy) ? apiProxy : undefined
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
// This API key should be stored globally for the duration of the CLI execution.
|
|
582
|
-
let _defaultToken
|
|
583
|
-
function getDefaultToken() {
|
|
584
|
-
// Lazily access constants.ENV[SOCKET_CLI_NO_API_TOKEN].
|
|
585
|
-
if (constants.ENV[SOCKET_CLI_NO_API_TOKEN]) {
|
|
586
|
-
_defaultToken = undefined
|
|
587
|
-
} else {
|
|
588
|
-
const key =
|
|
589
|
-
// Lazily access constants.ENV[SOCKET_SECURITY_API_TOKEN].
|
|
590
|
-
constants.ENV[SOCKET_SECURITY_API_TOKEN] ||
|
|
591
|
-
getConfigValue('apiToken') ||
|
|
592
|
-
_defaultToken
|
|
593
|
-
_defaultToken = strings.isNonEmptyString(key) ? key : undefined
|
|
594
|
-
}
|
|
595
|
-
return _defaultToken
|
|
596
|
-
}
|
|
597
|
-
function getPublicToken() {
|
|
598
|
-
return (
|
|
599
|
-
// Lazily access constants.ENV[SOCKET_SECURITY_API_TOKEN].
|
|
600
|
-
(constants.ENV[SOCKET_SECURITY_API_TOKEN] || getDefaultToken()) ??
|
|
601
|
-
registryConstants.SOCKET_PUBLIC_API_TOKEN
|
|
602
|
-
)
|
|
603
|
-
}
|
|
604
|
-
async function setupSdk(
|
|
605
|
-
apiToken = getDefaultToken(),
|
|
606
|
-
apiBaseUrl = getDefaultApiBaseUrl(),
|
|
607
|
-
proxy = getDefaultHttpProxy()
|
|
608
|
-
) {
|
|
609
|
-
if (typeof apiToken !== 'string' && isInteractive()) {
|
|
610
|
-
apiToken = await prompts.password({
|
|
611
|
-
message:
|
|
612
|
-
'Enter your Socket.dev API key (not saved, use socket login to persist)'
|
|
613
|
-
})
|
|
614
|
-
_defaultToken = apiToken
|
|
615
|
-
}
|
|
616
|
-
if (!apiToken) {
|
|
617
|
-
throw new AuthError('You need to provide an API key')
|
|
618
|
-
}
|
|
619
|
-
return new sdk.SocketSdk(apiToken, {
|
|
620
|
-
agent: proxy
|
|
621
|
-
? new vendor.HttpsProxyAgent({
|
|
622
|
-
proxy
|
|
623
|
-
})
|
|
624
|
-
: undefined,
|
|
625
|
-
baseUrl: apiBaseUrl,
|
|
626
|
-
userAgent: sdk.createUserAgentFromPkgJson({
|
|
627
|
-
// The '@rollup/plugin-replace' will replace "process.env['INLINED_SOCKET_CLI_NAME']".
|
|
628
|
-
name: '@socketsecurity/cli',
|
|
629
|
-
// The '@rollup/plugin-replace' will replace "process.env['INLINED_SOCKET_CLI_VERSION']".
|
|
630
|
-
version: '0.14.130',
|
|
631
|
-
// The '@rollup/plugin-replace' will replace "process.env['INLINED_SOCKET_CLI_HOMEPAGE']".
|
|
632
|
-
homepage: 'https://github.com/SocketDev/socket-cli'
|
|
633
|
-
})
|
|
634
|
-
})
|
|
635
|
-
}
|
|
636
|
-
|
|
637
|
-
const RangeStyles = ['caret', 'gt', 'lt', 'pin', 'preserve', 'tilde']
|
|
638
|
-
function applyRange(refRange, version, style = 'preserve') {
|
|
639
|
-
switch (style) {
|
|
640
|
-
case 'caret':
|
|
641
|
-
return `^${version}`
|
|
642
|
-
case 'gt':
|
|
643
|
-
return `>${version}`
|
|
644
|
-
case 'gte':
|
|
645
|
-
return `>=${version}`
|
|
646
|
-
case 'lt':
|
|
647
|
-
return `<${version}`
|
|
648
|
-
case 'lte':
|
|
649
|
-
return `<=${version}`
|
|
650
|
-
case 'preserve': {
|
|
651
|
-
const comparators = [
|
|
652
|
-
...new vendor.semverExports.Range(refRange).set
|
|
653
|
-
].flat()
|
|
654
|
-
const { length } = comparators
|
|
655
|
-
return !length || length > 1
|
|
656
|
-
? version
|
|
657
|
-
: `${comparators[0].operator}${version}`
|
|
658
|
-
}
|
|
659
|
-
case 'tilde':
|
|
660
|
-
return `~${version}`
|
|
661
|
-
case 'pin':
|
|
662
|
-
default:
|
|
663
|
-
return version
|
|
664
|
-
}
|
|
665
|
-
}
|
|
666
|
-
function getMajor(version) {
|
|
667
|
-
const coerced = vendor.semverExports.coerce(version)
|
|
668
|
-
if (coerced) {
|
|
669
|
-
try {
|
|
670
|
-
return vendor.semverExports.major(coerced)
|
|
671
|
-
} catch (e) {
|
|
672
|
-
debug.debugLog(`Error parsing '${version}'`, e)
|
|
673
|
-
}
|
|
674
|
-
}
|
|
675
|
-
return null
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
const DiffAction = /*#__PURE__*/ (function (DiffAction) {
|
|
679
|
-
DiffAction['add'] = 'ADD'
|
|
680
|
-
DiffAction['change'] = 'CHANGE'
|
|
681
|
-
DiffAction['remove'] = 'REMOVE'
|
|
682
|
-
return DiffAction
|
|
683
|
-
})({})
|
|
684
|
-
|
|
685
|
-
const depValid = require(shadowNpmPaths.getArboristDepValidPath())
|
|
686
|
-
|
|
687
|
-
const { UNDEFINED_TOKEN } = constants
|
|
688
|
-
function tryRequire(req, ...ids) {
|
|
689
|
-
for (const data of ids) {
|
|
690
|
-
let id
|
|
691
|
-
let transformer
|
|
692
|
-
if (Array.isArray(data)) {
|
|
693
|
-
id = data[0]
|
|
694
|
-
transformer = data[1]
|
|
695
|
-
} else {
|
|
696
|
-
id = data
|
|
697
|
-
transformer = mod => mod
|
|
698
|
-
}
|
|
699
|
-
try {
|
|
700
|
-
// Check that the transformed value isn't `undefined` because older
|
|
701
|
-
// versions of packages like 'proc-log' may not export a `log` method.
|
|
702
|
-
const exported = transformer(req(id))
|
|
703
|
-
if (exported !== undefined) {
|
|
704
|
-
return exported
|
|
705
|
-
}
|
|
706
|
-
} catch {}
|
|
707
|
-
}
|
|
708
|
-
return undefined
|
|
709
|
-
}
|
|
710
|
-
let _log = UNDEFINED_TOKEN
|
|
711
|
-
function getLogger() {
|
|
712
|
-
if (_log === UNDEFINED_TOKEN) {
|
|
713
|
-
_log = tryRequire(
|
|
714
|
-
shadowNpmPaths.getNpmRequire(),
|
|
715
|
-
[
|
|
716
|
-
'proc-log/lib/index.js',
|
|
717
|
-
// The proc-log DefinitelyTyped definition is incorrect. The type definition
|
|
718
|
-
// is really that of its export log.
|
|
719
|
-
mod => mod.log
|
|
720
|
-
],
|
|
721
|
-
'npmlog/lib/log.js'
|
|
722
|
-
)
|
|
723
|
-
}
|
|
724
|
-
return _log
|
|
725
|
-
}
|
|
726
|
-
|
|
727
|
-
const OverrideSet = require(shadowNpmPaths.getArboristOverrideSetClassPath())
|
|
728
|
-
|
|
729
|
-
// Implementation code not related to patch https://github.com/npm/cli/pull/8089
|
|
730
|
-
// is based on https://github.com/npm/cli/blob/v11.0.0/workspaces/arborist/lib/override-set.js:
|
|
731
|
-
class SafeOverrideSet extends OverrideSet {
|
|
732
|
-
// Patch adding doOverrideSetsConflict is based on
|
|
733
|
-
// https://github.com/npm/cli/pull/8089.
|
|
734
|
-
static doOverrideSetsConflict(first, second) {
|
|
735
|
-
// If override sets contain one another then we can try to use the more
|
|
736
|
-
// specific one. If neither one is more specific, then we consider them to
|
|
737
|
-
// be in conflict.
|
|
738
|
-
return this.findSpecificOverrideSet(first, second) === undefined
|
|
739
|
-
}
|
|
740
|
-
|
|
741
|
-
// Patch adding findSpecificOverrideSet is based on
|
|
742
|
-
// https://github.com/npm/cli/pull/8089.
|
|
743
|
-
static findSpecificOverrideSet(first, second) {
|
|
744
|
-
for (
|
|
745
|
-
let overrideSet = second;
|
|
746
|
-
overrideSet;
|
|
747
|
-
overrideSet = overrideSet.parent
|
|
748
|
-
) {
|
|
749
|
-
if (overrideSet.isEqual(first)) {
|
|
750
|
-
return second
|
|
751
|
-
}
|
|
752
|
-
}
|
|
753
|
-
for (
|
|
754
|
-
let overrideSet = first;
|
|
755
|
-
overrideSet;
|
|
756
|
-
overrideSet = overrideSet.parent
|
|
757
|
-
) {
|
|
758
|
-
if (overrideSet.isEqual(second)) {
|
|
759
|
-
return first
|
|
760
|
-
}
|
|
761
|
-
}
|
|
762
|
-
// The override sets are incomparable. Neither one contains the other.
|
|
763
|
-
const log = getLogger()
|
|
764
|
-
log?.silly('Conflicting override sets', first, second)
|
|
765
|
-
return undefined
|
|
766
|
-
}
|
|
767
|
-
|
|
768
|
-
// Patch adding childrenAreEqual is based on
|
|
769
|
-
// https://github.com/npm/cli/pull/8089.
|
|
770
|
-
childrenAreEqual(otherOverrideSet) {
|
|
771
|
-
if (this.children.size !== otherOverrideSet.children.size) {
|
|
772
|
-
return false
|
|
773
|
-
}
|
|
774
|
-
for (const { 0: key, 1: childOverrideSet } of this.children) {
|
|
775
|
-
const otherChildOverrideSet = otherOverrideSet.children.get(key)
|
|
776
|
-
if (!otherChildOverrideSet) {
|
|
777
|
-
return false
|
|
778
|
-
}
|
|
779
|
-
if (childOverrideSet.value !== otherChildOverrideSet.value) {
|
|
780
|
-
return false
|
|
781
|
-
}
|
|
782
|
-
if (!childOverrideSet.childrenAreEqual(otherChildOverrideSet)) {
|
|
783
|
-
return false
|
|
784
|
-
}
|
|
785
|
-
}
|
|
786
|
-
return true
|
|
787
|
-
}
|
|
788
|
-
getEdgeRule(edge) {
|
|
789
|
-
for (const rule of this.ruleset.values()) {
|
|
790
|
-
if (rule.name !== edge.name) {
|
|
791
|
-
continue
|
|
792
|
-
}
|
|
793
|
-
// If keySpec is * we found our override.
|
|
794
|
-
if (rule.keySpec === '*') {
|
|
795
|
-
return rule
|
|
796
|
-
}
|
|
797
|
-
// Patch replacing
|
|
798
|
-
// let spec = npa(`${edge.name}@${edge.spec}`)
|
|
799
|
-
// is based on https://github.com/npm/cli/pull/8089.
|
|
800
|
-
//
|
|
801
|
-
// We need to use the rawSpec here, because the spec has the overrides
|
|
802
|
-
// applied to it already. The rawSpec can be undefined, so we need to use
|
|
803
|
-
// the fallback value of spec if it is.
|
|
804
|
-
let spec = vendor.npaExports(`${edge.name}@${edge.rawSpec || edge.spec}`)
|
|
805
|
-
if (spec.type === 'alias') {
|
|
806
|
-
spec = spec.subSpec
|
|
807
|
-
}
|
|
808
|
-
if (spec.type === 'git') {
|
|
809
|
-
if (
|
|
810
|
-
spec.gitRange &&
|
|
811
|
-
vendor.semverExports.intersects(spec.gitRange, rule.keySpec)
|
|
812
|
-
) {
|
|
813
|
-
return rule
|
|
814
|
-
}
|
|
815
|
-
continue
|
|
816
|
-
}
|
|
817
|
-
if (spec.type === 'range' || spec.type === 'version') {
|
|
818
|
-
if (vendor.semverExports.intersects(spec.fetchSpec, rule.keySpec)) {
|
|
819
|
-
return rule
|
|
820
|
-
}
|
|
821
|
-
continue
|
|
822
|
-
}
|
|
823
|
-
// If we got this far, the spec type is one of tag, directory or file
|
|
824
|
-
// which means we have no real way to make version comparisons, so we
|
|
825
|
-
// just accept the override.
|
|
826
|
-
return rule
|
|
827
|
-
}
|
|
828
|
-
return this
|
|
829
|
-
}
|
|
830
|
-
|
|
831
|
-
// Patch adding isEqual is based on
|
|
832
|
-
// https://github.com/npm/cli/pull/8089.
|
|
833
|
-
isEqual(otherOverrideSet) {
|
|
834
|
-
if (this === otherOverrideSet) {
|
|
835
|
-
return true
|
|
836
|
-
}
|
|
837
|
-
if (!otherOverrideSet) {
|
|
838
|
-
return false
|
|
839
|
-
}
|
|
840
|
-
if (
|
|
841
|
-
this.key !== otherOverrideSet.key ||
|
|
842
|
-
this.value !== otherOverrideSet.value
|
|
843
|
-
) {
|
|
844
|
-
return false
|
|
845
|
-
}
|
|
846
|
-
if (!this.childrenAreEqual(otherOverrideSet)) {
|
|
847
|
-
return false
|
|
848
|
-
}
|
|
849
|
-
if (!this.parent) {
|
|
850
|
-
return !otherOverrideSet.parent
|
|
851
|
-
}
|
|
852
|
-
return this.parent.isEqual(otherOverrideSet.parent)
|
|
853
|
-
}
|
|
854
|
-
}
|
|
855
|
-
|
|
856
|
-
const Node = require(shadowNpmPaths.getArboristNodeClassPath())
|
|
857
|
-
|
|
858
|
-
// Implementation code not related to patch https://github.com/npm/cli/pull/8089
|
|
859
|
-
// is based on https://github.com/npm/cli/blob/v11.0.0/workspaces/arborist/lib/node.js:
|
|
860
|
-
class SafeNode extends Node {
|
|
861
|
-
// Return true if it's safe to remove this node, because anything that is
|
|
862
|
-
// depending on it would be fine with the thing that they would resolve to if
|
|
863
|
-
// it was removed, or nothing is depending on it in the first place.
|
|
864
|
-
canDedupe(preferDedupe = false) {
|
|
865
|
-
// Not allowed to mess with shrinkwraps or bundles.
|
|
866
|
-
if (this.inDepBundle || this.inShrinkwrap) {
|
|
867
|
-
return false
|
|
868
|
-
}
|
|
869
|
-
// It's a top level pkg, or a dep of one.
|
|
870
|
-
if (!this.resolveParent?.resolveParent) {
|
|
871
|
-
return false
|
|
872
|
-
}
|
|
873
|
-
// No one wants it, remove it.
|
|
874
|
-
if (this.edgesIn.size === 0) {
|
|
875
|
-
return true
|
|
876
|
-
}
|
|
877
|
-
const other = this.resolveParent.resolveParent.resolve(this.name)
|
|
878
|
-
// Nothing else, need this one.
|
|
879
|
-
if (!other) {
|
|
880
|
-
return false
|
|
881
|
-
}
|
|
882
|
-
// If it's the same thing, then always fine to remove.
|
|
883
|
-
if (other.matches(this)) {
|
|
884
|
-
return true
|
|
885
|
-
}
|
|
886
|
-
// If the other thing can't replace this, then skip it.
|
|
887
|
-
if (!other.canReplace(this)) {
|
|
888
|
-
return false
|
|
889
|
-
}
|
|
890
|
-
// Patch replacing
|
|
891
|
-
// if (preferDedupe || semver.gte(other.version, this.version)) {
|
|
892
|
-
// return true
|
|
893
|
-
// }
|
|
894
|
-
// is based on https://github.com/npm/cli/pull/8089.
|
|
895
|
-
//
|
|
896
|
-
// If we prefer dedupe, or if the version is equal, take the other.
|
|
897
|
-
if (preferDedupe || vendor.semverExports.eq(other.version, this.version)) {
|
|
898
|
-
return true
|
|
899
|
-
}
|
|
900
|
-
// If our current version isn't the result of an override, then prefer to
|
|
901
|
-
// take the greater version.
|
|
902
|
-
if (
|
|
903
|
-
!this.overridden &&
|
|
904
|
-
vendor.semverExports.gt(other.version, this.version)
|
|
905
|
-
) {
|
|
906
|
-
return true
|
|
907
|
-
}
|
|
908
|
-
return false
|
|
909
|
-
}
|
|
910
|
-
|
|
911
|
-
// Is it safe to replace one node with another? check the edges to
|
|
912
|
-
// make sure no one will get upset. Note that the node might end up
|
|
913
|
-
// having its own unmet dependencies, if the new node has new deps.
|
|
914
|
-
// Note that there are cases where Arborist will opt to insert a node
|
|
915
|
-
// into the tree even though this function returns false! This is
|
|
916
|
-
// necessary when a root dependency is added or updated, or when a
|
|
917
|
-
// root dependency brings peer deps along with it. In that case, we
|
|
918
|
-
// will go ahead and create the invalid state, and then try to resolve
|
|
919
|
-
// it with more tree construction, because it's a user request.
|
|
920
|
-
canReplaceWith(node, ignorePeers) {
|
|
921
|
-
if (this.name !== node.name || this.packageName !== node.packageName) {
|
|
922
|
-
return false
|
|
923
|
-
}
|
|
924
|
-
// Patch replacing
|
|
925
|
-
// if (node.overrides !== this.overrides) {
|
|
926
|
-
// return false
|
|
927
|
-
// }
|
|
928
|
-
// is based on https://github.com/npm/cli/pull/8089.
|
|
929
|
-
//
|
|
930
|
-
// If this node has no dependencies, then it's irrelevant to check the
|
|
931
|
-
// override rules of the replacement node.
|
|
932
|
-
if (this.edgesOut.size) {
|
|
933
|
-
// XXX need to check for two root nodes?
|
|
934
|
-
if (node.overrides) {
|
|
935
|
-
if (!node.overrides.isEqual(this.overrides)) {
|
|
936
|
-
return false
|
|
937
|
-
}
|
|
938
|
-
} else {
|
|
939
|
-
if (this.overrides) {
|
|
940
|
-
return false
|
|
941
|
-
}
|
|
942
|
-
}
|
|
943
|
-
}
|
|
944
|
-
// To satisfy the patch we ensure `node.overrides === this.overrides`
|
|
945
|
-
// so that the condition we want to replace,
|
|
946
|
-
// if (this.overrides !== node.overrides) {
|
|
947
|
-
// , is not hit.`
|
|
948
|
-
const oldOverrideSet = this.overrides
|
|
949
|
-
let result = true
|
|
950
|
-
if (oldOverrideSet !== node.overrides) {
|
|
951
|
-
this.overrides = node.overrides
|
|
952
|
-
}
|
|
953
|
-
try {
|
|
954
|
-
result = super.canReplaceWith(node, ignorePeers)
|
|
955
|
-
this.overrides = oldOverrideSet
|
|
956
|
-
} catch (e) {
|
|
957
|
-
this.overrides = oldOverrideSet
|
|
958
|
-
throw e
|
|
959
|
-
}
|
|
960
|
-
return result
|
|
961
|
-
}
|
|
962
|
-
|
|
963
|
-
// Patch adding deleteEdgeIn is based on https://github.com/npm/cli/pull/8089.
|
|
964
|
-
deleteEdgeIn(edge) {
|
|
965
|
-
this.edgesIn.delete(edge)
|
|
966
|
-
const { overrides } = edge
|
|
967
|
-
if (overrides) {
|
|
968
|
-
this.updateOverridesEdgeInRemoved(overrides)
|
|
969
|
-
}
|
|
970
|
-
}
|
|
971
|
-
addEdgeIn(edge) {
|
|
972
|
-
// Patch replacing
|
|
973
|
-
// if (edge.overrides) {
|
|
974
|
-
// this.overrides = edge.overrides
|
|
975
|
-
// }
|
|
976
|
-
// is based on https://github.com/npm/cli/pull/8089.
|
|
977
|
-
//
|
|
978
|
-
// We need to handle the case where the new edge in has an overrides field
|
|
979
|
-
// which is different from the current value.
|
|
980
|
-
if (!this.overrides || !this.overrides.isEqual(edge.overrides)) {
|
|
981
|
-
this.updateOverridesEdgeInAdded(edge.overrides)
|
|
982
|
-
}
|
|
983
|
-
this.edgesIn.add(edge)
|
|
984
|
-
// Try to get metadata from the yarn.lock file.
|
|
985
|
-
this.root.meta?.addEdge(edge)
|
|
986
|
-
}
|
|
987
|
-
|
|
988
|
-
// @ts-ignore: Incorrectly typed as a property instead of an accessor.
|
|
989
|
-
get overridden() {
|
|
990
|
-
// Patch replacing
|
|
991
|
-
// return !!(this.overrides && this.overrides.value && this.overrides.name === this.name)
|
|
992
|
-
// is based on https://github.com/npm/cli/pull/8089.
|
|
993
|
-
if (
|
|
994
|
-
!this.overrides ||
|
|
995
|
-
!this.overrides.value ||
|
|
996
|
-
this.overrides.name !== this.name
|
|
997
|
-
) {
|
|
998
|
-
return false
|
|
999
|
-
}
|
|
1000
|
-
// The overrides rule is for a package with this name, but some override
|
|
1001
|
-
// rules only apply to specific versions. To make sure this package was
|
|
1002
|
-
// actually overridden, we check whether any edge going in had the rule
|
|
1003
|
-
// applied to it, in which case its overrides set is different than its
|
|
1004
|
-
// source node.
|
|
1005
|
-
for (const edge of this.edgesIn) {
|
|
1006
|
-
if (
|
|
1007
|
-
edge.overrides &&
|
|
1008
|
-
edge.overrides.name === this.name &&
|
|
1009
|
-
edge.overrides.value === this.version
|
|
1010
|
-
) {
|
|
1011
|
-
if (!edge.overrides.isEqual(edge.from?.overrides)) {
|
|
1012
|
-
return true
|
|
1013
|
-
}
|
|
1014
|
-
}
|
|
1015
|
-
}
|
|
1016
|
-
return false
|
|
1017
|
-
}
|
|
1018
|
-
set parent(newParent) {
|
|
1019
|
-
// Patch removing
|
|
1020
|
-
// if (parent.overrides) {
|
|
1021
|
-
// this.overrides = parent.overrides.getNodeRule(this)
|
|
1022
|
-
// }
|
|
1023
|
-
// is based on https://github.com/npm/cli/pull/8089.
|
|
1024
|
-
//
|
|
1025
|
-
// The "parent" setter is a really large and complex function. To satisfy
|
|
1026
|
-
// the patch we hold on to the old overrides value and set `this.overrides`
|
|
1027
|
-
// to `undefined` so that the condition we want to remove is not hit.
|
|
1028
|
-
const { overrides } = this
|
|
1029
|
-
if (overrides) {
|
|
1030
|
-
this.overrides = undefined
|
|
1031
|
-
}
|
|
1032
|
-
try {
|
|
1033
|
-
super.parent = newParent
|
|
1034
|
-
this.overrides = overrides
|
|
1035
|
-
} catch (e) {
|
|
1036
|
-
this.overrides = overrides
|
|
1037
|
-
throw e
|
|
1038
|
-
}
|
|
1039
|
-
}
|
|
1040
|
-
|
|
1041
|
-
// Patch adding recalculateOutEdgesOverrides is based on
|
|
1042
|
-
// https://github.com/npm/cli/pull/8089.
|
|
1043
|
-
recalculateOutEdgesOverrides() {
|
|
1044
|
-
// For each edge out propagate the new overrides through.
|
|
1045
|
-
for (const edge of this.edgesOut.values()) {
|
|
1046
|
-
edge.reload(true)
|
|
1047
|
-
if (edge.to) {
|
|
1048
|
-
edge.to.updateOverridesEdgeInAdded(edge.overrides)
|
|
1049
|
-
}
|
|
1050
|
-
}
|
|
1051
|
-
}
|
|
1052
|
-
|
|
1053
|
-
// @ts-ignore: Incorrectly typed to accept null.
|
|
1054
|
-
set root(newRoot) {
|
|
1055
|
-
// Patch removing
|
|
1056
|
-
// if (!this.overrides && this.parent && this.parent.overrides) {
|
|
1057
|
-
// this.overrides = this.parent.overrides.getNodeRule(this)
|
|
1058
|
-
// }
|
|
1059
|
-
// is based on https://github.com/npm/cli/pull/8089.
|
|
1060
|
-
//
|
|
1061
|
-
// The "root" setter is a really large and complex function. To satisfy the
|
|
1062
|
-
// patch we add a dummy value to `this.overrides` so that the condition we
|
|
1063
|
-
// want to remove is not hit.
|
|
1064
|
-
if (!this.overrides) {
|
|
1065
|
-
this.overrides = new SafeOverrideSet({
|
|
1066
|
-
overrides: ''
|
|
1067
|
-
})
|
|
1068
|
-
}
|
|
1069
|
-
try {
|
|
1070
|
-
super.root = newRoot
|
|
1071
|
-
this.overrides = undefined
|
|
1072
|
-
} catch (e) {
|
|
1073
|
-
this.overrides = undefined
|
|
1074
|
-
throw e
|
|
1075
|
-
}
|
|
1076
|
-
}
|
|
1077
|
-
|
|
1078
|
-
// Patch adding updateOverridesEdgeInAdded is based on
|
|
1079
|
-
// https://github.com/npm/cli/pull/7025.
|
|
1080
|
-
//
|
|
1081
|
-
// This logic isn't perfect either. When we have two edges in that have
|
|
1082
|
-
// different override sets, then we have to decide which set is correct. This
|
|
1083
|
-
// function assumes the more specific override set is applicable, so if we have
|
|
1084
|
-
// dependencies A->B->C and A->C and an override set that specifies what happens
|
|
1085
|
-
// for C under A->B, this will work even if the new A->C edge comes along and
|
|
1086
|
-
// tries to change the override set. The strictly correct logic is not to allow
|
|
1087
|
-
// two edges with different overrides to point to the same node, because even
|
|
1088
|
-
// if this node can satisfy both, one of its dependencies might need to be
|
|
1089
|
-
// different depending on the edge leading to it. However, this might cause a
|
|
1090
|
-
// lot of duplication, because the conflict in the dependencies might never
|
|
1091
|
-
// actually happen.
|
|
1092
|
-
updateOverridesEdgeInAdded(otherOverrideSet) {
|
|
1093
|
-
if (!otherOverrideSet) {
|
|
1094
|
-
// Assuming there are any overrides at all, the overrides field is never
|
|
1095
|
-
// undefined for any node at the end state of the tree. So if the new edge's
|
|
1096
|
-
// overrides is undefined it will be updated later. So we can wait with
|
|
1097
|
-
// updating the node's overrides field.
|
|
1098
|
-
return false
|
|
1099
|
-
}
|
|
1100
|
-
if (!this.overrides) {
|
|
1101
|
-
this.overrides = otherOverrideSet
|
|
1102
|
-
this.recalculateOutEdgesOverrides()
|
|
1103
|
-
return true
|
|
1104
|
-
}
|
|
1105
|
-
if (this.overrides.isEqual(otherOverrideSet)) {
|
|
1106
|
-
return false
|
|
1107
|
-
}
|
|
1108
|
-
const newOverrideSet = SafeOverrideSet.findSpecificOverrideSet(
|
|
1109
|
-
this.overrides,
|
|
1110
|
-
otherOverrideSet
|
|
1111
|
-
)
|
|
1112
|
-
if (newOverrideSet) {
|
|
1113
|
-
if (this.overrides.isEqual(newOverrideSet)) {
|
|
1114
|
-
return false
|
|
1115
|
-
}
|
|
1116
|
-
this.overrides = newOverrideSet
|
|
1117
|
-
this.recalculateOutEdgesOverrides()
|
|
1118
|
-
return true
|
|
1119
|
-
}
|
|
1120
|
-
// This is an error condition. We can only get here if the new override set
|
|
1121
|
-
// is in conflict with the existing.
|
|
1122
|
-
const log = getLogger()
|
|
1123
|
-
log?.silly('Conflicting override sets', this.name)
|
|
1124
|
-
return false
|
|
1125
|
-
}
|
|
1126
|
-
|
|
1127
|
-
// Patch adding updateOverridesEdgeInRemoved is based on
|
|
1128
|
-
// https://github.com/npm/cli/pull/7025.
|
|
1129
|
-
updateOverridesEdgeInRemoved(otherOverrideSet) {
|
|
1130
|
-
// If this edge's overrides isn't equal to this node's overrides,
|
|
1131
|
-
// then removing it won't change newOverrideSet later.
|
|
1132
|
-
if (!this.overrides || !this.overrides.isEqual(otherOverrideSet)) {
|
|
1133
|
-
return false
|
|
1134
|
-
}
|
|
1135
|
-
let newOverrideSet
|
|
1136
|
-
for (const edge of this.edgesIn) {
|
|
1137
|
-
const { overrides: edgeOverrides } = edge
|
|
1138
|
-
if (newOverrideSet && edgeOverrides) {
|
|
1139
|
-
newOverrideSet = SafeOverrideSet.findSpecificOverrideSet(
|
|
1140
|
-
edgeOverrides,
|
|
1141
|
-
newOverrideSet
|
|
1142
|
-
)
|
|
1143
|
-
} else {
|
|
1144
|
-
newOverrideSet = edgeOverrides
|
|
1145
|
-
}
|
|
1146
|
-
}
|
|
1147
|
-
if (this.overrides.isEqual(newOverrideSet)) {
|
|
1148
|
-
return false
|
|
1149
|
-
}
|
|
1150
|
-
this.overrides = newOverrideSet
|
|
1151
|
-
if (newOverrideSet) {
|
|
1152
|
-
// Optimization: If there's any override set at all, then no non-extraneous
|
|
1153
|
-
// node has an empty override set. So if we temporarily have no override set
|
|
1154
|
-
// (for example, we removed all the edges in), there's no use updating all
|
|
1155
|
-
// the edges out right now. Let's just wait until we have an actual override
|
|
1156
|
-
// set later.
|
|
1157
|
-
this.recalculateOutEdgesOverrides()
|
|
1158
|
-
}
|
|
1159
|
-
return true
|
|
1160
|
-
}
|
|
1161
|
-
}
|
|
1162
|
-
|
|
1163
|
-
const Edge = require(shadowNpmPaths.getArboristEdgeClassPath())
|
|
1164
|
-
|
|
1165
|
-
// The Edge class makes heavy use of private properties which subclasses do NOT
|
|
1166
|
-
// have access to. So we have to recreate any functionality that relies on those
|
|
1167
|
-
// private properties and use our own "safe" prefixed non-conflicting private
|
|
1168
|
-
// properties. Implementation code not related to patch https://github.com/npm/cli/pull/8089
|
|
1169
|
-
// is based on https://github.com/npm/cli/blob/v11.0.0/workspaces/arborist/lib/edge.js.
|
|
1170
|
-
//
|
|
1171
|
-
// The npm application
|
|
1172
|
-
// Copyright (c) npm, Inc. and Contributors
|
|
1173
|
-
// Licensed on the terms of The Artistic License 2.0
|
|
1174
|
-
//
|
|
1175
|
-
// An edge in the dependency graph.
|
|
1176
|
-
// Represents a dependency relationship of some kind.
|
|
1177
|
-
class SafeEdge extends Edge {
|
|
1178
|
-
#safeError
|
|
1179
|
-
#safeExplanation
|
|
1180
|
-
#safeFrom
|
|
1181
|
-
#safeTo
|
|
1182
|
-
constructor(options) {
|
|
1183
|
-
const { from } = options
|
|
1184
|
-
// Defer to supper to validate options and assign non-private values.
|
|
1185
|
-
super(options)
|
|
1186
|
-
if (from.constructor !== SafeNode) {
|
|
1187
|
-
Reflect.setPrototypeOf(from, SafeNode.prototype)
|
|
1188
|
-
}
|
|
1189
|
-
this.#safeError = null
|
|
1190
|
-
this.#safeExplanation = null
|
|
1191
|
-
this.#safeFrom = from
|
|
1192
|
-
this.#safeTo = null
|
|
1193
|
-
this.reload(true)
|
|
1194
|
-
}
|
|
1195
|
-
get bundled() {
|
|
1196
|
-
return !!this.#safeFrom?.package?.bundleDependencies?.includes(this.name)
|
|
1197
|
-
}
|
|
1198
|
-
get error() {
|
|
1199
|
-
if (!this.#safeError) {
|
|
1200
|
-
if (!this.#safeTo) {
|
|
1201
|
-
if (this.optional) {
|
|
1202
|
-
this.#safeError = null
|
|
1203
|
-
} else {
|
|
1204
|
-
this.#safeError = 'MISSING'
|
|
1205
|
-
}
|
|
1206
|
-
} else if (
|
|
1207
|
-
this.peer &&
|
|
1208
|
-
this.#safeFrom === this.#safeTo.parent &&
|
|
1209
|
-
// Patch adding "?." use based on
|
|
1210
|
-
// https://github.com/npm/cli/pull/8089.
|
|
1211
|
-
!this.#safeFrom?.isTop
|
|
1212
|
-
) {
|
|
1213
|
-
this.#safeError = 'PEER LOCAL'
|
|
1214
|
-
} else if (!this.satisfiedBy(this.#safeTo)) {
|
|
1215
|
-
this.#safeError = 'INVALID'
|
|
1216
|
-
}
|
|
1217
|
-
// Patch adding "else if" condition is based on
|
|
1218
|
-
// https://github.com/npm/cli/pull/8089.
|
|
1219
|
-
else if (
|
|
1220
|
-
this.overrides &&
|
|
1221
|
-
this.#safeTo.edgesOut.size &&
|
|
1222
|
-
SafeOverrideSet.doOverrideSetsConflict(
|
|
1223
|
-
this.overrides,
|
|
1224
|
-
this.#safeTo.overrides
|
|
1225
|
-
)
|
|
1226
|
-
) {
|
|
1227
|
-
// Any inconsistency between the edge's override set and the target's
|
|
1228
|
-
// override set is potentially problematic. But we only say the edge is
|
|
1229
|
-
// in error if the override sets are plainly conflicting. Note that if
|
|
1230
|
-
// the target doesn't have any dependencies of their own, then this
|
|
1231
|
-
// inconsistency is irrelevant.
|
|
1232
|
-
this.#safeError = 'INVALID'
|
|
1233
|
-
} else {
|
|
1234
|
-
this.#safeError = 'OK'
|
|
1235
|
-
}
|
|
1236
|
-
}
|
|
1237
|
-
if (this.#safeError === 'OK') {
|
|
1238
|
-
return null
|
|
1239
|
-
}
|
|
1240
|
-
return this.#safeError
|
|
1241
|
-
}
|
|
1242
|
-
|
|
1243
|
-
// @ts-ignore: Incorrectly typed as a property instead of an accessor.
|
|
1244
|
-
get from() {
|
|
1245
|
-
return this.#safeFrom
|
|
1246
|
-
}
|
|
1247
|
-
|
|
1248
|
-
// @ts-ignore: Incorrectly typed as a property instead of an accessor.
|
|
1249
|
-
get spec() {
|
|
1250
|
-
if (
|
|
1251
|
-
this.overrides?.value &&
|
|
1252
|
-
this.overrides.value !== '*' &&
|
|
1253
|
-
this.overrides.name === this.name
|
|
1254
|
-
) {
|
|
1255
|
-
if (this.overrides.value.startsWith('$')) {
|
|
1256
|
-
const ref = this.overrides.value.slice(1)
|
|
1257
|
-
// We may be a virtual root, if we are we want to resolve reference
|
|
1258
|
-
// overrides from the real root, not the virtual one.
|
|
1259
|
-
//
|
|
1260
|
-
// Patch adding "?." use based on
|
|
1261
|
-
// https://github.com/npm/cli/pull/8089.
|
|
1262
|
-
const pkg = this.#safeFrom?.sourceReference
|
|
1263
|
-
? this.#safeFrom?.sourceReference.root.package
|
|
1264
|
-
: this.#safeFrom?.root?.package
|
|
1265
|
-
if (pkg?.devDependencies?.[ref]) {
|
|
1266
|
-
return pkg.devDependencies[ref]
|
|
1267
|
-
}
|
|
1268
|
-
if (pkg?.optionalDependencies?.[ref]) {
|
|
1269
|
-
return pkg.optionalDependencies[ref]
|
|
1270
|
-
}
|
|
1271
|
-
if (pkg?.dependencies?.[ref]) {
|
|
1272
|
-
return pkg.dependencies[ref]
|
|
1273
|
-
}
|
|
1274
|
-
if (pkg?.peerDependencies?.[ref]) {
|
|
1275
|
-
return pkg.peerDependencies[ref]
|
|
1276
|
-
}
|
|
1277
|
-
throw new Error(`Unable to resolve reference ${this.overrides.value}`)
|
|
1278
|
-
}
|
|
1279
|
-
return this.overrides.value
|
|
1280
|
-
}
|
|
1281
|
-
return this.rawSpec
|
|
1282
|
-
}
|
|
1283
|
-
|
|
1284
|
-
// @ts-ignore: Incorrectly typed as a property instead of an accessor.
|
|
1285
|
-
get to() {
|
|
1286
|
-
return this.#safeTo
|
|
1287
|
-
}
|
|
1288
|
-
detach() {
|
|
1289
|
-
this.#safeExplanation = null
|
|
1290
|
-
// Patch replacing
|
|
1291
|
-
// if (this.#to) {
|
|
1292
|
-
// this.#to.edgesIn.delete(this)
|
|
1293
|
-
// }
|
|
1294
|
-
// this.#from.edgesOut.delete(this.#name)
|
|
1295
|
-
// is based on https://github.com/npm/cli/pull/8089.
|
|
1296
|
-
this.#safeTo?.deleteEdgeIn(this)
|
|
1297
|
-
this.#safeFrom?.edgesOut.delete(this.name)
|
|
1298
|
-
this.#safeTo = null
|
|
1299
|
-
this.#safeError = 'DETACHED'
|
|
1300
|
-
this.#safeFrom = null
|
|
1301
|
-
}
|
|
1302
|
-
|
|
1303
|
-
// Return the edge data, and an explanation of how that edge came to be here.
|
|
1304
|
-
// @ts-ignore: Edge#explain is defined with an unused `seen = []` param.
|
|
1305
|
-
explain() {
|
|
1306
|
-
if (!this.#safeExplanation) {
|
|
1307
|
-
const explanation = {
|
|
1308
|
-
type: this.type,
|
|
1309
|
-
name: this.name,
|
|
1310
|
-
spec: this.spec,
|
|
1311
|
-
bundled: false,
|
|
1312
|
-
overridden: false,
|
|
1313
|
-
error: undefined,
|
|
1314
|
-
from: undefined,
|
|
1315
|
-
rawSpec: undefined
|
|
1316
|
-
}
|
|
1317
|
-
if (this.rawSpec !== this.spec) {
|
|
1318
|
-
explanation.rawSpec = this.rawSpec
|
|
1319
|
-
explanation.overridden = true
|
|
1320
|
-
}
|
|
1321
|
-
if (this.bundled) {
|
|
1322
|
-
explanation.bundled = this.bundled
|
|
1323
|
-
}
|
|
1324
|
-
if (this.error) {
|
|
1325
|
-
explanation.error = this.error
|
|
1326
|
-
}
|
|
1327
|
-
if (this.#safeFrom) {
|
|
1328
|
-
explanation.from = this.#safeFrom.explain()
|
|
1329
|
-
}
|
|
1330
|
-
this.#safeExplanation = explanation
|
|
1331
|
-
}
|
|
1332
|
-
return this.#safeExplanation
|
|
1333
|
-
}
|
|
1334
|
-
reload(hard = false) {
|
|
1335
|
-
this.#safeExplanation = null
|
|
1336
|
-
// Patch replacing
|
|
1337
|
-
// if (this.#from.overrides) {
|
|
1338
|
-
// is based on https://github.com/npm/cli/pull/8089.
|
|
1339
|
-
let needToUpdateOverrideSet = false
|
|
1340
|
-
let newOverrideSet
|
|
1341
|
-
let oldOverrideSet
|
|
1342
|
-
if (this.#safeFrom?.overrides) {
|
|
1343
|
-
newOverrideSet = this.#safeFrom.overrides.getEdgeRule(this)
|
|
1344
|
-
if (newOverrideSet && !newOverrideSet.isEqual(this.overrides)) {
|
|
1345
|
-
// If there's a new different override set we need to propagate it to
|
|
1346
|
-
// the nodes. If we're deleting the override set then there's no point
|
|
1347
|
-
// propagating it right now since it will be filled with another value
|
|
1348
|
-
// later.
|
|
1349
|
-
needToUpdateOverrideSet = true
|
|
1350
|
-
oldOverrideSet = this.overrides
|
|
1351
|
-
this.overrides = newOverrideSet
|
|
1352
|
-
}
|
|
1353
|
-
} else {
|
|
1354
|
-
this.overrides = undefined
|
|
1355
|
-
}
|
|
1356
|
-
// Patch adding "?." use based on
|
|
1357
|
-
// https://github.com/npm/cli/pull/8089.
|
|
1358
|
-
const newTo = this.#safeFrom?.resolve(this.name)
|
|
1359
|
-
if (newTo !== this.#safeTo) {
|
|
1360
|
-
// Patch replacing
|
|
1361
|
-
// this.#to.edgesIn.delete(this)
|
|
1362
|
-
// is based on https://github.com/npm/cli/pull/8089.
|
|
1363
|
-
this.#safeTo?.deleteEdgeIn(this)
|
|
1364
|
-
this.#safeTo = newTo ?? null
|
|
1365
|
-
this.#safeError = null
|
|
1366
|
-
this.#safeTo?.addEdgeIn(this)
|
|
1367
|
-
} else if (hard) {
|
|
1368
|
-
this.#safeError = null
|
|
1369
|
-
}
|
|
1370
|
-
// Patch adding "else if" condition based on
|
|
1371
|
-
// https://github.com/npm/cli/pull/8089.
|
|
1372
|
-
else if (needToUpdateOverrideSet && this.#safeTo) {
|
|
1373
|
-
// Propagate the new override set to the target node.
|
|
1374
|
-
this.#safeTo.updateOverridesEdgeInRemoved(oldOverrideSet)
|
|
1375
|
-
this.#safeTo.updateOverridesEdgeInAdded(newOverrideSet)
|
|
1376
|
-
}
|
|
1377
|
-
}
|
|
1378
|
-
satisfiedBy(node) {
|
|
1379
|
-
// Patch replacing
|
|
1380
|
-
// if (node.name !== this.#name) {
|
|
1381
|
-
// return false
|
|
1382
|
-
// }
|
|
1383
|
-
// is based on https://github.com/npm/cli/pull/8089.
|
|
1384
|
-
if (node.name !== this.name || !this.#safeFrom) {
|
|
1385
|
-
return false
|
|
1386
|
-
}
|
|
1387
|
-
// NOTE: this condition means we explicitly do not support overriding
|
|
1388
|
-
// bundled or shrinkwrapped dependencies
|
|
1389
|
-
if (node.hasShrinkwrap || node.inShrinkwrap || node.inBundle) {
|
|
1390
|
-
return depValid(node, this.rawSpec, this.accept, this.#safeFrom)
|
|
1391
|
-
}
|
|
1392
|
-
// Patch replacing
|
|
1393
|
-
// return depValid(node, this.spec, this.#accept, this.#from)
|
|
1394
|
-
// is based on https://github.com/npm/cli/pull/8089.
|
|
1395
|
-
//
|
|
1396
|
-
// If there's no override we just use the spec.
|
|
1397
|
-
if (!this.overrides?.keySpec) {
|
|
1398
|
-
return depValid(node, this.spec, this.accept, this.#safeFrom)
|
|
1399
|
-
}
|
|
1400
|
-
// There's some override. If the target node satisfies the overriding spec
|
|
1401
|
-
// then it's okay.
|
|
1402
|
-
if (depValid(node, this.spec, this.accept, this.#safeFrom)) {
|
|
1403
|
-
return true
|
|
1404
|
-
}
|
|
1405
|
-
// If it doesn't, then it should at least satisfy the original spec.
|
|
1406
|
-
if (!depValid(node, this.rawSpec, this.accept, this.#safeFrom)) {
|
|
1407
|
-
return false
|
|
1408
|
-
}
|
|
1409
|
-
// It satisfies the original spec, not the overriding spec. We need to make
|
|
1410
|
-
// sure it doesn't use the overridden spec.
|
|
1411
|
-
// For example:
|
|
1412
|
-
// we might have an ^8.0.0 rawSpec, and an override that makes
|
|
1413
|
-
// keySpec=8.23.0 and the override value spec=9.0.0.
|
|
1414
|
-
// If the node is 9.0.0, then it's okay because it's consistent with spec.
|
|
1415
|
-
// If the node is 8.24.0, then it's okay because it's consistent with the rawSpec.
|
|
1416
|
-
// If the node is 8.23.0, then it's not okay because even though it's consistent
|
|
1417
|
-
// with the rawSpec, it's also consistent with the keySpec.
|
|
1418
|
-
// So we're looking for ^8.0.0 or 9.0.0 and not 8.23.0.
|
|
1419
|
-
return !depValid(node, this.overrides.keySpec, this.accept, this.#safeFrom)
|
|
1420
|
-
}
|
|
1421
|
-
}
|
|
1422
|
-
|
|
1423
|
-
const { LOOP_SENTINEL, NPM: NPM$2, NPM_REGISTRY_URL } = constants
|
|
1424
|
-
function getUrlOrigin(input) {
|
|
1425
|
-
try {
|
|
1426
|
-
// TODO: URL.parse is available in Node 22.1.0. We can use it when we drop Node 18.
|
|
1427
|
-
// https://nodejs.org/docs/latest-v22.x/api/url.html#urlparseinput-base
|
|
1428
|
-
// return URL.parse(input)?.origin ?? ''
|
|
1429
|
-
return new URL(input).origin ?? ''
|
|
1430
|
-
} catch {}
|
|
1431
|
-
return ''
|
|
1432
|
-
}
|
|
1433
|
-
function findBestPatchVersion(
|
|
1434
|
-
node,
|
|
1435
|
-
availableVersions,
|
|
1436
|
-
vulnerableVersionRange,
|
|
1437
|
-
_firstPatchedVersionIdentifier
|
|
1438
|
-
) {
|
|
1439
|
-
const manifestData = registry.getManifestData(NPM$2, node.name)
|
|
1440
|
-
let eligibleVersions
|
|
1441
|
-
if (manifestData && manifestData.name === manifestData.package) {
|
|
1442
|
-
const major = getMajor(manifestData.version)
|
|
1443
|
-
if (typeof major !== 'number') {
|
|
1444
|
-
return null
|
|
1445
|
-
}
|
|
1446
|
-
eligibleVersions = availableVersions.filter(v => getMajor(v) === major)
|
|
1447
|
-
} else {
|
|
1448
|
-
const major = getMajor(node.version)
|
|
1449
|
-
if (typeof major !== 'number') {
|
|
1450
|
-
return null
|
|
1451
|
-
}
|
|
1452
|
-
eligibleVersions = availableVersions.filter(
|
|
1453
|
-
v =>
|
|
1454
|
-
// Filter for versions that are within the current major version and
|
|
1455
|
-
// are NOT in the vulnerable range.
|
|
1456
|
-
getMajor(v) === major &&
|
|
1457
|
-
(!vulnerableVersionRange ||
|
|
1458
|
-
!vendor.semverExports.satisfies(v, vulnerableVersionRange))
|
|
1459
|
-
)
|
|
1460
|
-
}
|
|
1461
|
-
return eligibleVersions
|
|
1462
|
-
? vendor.semverExports.maxSatisfying(eligibleVersions, '*')
|
|
1463
|
-
: null
|
|
1464
|
-
}
|
|
1465
|
-
function findPackageNode(tree, name, version) {
|
|
1466
|
-
const queue = [tree]
|
|
1467
|
-
let sentinel = 0
|
|
1468
|
-
while (queue.length) {
|
|
1469
|
-
if (sentinel++ === LOOP_SENTINEL) {
|
|
1470
|
-
throw new Error('Detected infinite loop in findPackageNodes')
|
|
1471
|
-
}
|
|
1472
|
-
const currentNode = queue.pop()
|
|
1473
|
-
const node = currentNode.children.get(name)
|
|
1474
|
-
if (node && (typeof version !== 'string' || node.version === version)) {
|
|
1475
|
-
return node
|
|
1476
|
-
}
|
|
1477
|
-
const children = [...currentNode.children.values()]
|
|
1478
|
-
for (let i = children.length - 1; i >= 0; i -= 1) {
|
|
1479
|
-
queue.push(children[i])
|
|
1480
|
-
}
|
|
1481
|
-
}
|
|
1482
|
-
}
|
|
1483
|
-
function findPackageNodes(tree, name, version) {
|
|
1484
|
-
const queue = [tree]
|
|
1485
|
-
const matches = []
|
|
1486
|
-
let sentinel = 0
|
|
1487
|
-
while (queue.length) {
|
|
1488
|
-
if (sentinel++ === LOOP_SENTINEL) {
|
|
1489
|
-
throw new Error('Detected infinite loop in findPackageNodes')
|
|
1490
|
-
}
|
|
1491
|
-
const currentNode = queue.pop()
|
|
1492
|
-
const node = currentNode.children.get(name)
|
|
1493
|
-
if (node && 'undefined' !== 'string') {
|
|
1494
|
-
matches.push(node)
|
|
1495
|
-
}
|
|
1496
|
-
const children = [...currentNode.children.values()]
|
|
1497
|
-
for (let i = children.length - 1; i >= 0; i -= 1) {
|
|
1498
|
-
queue.push(children[i])
|
|
1499
|
-
}
|
|
1500
|
-
}
|
|
1501
|
-
return matches
|
|
1502
|
-
}
|
|
1503
|
-
function getDetailsFromDiff(diff_, options) {
|
|
1504
|
-
const details = []
|
|
1505
|
-
// `diff_` is `null` when `npm install --package-lock-only` is passed.
|
|
1506
|
-
if (!diff_) {
|
|
1507
|
-
return details
|
|
1508
|
-
}
|
|
1509
|
-
const include = {
|
|
1510
|
-
__proto__: null,
|
|
1511
|
-
unchanged: false,
|
|
1512
|
-
unknownOrigin: false,
|
|
1513
|
-
...{
|
|
1514
|
-
__proto__: null,
|
|
1515
|
-
...options
|
|
1516
|
-
}.include
|
|
1517
|
-
}
|
|
1518
|
-
const queue = [...diff_.children]
|
|
1519
|
-
let pos = 0
|
|
1520
|
-
let { length: queueLength } = queue
|
|
1521
|
-
while (pos < queueLength) {
|
|
1522
|
-
if (pos === LOOP_SENTINEL) {
|
|
1523
|
-
throw new Error('Detected infinite loop while walking Arborist diff')
|
|
1524
|
-
}
|
|
1525
|
-
const diff = queue[pos++]
|
|
1526
|
-
const { action } = diff
|
|
1527
|
-
if (action) {
|
|
1528
|
-
// The `pkgNode`, i.e. the `ideal` node, will be `undefined` if the diff
|
|
1529
|
-
// action is 'REMOVE'
|
|
1530
|
-
// The `oldNode`, i.e. the `actual` node, will be `undefined` if the diff
|
|
1531
|
-
// action is 'ADD'.
|
|
1532
|
-
const { actual: oldNode, ideal: pkgNode } = diff
|
|
1533
|
-
let existing
|
|
1534
|
-
let keep = false
|
|
1535
|
-
if (action === DiffAction.change) {
|
|
1536
|
-
if (pkgNode?.package.version !== oldNode?.package.version) {
|
|
1537
|
-
keep = true
|
|
1538
|
-
if (
|
|
1539
|
-
oldNode?.package.name &&
|
|
1540
|
-
oldNode.package.name === pkgNode?.package.name
|
|
1541
|
-
) {
|
|
1542
|
-
existing = oldNode
|
|
1543
|
-
}
|
|
1544
|
-
} else {
|
|
1545
|
-
debug.debugLog('SKIPPING META CHANGE ON\n', diff)
|
|
1546
|
-
}
|
|
1547
|
-
} else {
|
|
1548
|
-
keep = action !== DiffAction.remove
|
|
1549
|
-
}
|
|
1550
|
-
if (keep && pkgNode?.resolved && (!oldNode || oldNode.resolved)) {
|
|
1551
|
-
if (
|
|
1552
|
-
include.unknownOrigin ||
|
|
1553
|
-
getUrlOrigin(pkgNode.resolved) === NPM_REGISTRY_URL
|
|
1554
|
-
) {
|
|
1555
|
-
details.push({
|
|
1556
|
-
node: pkgNode,
|
|
1557
|
-
existing
|
|
1558
|
-
})
|
|
1559
|
-
}
|
|
1560
|
-
}
|
|
1561
|
-
}
|
|
1562
|
-
for (const child of diff.children) {
|
|
1563
|
-
queue[queueLength++] = child
|
|
1564
|
-
}
|
|
1565
|
-
}
|
|
1566
|
-
if (include.unchanged) {
|
|
1567
|
-
const { unchanged } = diff_
|
|
1568
|
-
for (let i = 0, { length } = unchanged; i < length; i += 1) {
|
|
1569
|
-
const pkgNode = unchanged[i]
|
|
1570
|
-
if (
|
|
1571
|
-
include.unknownOrigin ||
|
|
1572
|
-
getUrlOrigin(pkgNode.resolved) === NPM_REGISTRY_URL
|
|
1573
|
-
) {
|
|
1574
|
-
details.push({
|
|
1575
|
-
node: pkgNode,
|
|
1576
|
-
existing: pkgNode
|
|
1577
|
-
})
|
|
1578
|
-
}
|
|
1579
|
-
}
|
|
1580
|
-
}
|
|
1581
|
-
return details
|
|
1582
|
-
}
|
|
1583
|
-
function isTopLevel(tree, node) {
|
|
1584
|
-
return tree.children.get(node.name) === node
|
|
1585
|
-
}
|
|
1586
|
-
function updateNode(node, newVersion, newVersionPackument) {
|
|
1587
|
-
// Object.defineProperty is needed to set the version property and replace
|
|
1588
|
-
// the old value with newVersion.
|
|
1589
|
-
Object.defineProperty(node, 'version', {
|
|
1590
|
-
configurable: true,
|
|
1591
|
-
enumerable: true,
|
|
1592
|
-
get: () => newVersion
|
|
1593
|
-
})
|
|
1594
|
-
// Update package.version associated with the node.
|
|
1595
|
-
node.package.version = newVersion
|
|
1596
|
-
// Update node.resolved.
|
|
1597
|
-
const purlObj = packageurlJs.PackageURL.fromString(`pkg:npm/${node.name}`)
|
|
1598
|
-
node.resolved = `${NPM_REGISTRY_URL}/${node.name}/-/${purlObj.name}-${newVersion}.tgz`
|
|
1599
|
-
// Update node.integrity with the targetPackument.dist.integrity value if available
|
|
1600
|
-
// else delete node.integrity so a new value is resolved for the target version.
|
|
1601
|
-
const { integrity } = newVersionPackument.dist
|
|
1602
|
-
if (integrity) {
|
|
1603
|
-
node.integrity = integrity
|
|
1604
|
-
} else {
|
|
1605
|
-
delete node.integrity
|
|
1606
|
-
}
|
|
1607
|
-
// Update node.package.deprecated based on targetPackument.deprecated.
|
|
1608
|
-
if (objects.hasOwn(newVersionPackument, 'deprecated')) {
|
|
1609
|
-
node.package['deprecated'] = newVersionPackument.deprecated
|
|
1610
|
-
} else {
|
|
1611
|
-
delete node.package['deprecated']
|
|
1612
|
-
}
|
|
1613
|
-
// Update node.package.dependencies.
|
|
1614
|
-
const newDeps = {
|
|
1615
|
-
...newVersionPackument.dependencies
|
|
1616
|
-
}
|
|
1617
|
-
const { dependencies: oldDeps } = node.package
|
|
1618
|
-
node.package.dependencies = newDeps
|
|
1619
|
-
if (oldDeps) {
|
|
1620
|
-
for (const oldDepName of Object.keys(oldDeps)) {
|
|
1621
|
-
if (!objects.hasOwn(newDeps, oldDepName)) {
|
|
1622
|
-
// Detach old edges for dependencies that don't exist on the updated
|
|
1623
|
-
// node.package.dependencies.
|
|
1624
|
-
node.edgesOut.get(oldDepName)?.detach()
|
|
1625
|
-
}
|
|
1626
|
-
}
|
|
1627
|
-
}
|
|
1628
|
-
for (const newDepName of Object.keys(newDeps)) {
|
|
1629
|
-
if (!objects.hasOwn(oldDeps, newDepName)) {
|
|
1630
|
-
// Add new edges for dependencies that don't exist on the old
|
|
1631
|
-
// node.package.dependencies.
|
|
1632
|
-
node.addEdgeOut(
|
|
1633
|
-
new Edge({
|
|
1634
|
-
from: node,
|
|
1635
|
-
name: newDepName,
|
|
1636
|
-
spec: newDeps[newDepName],
|
|
1637
|
-
type: 'prod'
|
|
1638
|
-
})
|
|
1639
|
-
)
|
|
1640
|
-
}
|
|
1641
|
-
}
|
|
1642
|
-
}
|
|
1643
|
-
function updatePackageJsonFromNode(
|
|
1644
|
-
editablePkgJson,
|
|
1645
|
-
tree,
|
|
1646
|
-
node,
|
|
1647
|
-
newVersion,
|
|
1648
|
-
rangeStyle
|
|
1649
|
-
) {
|
|
1650
|
-
let result = false
|
|
1651
|
-
if (!isTopLevel(tree, node)) {
|
|
1652
|
-
return result
|
|
1653
|
-
}
|
|
1654
|
-
const { name } = node
|
|
1655
|
-
for (const depField of [
|
|
1656
|
-
'dependencies',
|
|
1657
|
-
'optionalDependencies',
|
|
1658
|
-
'peerDependencies'
|
|
1659
|
-
]) {
|
|
1660
|
-
const depObject = editablePkgJson.content[depField]
|
|
1661
|
-
if (depObject) {
|
|
1662
|
-
const oldRange = depObject[name]
|
|
1663
|
-
if (oldRange) {
|
|
1664
|
-
const newRange = applyRange(oldRange, newVersion, rangeStyle)
|
|
1665
|
-
if (oldRange !== newRange) {
|
|
1666
|
-
result = true
|
|
1667
|
-
editablePkgJson.update({
|
|
1668
|
-
[depField]: {
|
|
1669
|
-
...depObject,
|
|
1670
|
-
[name]: newRange
|
|
1671
|
-
}
|
|
1672
|
-
})
|
|
1673
|
-
}
|
|
1674
|
-
}
|
|
1675
|
-
}
|
|
1676
|
-
}
|
|
1677
|
-
return result
|
|
1678
|
-
}
|
|
1679
|
-
|
|
1680
|
-
const {
|
|
1681
|
-
ALERT_TYPE_CRITICAL_CVE,
|
|
1682
|
-
ALERT_TYPE_CVE,
|
|
1683
|
-
ALERT_TYPE_MEDIUM_CVE,
|
|
1684
|
-
ALERT_TYPE_MILD_CVE
|
|
1685
|
-
} = constants
|
|
1686
|
-
function isArtifactAlertCve(alert) {
|
|
1687
|
-
const { type } = alert
|
|
1688
|
-
return (
|
|
1689
|
-
type === ALERT_TYPE_CVE ||
|
|
1690
|
-
type === ALERT_TYPE_MEDIUM_CVE ||
|
|
1691
|
-
type === ALERT_TYPE_MILD_CVE ||
|
|
1692
|
-
type === ALERT_TYPE_CRITICAL_CVE
|
|
1693
|
-
)
|
|
1694
|
-
}
|
|
1695
|
-
|
|
1696
|
-
const ALERT_FIX_TYPE = /*#__PURE__*/ (function (ALERT_FIX_TYPE) {
|
|
1697
|
-
ALERT_FIX_TYPE['cve'] = 'cve'
|
|
1698
|
-
ALERT_FIX_TYPE['remove'] = 'remove'
|
|
1699
|
-
ALERT_FIX_TYPE['upgrade'] = 'upgrade'
|
|
1700
|
-
return ALERT_FIX_TYPE
|
|
1701
|
-
})({})
|
|
1702
|
-
|
|
1703
|
-
function pick(input, keys) {
|
|
1704
|
-
const result = {}
|
|
1705
|
-
for (const key of keys) {
|
|
1706
|
-
result[key] = input[key]
|
|
1707
|
-
}
|
|
1708
|
-
return result
|
|
1709
|
-
}
|
|
1710
|
-
|
|
1711
|
-
function stringJoinWithSeparateFinalSeparator(list, separator = ' and ') {
|
|
1712
|
-
const values = list.filter(Boolean)
|
|
1713
|
-
const { length } = values
|
|
1714
|
-
if (!length) {
|
|
1715
|
-
return ''
|
|
1716
|
-
}
|
|
1717
|
-
if (length === 1) {
|
|
1718
|
-
return values[0]
|
|
1719
|
-
}
|
|
1720
|
-
const finalValue = values.pop()
|
|
1721
|
-
return `${values.join(', ')}${separator}${finalValue}`
|
|
1722
|
-
}
|
|
1723
|
-
|
|
1724
|
-
const ALERT_SEVERITY = /*#__PURE__*/ (function (ALERT_SEVERITY) {
|
|
1725
|
-
ALERT_SEVERITY['critical'] = 'critical'
|
|
1726
|
-
ALERT_SEVERITY['high'] = 'high'
|
|
1727
|
-
ALERT_SEVERITY['middle'] = 'middle'
|
|
1728
|
-
ALERT_SEVERITY['low'] = 'low'
|
|
1729
|
-
return ALERT_SEVERITY
|
|
1730
|
-
})({})
|
|
1731
|
-
// Ordered from most severe to least.
|
|
1732
|
-
const ALERT_SEVERITIES_SORTED = Object.freeze([
|
|
1733
|
-
'critical',
|
|
1734
|
-
'high',
|
|
1735
|
-
'middle',
|
|
1736
|
-
'low'
|
|
1737
|
-
])
|
|
1738
|
-
function getDesiredSeverities(lowestToInclude) {
|
|
1739
|
-
const result = []
|
|
1740
|
-
for (const severity of ALERT_SEVERITIES_SORTED) {
|
|
1741
|
-
result.push(severity)
|
|
1742
|
-
if (severity === lowestToInclude) {
|
|
1743
|
-
break
|
|
1744
|
-
}
|
|
1745
|
-
}
|
|
1746
|
-
return result
|
|
1747
|
-
}
|
|
1748
|
-
function formatSeverityCount(severityCount) {
|
|
1749
|
-
const summary = []
|
|
1750
|
-
for (const severity of ALERT_SEVERITIES_SORTED) {
|
|
1751
|
-
if (severityCount[severity]) {
|
|
1752
|
-
summary.push(`${severityCount[severity]} ${severity}`)
|
|
1753
|
-
}
|
|
1754
|
-
}
|
|
1755
|
-
return stringJoinWithSeparateFinalSeparator(summary)
|
|
1756
|
-
}
|
|
1757
|
-
function getSeverityCount(issues, lowestToInclude) {
|
|
1758
|
-
const severityCount = pick(
|
|
1759
|
-
{
|
|
1760
|
-
low: 0,
|
|
1761
|
-
middle: 0,
|
|
1762
|
-
high: 0,
|
|
1763
|
-
critical: 0
|
|
1764
|
-
},
|
|
1765
|
-
getDesiredSeverities(lowestToInclude)
|
|
1766
|
-
)
|
|
1767
|
-
for (const issue of issues) {
|
|
1768
|
-
const { value } = issue
|
|
1769
|
-
if (!value) {
|
|
1770
|
-
continue
|
|
1771
|
-
}
|
|
1772
|
-
const { severity } = value
|
|
1773
|
-
if (severityCount[severity] !== undefined) {
|
|
1774
|
-
severityCount[severity] += 1
|
|
1775
|
-
}
|
|
1776
|
-
}
|
|
1777
|
-
return severityCount
|
|
1778
|
-
}
|
|
1779
|
-
|
|
1780
|
-
class ColorOrMarkdown {
|
|
1781
|
-
constructor(useMarkdown) {
|
|
1782
|
-
this.useMarkdown = !!useMarkdown
|
|
1783
|
-
}
|
|
1784
|
-
bold(text) {
|
|
1785
|
-
return this.useMarkdown
|
|
1786
|
-
? `**${text}**`
|
|
1787
|
-
: vendor.yoctocolorsCjsExports.bold(`${text}`)
|
|
1788
|
-
}
|
|
1789
|
-
header(text, level = 1) {
|
|
1790
|
-
return this.useMarkdown
|
|
1791
|
-
? `\n${''.padStart(level, '#')} ${text}\n`
|
|
1792
|
-
: vendor.yoctocolorsCjsExports.underline(
|
|
1793
|
-
`\n${level === 1 ? vendor.yoctocolorsCjsExports.bold(text) : text}\n`
|
|
1794
|
-
)
|
|
1795
|
-
}
|
|
1796
|
-
hyperlink(text, url, { fallback = true, fallbackToUrl } = {}) {
|
|
1797
|
-
if (url) {
|
|
1798
|
-
return this.useMarkdown
|
|
1799
|
-
? `[${text}](${url})`
|
|
1800
|
-
: vendor.terminalLinkExports(text, url, {
|
|
1801
|
-
fallback: fallbackToUrl ? (_text, url) => url : fallback
|
|
1802
|
-
})
|
|
1803
|
-
}
|
|
1804
|
-
return text
|
|
1805
|
-
}
|
|
1806
|
-
indent(...args) {
|
|
1807
|
-
return indentString(...args)
|
|
1808
|
-
}
|
|
1809
|
-
italic(text) {
|
|
1810
|
-
return this.useMarkdown
|
|
1811
|
-
? `_${text}_`
|
|
1812
|
-
: vendor.yoctocolorsCjsExports.italic(`${text}`)
|
|
1813
|
-
}
|
|
1814
|
-
json(value) {
|
|
1815
|
-
return this.useMarkdown
|
|
1816
|
-
? '```json\n' + JSON.stringify(value) + '\n```'
|
|
1817
|
-
: JSON.stringify(value)
|
|
1818
|
-
}
|
|
1819
|
-
list(items) {
|
|
1820
|
-
const indentedContent = items.map(item => this.indent(item).trimStart())
|
|
1821
|
-
return this.useMarkdown
|
|
1822
|
-
? `* ${indentedContent.join('\n* ')}\n`
|
|
1823
|
-
: `${indentedContent.join('\n')}\n`
|
|
1824
|
-
}
|
|
1825
|
-
}
|
|
1826
|
-
|
|
1827
|
-
function getSocketDevAlertUrl(alertType) {
|
|
1828
|
-
return `https://socket.dev/alerts/${alertType}`
|
|
1829
|
-
}
|
|
1830
|
-
function getSocketDevPackageOverviewUrl(eco, name, version) {
|
|
1831
|
-
return `https://socket.dev/${eco}/package/${name}${version ? `/overview/${version}` : ''}`
|
|
1832
|
-
}
|
|
1833
|
-
|
|
1834
|
-
let _translations
|
|
1835
|
-
function getTranslations() {
|
|
1836
|
-
if (_translations === undefined) {
|
|
1837
|
-
_translations = require(
|
|
1838
|
-
// Lazily access constants.rootPath.
|
|
1839
|
-
path.join(constants.rootPath, 'translations.json')
|
|
1840
|
-
)
|
|
1841
|
-
}
|
|
1842
|
-
return _translations
|
|
1843
|
-
}
|
|
1844
|
-
|
|
1845
|
-
const ALERT_SEVERITY_COLOR = /*#__PURE__*/ (function (ALERT_SEVERITY_COLOR) {
|
|
1846
|
-
ALERT_SEVERITY_COLOR['critical'] = 'magenta'
|
|
1847
|
-
ALERT_SEVERITY_COLOR['high'] = 'red'
|
|
1848
|
-
ALERT_SEVERITY_COLOR['middle'] = 'yellow'
|
|
1849
|
-
ALERT_SEVERITY_COLOR['low'] = 'white'
|
|
1850
|
-
return ALERT_SEVERITY_COLOR
|
|
1851
|
-
})({})
|
|
1852
|
-
const ALERT_SEVERITY_ORDER = /*#__PURE__*/ (function (ALERT_SEVERITY_ORDER) {
|
|
1853
|
-
ALERT_SEVERITY_ORDER[(ALERT_SEVERITY_ORDER['critical'] = 0)] = 'critical'
|
|
1854
|
-
ALERT_SEVERITY_ORDER[(ALERT_SEVERITY_ORDER['high'] = 1)] = 'high'
|
|
1855
|
-
ALERT_SEVERITY_ORDER[(ALERT_SEVERITY_ORDER['middle'] = 2)] = 'middle'
|
|
1856
|
-
ALERT_SEVERITY_ORDER[(ALERT_SEVERITY_ORDER['low'] = 3)] = 'low'
|
|
1857
|
-
ALERT_SEVERITY_ORDER[(ALERT_SEVERITY_ORDER['none'] = 4)] = 'none'
|
|
1858
|
-
return ALERT_SEVERITY_ORDER
|
|
1859
|
-
})({})
|
|
1860
|
-
const { CVE_ALERT_PROPS_FIRST_PATCHED_VERSION_IDENTIFIER, NPM: NPM$1 } =
|
|
1861
|
-
constants
|
|
1862
|
-
const MIN_ABOVE_THE_FOLD_COUNT = 3
|
|
1863
|
-
const MIN_ABOVE_THE_FOLD_ALERT_COUNT = 1
|
|
1864
|
-
const format = new ColorOrMarkdown(false)
|
|
1865
|
-
function alertsHaveBlocked(alerts) {
|
|
1866
|
-
return alerts.find(a => a.blocked) !== undefined
|
|
1867
|
-
}
|
|
1868
|
-
function alertsHaveSeverity(alerts, severity) {
|
|
1869
|
-
return alerts.find(a => a.raw.severity === severity) !== undefined
|
|
1870
|
-
}
|
|
1871
|
-
function alertSeverityComparator(a, b) {
|
|
1872
|
-
return getAlertSeverityOrder(a) - getAlertSeverityOrder(b)
|
|
1873
|
-
}
|
|
1874
|
-
function getAlertSeverityOrder(alert) {
|
|
1875
|
-
const { severity } = alert.raw
|
|
1876
|
-
return severity === ALERT_SEVERITY.critical
|
|
1877
|
-
? 0
|
|
1878
|
-
: severity === ALERT_SEVERITY.high
|
|
1879
|
-
? 1
|
|
1880
|
-
: severity === ALERT_SEVERITY.middle
|
|
1881
|
-
? 2
|
|
1882
|
-
: severity === ALERT_SEVERITY.low
|
|
1883
|
-
? 3
|
|
1884
|
-
: 4
|
|
1885
|
-
}
|
|
1886
|
-
function getAlertsSeverityOrder(alerts) {
|
|
1887
|
-
return alertsHaveBlocked(alerts) ||
|
|
1888
|
-
alertsHaveSeverity(alerts, ALERT_SEVERITY.critical)
|
|
1889
|
-
? 0
|
|
1890
|
-
: alertsHaveSeverity(alerts, ALERT_SEVERITY.high)
|
|
1891
|
-
? 1
|
|
1892
|
-
: alertsHaveSeverity(alerts, ALERT_SEVERITY.middle)
|
|
1893
|
-
? 2
|
|
1894
|
-
: alertsHaveSeverity(alerts, ALERT_SEVERITY.low)
|
|
1895
|
-
? 3
|
|
1896
|
-
: 4
|
|
1897
|
-
}
|
|
1898
|
-
function getHiddenRiskCounts(hiddenAlerts) {
|
|
1899
|
-
const riskCounts = {
|
|
1900
|
-
critical: 0,
|
|
1901
|
-
high: 0,
|
|
1902
|
-
middle: 0,
|
|
1903
|
-
low: 0
|
|
1904
|
-
}
|
|
1905
|
-
for (const alert of hiddenAlerts) {
|
|
1906
|
-
switch (getAlertSeverityOrder(alert)) {
|
|
1907
|
-
case ALERT_SEVERITY_ORDER.critical:
|
|
1908
|
-
riskCounts.critical += 1
|
|
1909
|
-
break
|
|
1910
|
-
case ALERT_SEVERITY_ORDER.high:
|
|
1911
|
-
riskCounts.high += 1
|
|
1912
|
-
break
|
|
1913
|
-
case ALERT_SEVERITY_ORDER.middle:
|
|
1914
|
-
riskCounts.middle += 1
|
|
1915
|
-
break
|
|
1916
|
-
case ALERT_SEVERITY_ORDER.low:
|
|
1917
|
-
riskCounts.low += 1
|
|
1918
|
-
break
|
|
1919
|
-
}
|
|
1920
|
-
}
|
|
1921
|
-
return riskCounts
|
|
1922
|
-
}
|
|
1923
|
-
function getHiddenRisksDescription(riskCounts) {
|
|
1924
|
-
const descriptions = []
|
|
1925
|
-
if (riskCounts.critical) {
|
|
1926
|
-
descriptions.push(`${riskCounts.critical} ${getSeverityLabel('critical')}`)
|
|
1927
|
-
}
|
|
1928
|
-
if (riskCounts.high) {
|
|
1929
|
-
descriptions.push(`${riskCounts.high} ${getSeverityLabel('high')}`)
|
|
1930
|
-
}
|
|
1931
|
-
if (riskCounts.middle) {
|
|
1932
|
-
descriptions.push(`${riskCounts.middle} ${getSeverityLabel('middle')}`)
|
|
1933
|
-
}
|
|
1934
|
-
if (riskCounts.low) {
|
|
1935
|
-
descriptions.push(`${riskCounts.low} ${getSeverityLabel('low')}`)
|
|
1936
|
-
}
|
|
1937
|
-
return `(${descriptions.join('; ')})`
|
|
1938
|
-
}
|
|
1939
|
-
function getSeverityLabel(severity) {
|
|
1940
|
-
return severity === 'middle' ? 'moderate' : severity
|
|
1941
|
-
}
|
|
1942
|
-
async function addArtifactToAlertsMap(artifact, alertsByPkgId, options) {
|
|
1943
|
-
// Make TypeScript happy.
|
|
1944
|
-
if (!artifact.name || !artifact.version || !artifact.alerts?.length) {
|
|
1945
|
-
return alertsByPkgId
|
|
1946
|
-
}
|
|
1947
|
-
const {
|
|
1948
|
-
consolidate = false,
|
|
1949
|
-
include: _include,
|
|
1950
|
-
overrides
|
|
1951
|
-
} = {
|
|
1952
|
-
__proto__: null,
|
|
1953
|
-
...options
|
|
1954
|
-
}
|
|
1955
|
-
const include = {
|
|
1956
|
-
__proto__: null,
|
|
1957
|
-
blocked: true,
|
|
1958
|
-
critical: true,
|
|
1959
|
-
cve: true,
|
|
1960
|
-
unfixable: true,
|
|
1961
|
-
upgradable: false,
|
|
1962
|
-
..._include
|
|
1963
|
-
}
|
|
1964
|
-
const name = packages.resolvePackageName(artifact)
|
|
1965
|
-
const { version } = artifact
|
|
1966
|
-
const pkgId = `${name}@${version}`
|
|
1967
|
-
const major = vendor.semverExports.major(version)
|
|
1968
|
-
const socketYml = findSocketYmlSync()
|
|
1969
|
-
const enabledState = {
|
|
1970
|
-
__proto__: null,
|
|
1971
|
-
...socketYml?.parsed.issueRules
|
|
1972
|
-
}
|
|
1973
|
-
let sockPkgAlerts = []
|
|
1974
|
-
for (const alert of artifact.alerts) {
|
|
1975
|
-
const action = alert.action ?? ''
|
|
1976
|
-
const enabledFlag = enabledState[alert.type]
|
|
1977
|
-
if (
|
|
1978
|
-
(action === 'ignore' && enabledFlag !== true) ||
|
|
1979
|
-
enabledFlag === false
|
|
1980
|
-
) {
|
|
1981
|
-
continue
|
|
1982
|
-
}
|
|
1983
|
-
const blocked = action === 'error'
|
|
1984
|
-
const critical = alert.severity === ALERT_SEVERITY.critical
|
|
1985
|
-
const cve = isArtifactAlertCve(alert)
|
|
1986
|
-
const fixType = alert.fix?.type ?? ''
|
|
1987
|
-
const fixableCve = fixType === ALERT_FIX_TYPE.cve
|
|
1988
|
-
const fixableUpgrade = fixType === ALERT_FIX_TYPE.upgrade
|
|
1989
|
-
const fixable = fixableCve || fixableUpgrade
|
|
1990
|
-
const upgradable = fixableUpgrade && !objects.hasOwn(overrides, name)
|
|
1991
|
-
if (
|
|
1992
|
-
(include.blocked && blocked) ||
|
|
1993
|
-
(include.critical && critical) ||
|
|
1994
|
-
(include.cve && cve) ||
|
|
1995
|
-
(include.unfixable && !fixable) ||
|
|
1996
|
-
(include.upgradable && upgradable)
|
|
1997
|
-
) {
|
|
1998
|
-
sockPkgAlerts.push({
|
|
1999
|
-
name,
|
|
2000
|
-
version,
|
|
2001
|
-
key: alert.key,
|
|
2002
|
-
type: alert.type,
|
|
2003
|
-
blocked,
|
|
2004
|
-
critical,
|
|
2005
|
-
fixable,
|
|
2006
|
-
raw: alert,
|
|
2007
|
-
upgradable
|
|
2008
|
-
})
|
|
2009
|
-
}
|
|
2010
|
-
}
|
|
2011
|
-
if (!sockPkgAlerts.length) {
|
|
2012
|
-
return alertsByPkgId
|
|
2013
|
-
}
|
|
2014
|
-
if (consolidate) {
|
|
2015
|
-
const highestForCve = new Map()
|
|
2016
|
-
const highestForUpgrade = new Map()
|
|
2017
|
-
const unfixableAlerts = []
|
|
2018
|
-
for (const sockPkgAlert of sockPkgAlerts) {
|
|
2019
|
-
const alert = sockPkgAlert.raw
|
|
2020
|
-
const fixType = alert.fix?.type ?? ''
|
|
2021
|
-
if (fixType === ALERT_FIX_TYPE.cve) {
|
|
2022
|
-
const patchedVersion =
|
|
2023
|
-
alert.props[CVE_ALERT_PROPS_FIRST_PATCHED_VERSION_IDENTIFIER]
|
|
2024
|
-
const patchedMajor = vendor.semverExports.major(patchedVersion)
|
|
2025
|
-
const oldHighest = highestForCve.get(patchedMajor)
|
|
2026
|
-
const highest = oldHighest?.version ?? '0.0.0'
|
|
2027
|
-
if (vendor.semverExports.gt(patchedVersion, highest)) {
|
|
2028
|
-
highestForCve.set(patchedMajor, {
|
|
2029
|
-
alert: sockPkgAlert,
|
|
2030
|
-
version: patchedVersion
|
|
2031
|
-
})
|
|
2032
|
-
}
|
|
2033
|
-
} else if (fixType === ALERT_FIX_TYPE.upgrade) {
|
|
2034
|
-
const oldHighest = highestForUpgrade.get(major)
|
|
2035
|
-
const highest = oldHighest?.version ?? '0.0.0'
|
|
2036
|
-
if (vendor.semverExports.gt(version, highest)) {
|
|
2037
|
-
highestForUpgrade.set(major, {
|
|
2038
|
-
alert: sockPkgAlert,
|
|
2039
|
-
version
|
|
2040
|
-
})
|
|
2041
|
-
}
|
|
2042
|
-
} else {
|
|
2043
|
-
unfixableAlerts.push(sockPkgAlert)
|
|
2044
|
-
}
|
|
2045
|
-
}
|
|
2046
|
-
sockPkgAlerts = [
|
|
2047
|
-
...unfixableAlerts,
|
|
2048
|
-
...[...highestForCve.values()].map(d => d.alert),
|
|
2049
|
-
...[...highestForUpgrade.values()].map(d => d.alert)
|
|
2050
|
-
]
|
|
2051
|
-
}
|
|
2052
|
-
if (sockPkgAlerts.length) {
|
|
2053
|
-
sockPkgAlerts.sort((a, b) => sorts.naturalCompare(a.type, b.type))
|
|
2054
|
-
alertsByPkgId.set(pkgId, sockPkgAlerts)
|
|
2055
|
-
}
|
|
2056
|
-
return alertsByPkgId
|
|
2057
|
-
}
|
|
2058
|
-
function getCveInfoByAlertsMap(alertsMap, options) {
|
|
2059
|
-
const exclude = {
|
|
2060
|
-
upgradable: true,
|
|
2061
|
-
...{
|
|
2062
|
-
__proto__: null,
|
|
2063
|
-
...options
|
|
2064
|
-
}.exclude
|
|
2065
|
-
}
|
|
2066
|
-
let infoByPkg = null
|
|
2067
|
-
for (const [pkgId, sockPkgAlerts] of alertsMap) {
|
|
2068
|
-
const purlObj = packageurlJs.PackageURL.fromString(`pkg:npm/${pkgId}`)
|
|
2069
|
-
const name = packages.resolvePackageName(purlObj)
|
|
2070
|
-
for (const sockPkgAlert of sockPkgAlerts) {
|
|
2071
|
-
const alert = sockPkgAlert.raw
|
|
2072
|
-
if (
|
|
2073
|
-
alert.fix?.type !== ALERT_FIX_TYPE.cve ||
|
|
2074
|
-
(exclude.upgradable && registry.getManifestData(NPM$1, name))
|
|
2075
|
-
) {
|
|
2076
|
-
continue
|
|
2077
|
-
}
|
|
2078
|
-
if (!infoByPkg) {
|
|
2079
|
-
infoByPkg = new Map()
|
|
2080
|
-
}
|
|
2081
|
-
let infos = infoByPkg.get(name)
|
|
2082
|
-
if (!infos) {
|
|
2083
|
-
infos = []
|
|
2084
|
-
infoByPkg.set(name, infos)
|
|
2085
|
-
}
|
|
2086
|
-
const { firstPatchedVersionIdentifier, vulnerableVersionRange } =
|
|
2087
|
-
alert.props
|
|
2088
|
-
infos.push({
|
|
2089
|
-
firstPatchedVersionIdentifier,
|
|
2090
|
-
vulnerableVersionRange: new vendor.semverExports.Range(
|
|
2091
|
-
vulnerableVersionRange
|
|
2092
|
-
).format()
|
|
2093
|
-
})
|
|
2094
|
-
}
|
|
2095
|
-
}
|
|
2096
|
-
return infoByPkg
|
|
2097
|
-
}
|
|
2098
|
-
function logAlertsMap(alertsMap, options) {
|
|
2099
|
-
const { hideAt = 'middle', output = process.stderr } = {
|
|
2100
|
-
__proto__: null,
|
|
2101
|
-
...options
|
|
2102
|
-
}
|
|
2103
|
-
const translations = getTranslations()
|
|
2104
|
-
const sortedEntries = [...alertsMap.entries()].sort(
|
|
2105
|
-
(a, b) => getAlertsSeverityOrder(a[1]) - getAlertsSeverityOrder(b[1])
|
|
2106
|
-
)
|
|
2107
|
-
const aboveTheFoldPkgIds = new Set()
|
|
2108
|
-
const viewableAlertsByPkgId = new Map()
|
|
2109
|
-
const hiddenAlertsByPkgId = new Map()
|
|
2110
|
-
for (let i = 0, { length } = sortedEntries; i < length; i += 1) {
|
|
2111
|
-
const { 0: pkgId, 1: alerts } = sortedEntries[i]
|
|
2112
|
-
const hiddenAlerts = []
|
|
2113
|
-
const viewableAlerts = alerts.filter(a => {
|
|
2114
|
-
const keep =
|
|
2115
|
-
a.blocked || getAlertSeverityOrder(a) < ALERT_SEVERITY_ORDER[hideAt]
|
|
2116
|
-
if (!keep) {
|
|
2117
|
-
hiddenAlerts.push(a)
|
|
2118
|
-
}
|
|
2119
|
-
return keep
|
|
2120
|
-
})
|
|
2121
|
-
if (hiddenAlerts.length) {
|
|
2122
|
-
hiddenAlertsByPkgId.set(pkgId, hiddenAlerts.sort(alertSeverityComparator))
|
|
2123
|
-
}
|
|
2124
|
-
if (!viewableAlerts.length) {
|
|
2125
|
-
continue
|
|
2126
|
-
}
|
|
2127
|
-
viewableAlerts.sort(alertSeverityComparator)
|
|
2128
|
-
viewableAlertsByPkgId.set(pkgId, viewableAlerts)
|
|
2129
|
-
if (
|
|
2130
|
-
viewableAlerts.find(
|
|
2131
|
-
a => a.blocked || getAlertSeverityOrder(a) < ALERT_SEVERITY_ORDER.middle
|
|
2132
|
-
)
|
|
2133
|
-
) {
|
|
2134
|
-
aboveTheFoldPkgIds.add(pkgId)
|
|
2135
|
-
}
|
|
2136
|
-
}
|
|
2137
|
-
|
|
2138
|
-
// If MIN_ABOVE_THE_FOLD_COUNT is NOT met add more from viewable pkg ids.
|
|
2139
|
-
for (const { 0: pkgId } of viewableAlertsByPkgId.entries()) {
|
|
2140
|
-
if (aboveTheFoldPkgIds.size >= MIN_ABOVE_THE_FOLD_COUNT) {
|
|
2141
|
-
break
|
|
2142
|
-
}
|
|
2143
|
-
aboveTheFoldPkgIds.add(pkgId)
|
|
2144
|
-
}
|
|
2145
|
-
// If MIN_ABOVE_THE_FOLD_COUNT is STILL NOT met add more from hidden pkg ids.
|
|
2146
|
-
for (const { 0: pkgId, 1: hiddenAlerts } of hiddenAlertsByPkgId.entries()) {
|
|
2147
|
-
if (aboveTheFoldPkgIds.size >= MIN_ABOVE_THE_FOLD_COUNT) {
|
|
2148
|
-
break
|
|
2149
|
-
}
|
|
2150
|
-
aboveTheFoldPkgIds.add(pkgId)
|
|
2151
|
-
const viewableAlerts = viewableAlertsByPkgId.get(pkgId) ?? []
|
|
2152
|
-
if (viewableAlerts.length < MIN_ABOVE_THE_FOLD_ALERT_COUNT) {
|
|
2153
|
-
const neededCount = MIN_ABOVE_THE_FOLD_ALERT_COUNT - viewableAlerts.length
|
|
2154
|
-
let removedHiddenAlerts
|
|
2155
|
-
if (hiddenAlerts.length - neededCount > 0) {
|
|
2156
|
-
removedHiddenAlerts = hiddenAlerts.splice(
|
|
2157
|
-
0,
|
|
2158
|
-
MIN_ABOVE_THE_FOLD_ALERT_COUNT
|
|
2159
|
-
)
|
|
2160
|
-
} else {
|
|
2161
|
-
removedHiddenAlerts = hiddenAlerts
|
|
2162
|
-
hiddenAlertsByPkgId.delete(pkgId)
|
|
2163
|
-
}
|
|
2164
|
-
viewableAlertsByPkgId.set(pkgId, [
|
|
2165
|
-
...viewableAlerts,
|
|
2166
|
-
...removedHiddenAlerts
|
|
2167
|
-
])
|
|
2168
|
-
}
|
|
2169
|
-
}
|
|
2170
|
-
const mentionedPkgIdsWithHiddenAlerts = new Set()
|
|
2171
|
-
for (
|
|
2172
|
-
let i = 0,
|
|
2173
|
-
prevAboveTheFold = true,
|
|
2174
|
-
entries = [...viewableAlertsByPkgId.entries()],
|
|
2175
|
-
{ length } = entries;
|
|
2176
|
-
i < length;
|
|
2177
|
-
i += 1
|
|
2178
|
-
) {
|
|
2179
|
-
const { 0: pkgId, 1: alerts } = entries[i]
|
|
2180
|
-
const lines = new Set()
|
|
2181
|
-
for (const alert of alerts) {
|
|
2182
|
-
const { type } = alert
|
|
2183
|
-
const severity = alert.raw.severity ?? ''
|
|
2184
|
-
const attributes = [
|
|
2185
|
-
...(severity
|
|
2186
|
-
? [
|
|
2187
|
-
vendor.yoctocolorsCjsExports[ALERT_SEVERITY_COLOR[severity]](
|
|
2188
|
-
getSeverityLabel(severity)
|
|
2189
|
-
)
|
|
2190
|
-
]
|
|
2191
|
-
: []),
|
|
2192
|
-
...(alert.blocked
|
|
2193
|
-
? [
|
|
2194
|
-
vendor.yoctocolorsCjsExports.bold(
|
|
2195
|
-
vendor.yoctocolorsCjsExports.red('blocked')
|
|
2196
|
-
)
|
|
2197
|
-
]
|
|
2198
|
-
: []),
|
|
2199
|
-
...(alert.fixable ? ['fixable'] : [])
|
|
2200
|
-
]
|
|
2201
|
-
const maybeAttributes = attributes.length
|
|
2202
|
-
? ` ${vendor.yoctocolorsCjsExports.italic(`(${attributes.join('; ')})`)}`
|
|
2203
|
-
: ''
|
|
2204
|
-
// Based data from { pageProps: { alertTypes } } of:
|
|
2205
|
-
// https://socket.dev/_next/data/94666139314b6437ee4491a0864e72b264547585/en-US.json
|
|
2206
|
-
const info = translations.alerts[type]
|
|
2207
|
-
const title = info?.title ?? type
|
|
2208
|
-
const maybeDesc = info?.description ? ` - ${info.description}` : ''
|
|
2209
|
-
const content = `${title}${maybeAttributes}${maybeDesc}`
|
|
2210
|
-
// TODO: emoji seems to mis-align terminals sometimes
|
|
2211
|
-
lines.add(` ${content}`)
|
|
2212
|
-
}
|
|
2213
|
-
const purlObj = packageurlJs.PackageURL.fromString(`pkg:npm/${pkgId}`)
|
|
2214
|
-
const hyperlink = format.hyperlink(
|
|
2215
|
-
pkgId,
|
|
2216
|
-
getSocketDevPackageOverviewUrl(
|
|
2217
|
-
NPM$1,
|
|
2218
|
-
packages.resolvePackageName(purlObj),
|
|
2219
|
-
purlObj.version
|
|
2220
|
-
)
|
|
2221
|
-
)
|
|
2222
|
-
const isAboveTheFold = aboveTheFoldPkgIds.has(pkgId)
|
|
2223
|
-
if (isAboveTheFold) {
|
|
2224
|
-
aboveTheFoldPkgIds.add(pkgId)
|
|
2225
|
-
output.write(`${i ? '\n' : ''}${hyperlink}:\n`)
|
|
2226
|
-
} else {
|
|
2227
|
-
output.write(`${prevAboveTheFold ? '\n' : ''}${hyperlink}:\n`)
|
|
2228
|
-
}
|
|
2229
|
-
for (const line of lines) {
|
|
2230
|
-
output.write(`${line}\n`)
|
|
2231
|
-
}
|
|
2232
|
-
const hiddenAlerts = hiddenAlertsByPkgId.get(pkgId) ?? []
|
|
2233
|
-
const { length: hiddenAlertsCount } = hiddenAlerts
|
|
2234
|
-
if (hiddenAlertsCount) {
|
|
2235
|
-
mentionedPkgIdsWithHiddenAlerts.add(pkgId)
|
|
2236
|
-
if (hiddenAlertsCount === 1) {
|
|
2237
|
-
output.write(
|
|
2238
|
-
` ${vendor.yoctocolorsCjsExports.dim(`+1 Hidden ${getSeverityLabel(hiddenAlerts[0].raw.severity ?? 'low')} risk alert`)}\n`
|
|
2239
|
-
)
|
|
2240
|
-
} else {
|
|
2241
|
-
output.write(
|
|
2242
|
-
` ${vendor.yoctocolorsCjsExports.dim(`+${hiddenAlertsCount} Hidden alerts ${vendor.yoctocolorsCjsExports.italic(getHiddenRisksDescription(getHiddenRiskCounts(hiddenAlerts)))}`)}\n`
|
|
2243
|
-
)
|
|
2244
|
-
}
|
|
2245
|
-
}
|
|
2246
|
-
prevAboveTheFold = isAboveTheFold
|
|
2247
|
-
}
|
|
2248
|
-
const additionalHiddenCount =
|
|
2249
|
-
hiddenAlertsByPkgId.size - mentionedPkgIdsWithHiddenAlerts.size
|
|
2250
|
-
if (additionalHiddenCount) {
|
|
2251
|
-
const totalRiskCounts = {
|
|
2252
|
-
critical: 0,
|
|
2253
|
-
high: 0,
|
|
2254
|
-
middle: 0,
|
|
2255
|
-
low: 0
|
|
2256
|
-
}
|
|
2257
|
-
for (const { 0: pkgId, 1: alerts } of hiddenAlertsByPkgId.entries()) {
|
|
2258
|
-
if (mentionedPkgIdsWithHiddenAlerts.has(pkgId)) {
|
|
2259
|
-
continue
|
|
2260
|
-
}
|
|
2261
|
-
const riskCounts = getHiddenRiskCounts(alerts)
|
|
2262
|
-
totalRiskCounts.critical += riskCounts.critical
|
|
2263
|
-
totalRiskCounts.high += riskCounts.high
|
|
2264
|
-
totalRiskCounts.middle += riskCounts.middle
|
|
2265
|
-
totalRiskCounts.low += riskCounts.low
|
|
2266
|
-
}
|
|
2267
|
-
output.write(
|
|
2268
|
-
`${aboveTheFoldPkgIds.size ? '\n' : ''}${vendor.yoctocolorsCjsExports.dim(`${aboveTheFoldPkgIds.size ? '+' : ''}${additionalHiddenCount} Packages with hidden alerts ${vendor.yoctocolorsCjsExports.italic(getHiddenRisksDescription(totalRiskCounts))}`)}\n`
|
|
2269
|
-
)
|
|
2270
|
-
}
|
|
2271
|
-
output.write('\n')
|
|
2272
|
-
}
|
|
2273
|
-
|
|
2274
|
-
async function getAlertsMapFromArborist(arb, options_) {
|
|
2275
|
-
const options = {
|
|
2276
|
-
__proto__: null,
|
|
2277
|
-
consolidate: false,
|
|
2278
|
-
nothrow: false,
|
|
2279
|
-
...options_
|
|
2280
|
-
}
|
|
2281
|
-
const include = {
|
|
2282
|
-
__proto__: null,
|
|
2283
|
-
existing: false,
|
|
2284
|
-
...options.include
|
|
2285
|
-
}
|
|
2286
|
-
const needInfoOn = getDetailsFromDiff(arb.diff, {
|
|
2287
|
-
include: {
|
|
2288
|
-
unchanged: include.existing
|
|
2289
|
-
}
|
|
2290
|
-
})
|
|
2291
|
-
const purls = needInfoOn.map(d => `pkg:npm/${d.node.pkgid}`)
|
|
2292
|
-
let overrides
|
|
2293
|
-
const overridesMap = (
|
|
2294
|
-
arb.actualTree ??
|
|
2295
|
-
arb.idealTree ??
|
|
2296
|
-
(await arb.loadActual())
|
|
2297
|
-
)?.overrides?.children
|
|
2298
|
-
if (overridesMap) {
|
|
2299
|
-
overrides = Object.fromEntries(
|
|
2300
|
-
[...overridesMap.entries()].map(([key, overrideSet]) => {
|
|
2301
|
-
return [key, overrideSet.value]
|
|
2302
|
-
})
|
|
2303
|
-
)
|
|
2304
|
-
}
|
|
2305
|
-
return await getAlertsMapFromPurls(purls, {
|
|
2306
|
-
overrides,
|
|
2307
|
-
...options
|
|
2308
|
-
})
|
|
2309
|
-
}
|
|
2310
|
-
async function getAlertsMapFromPnpmLockfile(lockfile, options_) {
|
|
2311
|
-
const options = {
|
|
2312
|
-
__proto__: null,
|
|
2313
|
-
consolidate: false,
|
|
2314
|
-
nothrow: false,
|
|
2315
|
-
...options_
|
|
2316
|
-
}
|
|
2317
|
-
const depTypes = vendor.libExports$1.detectDepTypes(lockfile)
|
|
2318
|
-
const purls = Object.keys(depTypes).map(id => `pkg:npm/${id}`)
|
|
2319
|
-
return await getAlertsMapFromPurls(purls, {
|
|
2320
|
-
overrides: lockfile.overrides,
|
|
2321
|
-
...options
|
|
2322
|
-
})
|
|
2323
|
-
}
|
|
2324
|
-
async function getAlertsMapFromPurls(purls, options_) {
|
|
2325
|
-
const options = {
|
|
2326
|
-
__proto__: null,
|
|
2327
|
-
consolidate: false,
|
|
2328
|
-
nothrow: false,
|
|
2329
|
-
...options_
|
|
2330
|
-
}
|
|
2331
|
-
const include = {
|
|
2332
|
-
__proto__: null,
|
|
2333
|
-
actions: undefined,
|
|
2334
|
-
blocked: true,
|
|
2335
|
-
critical: true,
|
|
2336
|
-
cve: true,
|
|
2337
|
-
existing: false,
|
|
2338
|
-
unfixable: true,
|
|
2339
|
-
upgradable: false,
|
|
2340
|
-
...options.include
|
|
2341
|
-
}
|
|
2342
|
-
const { spinner } = options
|
|
2343
|
-
const uniqPurls = arrays.arrayUnique(purls)
|
|
2344
|
-
let { length: remaining } = uniqPurls
|
|
2345
|
-
const alertsByPkgId = new Map()
|
|
2346
|
-
if (!remaining) {
|
|
2347
|
-
return alertsByPkgId
|
|
2348
|
-
}
|
|
2349
|
-
const getText = () => `Looking up data for ${remaining} packages`
|
|
2350
|
-
spinner?.start(getText())
|
|
2351
|
-
const sockSdk = await setupSdk(getPublicToken())
|
|
2352
|
-
const toAlertsMapOptions = {
|
|
2353
|
-
overrides: options.overrides,
|
|
2354
|
-
consolidate: options.consolidate,
|
|
2355
|
-
include,
|
|
2356
|
-
spinner
|
|
2357
|
-
}
|
|
2358
|
-
for await (const batchResult of sockSdk.batchPackageStream(
|
|
2359
|
-
{
|
|
2360
|
-
alerts: 'true',
|
|
2361
|
-
compact: 'true',
|
|
2362
|
-
...(include.actions
|
|
2363
|
-
? {
|
|
2364
|
-
actions: include.actions.join(',')
|
|
2365
|
-
}
|
|
2366
|
-
: {}),
|
|
2367
|
-
...(include.unfixable
|
|
2368
|
-
? {}
|
|
2369
|
-
: {
|
|
2370
|
-
fixable: 'true'
|
|
2371
|
-
})
|
|
2372
|
-
},
|
|
2373
|
-
{
|
|
2374
|
-
components: uniqPurls.map(purl => ({
|
|
2375
|
-
purl
|
|
2376
|
-
}))
|
|
2377
|
-
}
|
|
2378
|
-
)) {
|
|
2379
|
-
if (batchResult.success) {
|
|
2380
|
-
await addArtifactToAlertsMap(
|
|
2381
|
-
batchResult.data,
|
|
2382
|
-
alertsByPkgId,
|
|
2383
|
-
toAlertsMapOptions
|
|
2384
|
-
)
|
|
2385
|
-
} else if (!options.nothrow) {
|
|
2386
|
-
const statusCode = batchResult.status ?? 'unknown'
|
|
2387
|
-
const statusMessage = batchResult.error ?? 'No status message'
|
|
2388
|
-
throw new Error(
|
|
2389
|
-
`Socket API server error (${statusCode}): ${statusMessage}`
|
|
2390
|
-
)
|
|
2391
|
-
}
|
|
2392
|
-
remaining -= 1
|
|
2393
|
-
if (spinner && remaining > 0) {
|
|
2394
|
-
spinner.start()
|
|
2395
|
-
spinner.setText(getText())
|
|
2396
|
-
}
|
|
2397
|
-
}
|
|
2398
|
-
spinner?.stop()
|
|
2399
|
-
return alertsByPkgId
|
|
2400
|
-
}
|
|
2401
|
-
|
|
2402
|
-
const {
|
|
2403
|
-
NPM,
|
|
2404
|
-
NPX,
|
|
2405
|
-
SOCKET_CLI_ACCEPT_RISKS,
|
|
2406
|
-
SOCKET_CLI_SAFE_BIN,
|
|
2407
|
-
SOCKET_CLI_SAFE_PROGRESS,
|
|
2408
|
-
SOCKET_CLI_VIEW_ALL_RISKS,
|
|
2409
|
-
kInternalsSymbol,
|
|
2410
|
-
[kInternalsSymbol]: { getIpc }
|
|
2411
|
-
} = constants
|
|
2412
|
-
const SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES = {
|
|
2413
|
-
__proto__: null,
|
|
2414
|
-
audit: false,
|
|
2415
|
-
dryRun: true,
|
|
2416
|
-
fund: false,
|
|
2417
|
-
ignoreScripts: true,
|
|
2418
|
-
progress: false,
|
|
2419
|
-
save: false,
|
|
2420
|
-
saveBundle: false,
|
|
2421
|
-
silent: true
|
|
2422
|
-
}
|
|
2423
|
-
const kCtorArgs = Symbol('ctorArgs')
|
|
2424
|
-
const kRiskyReify = Symbol('riskyReify')
|
|
2425
|
-
const Arborist = require(shadowNpmPaths.getArboristClassPath())
|
|
2426
|
-
|
|
2427
|
-
// Implementation code not related to our custom behavior is based on
|
|
2428
|
-
// https://github.com/npm/cli/blob/v11.0.0/workspaces/arborist/lib/arborist/index.js:
|
|
2429
|
-
class SafeArborist extends Arborist {
|
|
2430
|
-
constructor(...ctorArgs) {
|
|
2431
|
-
super(
|
|
2432
|
-
{
|
|
2433
|
-
path:
|
|
2434
|
-
(ctorArgs.length ? ctorArgs[0]?.path : undefined) ?? process$1.cwd(),
|
|
2435
|
-
...(ctorArgs.length ? ctorArgs[0] : undefined),
|
|
2436
|
-
...SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES
|
|
2437
|
-
},
|
|
2438
|
-
...ctorArgs.slice(1)
|
|
2439
|
-
)
|
|
2440
|
-
this[kCtorArgs] = ctorArgs
|
|
2441
|
-
}
|
|
2442
|
-
async [kRiskyReify](...args) {
|
|
2443
|
-
const ctorArgs = this[kCtorArgs]
|
|
2444
|
-
const arb = new Arborist(
|
|
2445
|
-
{
|
|
2446
|
-
...(ctorArgs.length ? ctorArgs[0] : undefined),
|
|
2447
|
-
progress: false
|
|
2448
|
-
},
|
|
2449
|
-
...ctorArgs.slice(1)
|
|
2450
|
-
)
|
|
2451
|
-
const ret = await arb.reify(
|
|
2452
|
-
{
|
|
2453
|
-
...(args.length ? args[0] : undefined),
|
|
2454
|
-
progress: false
|
|
2455
|
-
},
|
|
2456
|
-
...args.slice(1)
|
|
2457
|
-
)
|
|
2458
|
-
Object.assign(this, arb)
|
|
2459
|
-
return ret
|
|
2460
|
-
}
|
|
2461
|
-
|
|
2462
|
-
// @ts-ignore Incorrectly typed.
|
|
2463
|
-
async reify(...args) {
|
|
2464
|
-
const options = {
|
|
2465
|
-
__proto__: null,
|
|
2466
|
-
...(args.length ? args[0] : undefined)
|
|
2467
|
-
}
|
|
2468
|
-
const ipc = await getIpc()
|
|
2469
|
-
const binName = ipc[SOCKET_CLI_SAFE_BIN]
|
|
2470
|
-
if (!binName) {
|
|
2471
|
-
return await this[kRiskyReify](...args)
|
|
2472
|
-
}
|
|
2473
|
-
await super.reify(
|
|
2474
|
-
{
|
|
2475
|
-
...options,
|
|
2476
|
-
...SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES,
|
|
2477
|
-
progress: false
|
|
2478
|
-
},
|
|
2479
|
-
// @ts-ignore: TypeScript gets grumpy about rest parameters.
|
|
2480
|
-
...args.slice(1)
|
|
2481
|
-
)
|
|
2482
|
-
// Lazily access constants.ENV[SOCKET_CLI_ACCEPT_RISKS].
|
|
2483
|
-
const acceptRisks = constants.ENV[SOCKET_CLI_ACCEPT_RISKS]
|
|
2484
|
-
// Lazily access constants.ENV[SOCKET_CLI_VIEW_ALL_RISKS].
|
|
2485
|
-
const viewAllRisks = constants.ENV[SOCKET_CLI_VIEW_ALL_RISKS]
|
|
2486
|
-
const progress = ipc[SOCKET_CLI_SAFE_PROGRESS]
|
|
2487
|
-
const spinner =
|
|
2488
|
-
options['silent'] || !progress
|
|
2489
|
-
? undefined
|
|
2490
|
-
: // Lazily access constants.spinner.
|
|
2491
|
-
constants.spinner
|
|
2492
|
-
const isSafeNpm = binName === NPM
|
|
2493
|
-
const isSafeNpx = binName === NPX
|
|
2494
|
-
const alertsMap = await getAlertsMapFromArborist(this, {
|
|
2495
|
-
spinner,
|
|
2496
|
-
include:
|
|
2497
|
-
acceptRisks || options.dryRun || options['yes']
|
|
2498
|
-
? {
|
|
2499
|
-
actions: ['error'],
|
|
2500
|
-
blocked: true,
|
|
2501
|
-
critical: false,
|
|
2502
|
-
cve: false,
|
|
2503
|
-
existing: true,
|
|
2504
|
-
unfixable: false
|
|
2505
|
-
}
|
|
2506
|
-
: {
|
|
2507
|
-
existing: isSafeNpx,
|
|
2508
|
-
unfixable: isSafeNpm
|
|
2509
|
-
}
|
|
2510
|
-
})
|
|
2511
|
-
if (alertsMap.size) {
|
|
2512
|
-
process$1.exitCode = 1
|
|
2513
|
-
logAlertsMap(alertsMap, {
|
|
2514
|
-
hideAt: viewAllRisks ? 'none' : 'middle',
|
|
2515
|
-
output: process$1.stderr
|
|
2516
|
-
})
|
|
2517
|
-
throw new Error(vendor.html`
|
|
2518
|
-
Socket ${binName} exiting due to risks.${viewAllRisks ? '' : `\nView all risks - Rerun with environment variable ${SOCKET_CLI_VIEW_ALL_RISKS}=1.`}${acceptRisks ? '' : `\nAccept risks - Rerun with environment variable ${SOCKET_CLI_ACCEPT_RISKS}=1.`}
|
|
2519
|
-
`)
|
|
2520
|
-
} else if (!options['silent']) {
|
|
2521
|
-
logger.logger.success(
|
|
2522
|
-
`Socket ${binName} ${acceptRisks ? 'accepted' : 'found no'} risks`
|
|
2523
|
-
)
|
|
2524
|
-
if (binName === NPX) {
|
|
2525
|
-
logger.logger.log(`Running ${options.add[0]}`)
|
|
2526
|
-
}
|
|
2527
|
-
}
|
|
2528
|
-
return await this[kRiskyReify](...args)
|
|
2529
|
-
}
|
|
2530
|
-
}
|
|
2531
|
-
|
|
2532
|
-
function installSafeArborist() {
|
|
2533
|
-
// Override '@npmcli/arborist' module exports with patched variants based on
|
|
2534
|
-
// https://github.com/npm/cli/pull/8089.
|
|
2535
|
-
const cache = require.cache
|
|
2536
|
-
cache[shadowNpmPaths.getArboristClassPath()] = {
|
|
2537
|
-
exports: SafeArborist
|
|
2538
|
-
}
|
|
2539
|
-
cache[shadowNpmPaths.getArboristEdgeClassPath()] = {
|
|
2540
|
-
exports: SafeEdge
|
|
2541
|
-
}
|
|
2542
|
-
cache[shadowNpmPaths.getArboristNodeClassPath()] = {
|
|
2543
|
-
exports: SafeNode
|
|
2544
|
-
}
|
|
2545
|
-
cache[shadowNpmPaths.getArboristOverrideSetClassPath()] = {
|
|
2546
|
-
exports: SafeOverrideSet
|
|
2547
|
-
}
|
|
2548
|
-
}
|
|
2549
|
-
|
|
2550
|
-
installSafeArborist()
|
|
2551
|
-
|
|
2552
|
-
exports.ALERT_SEVERITY = ALERT_SEVERITY
|
|
2553
|
-
exports.Arborist = Arborist
|
|
2554
|
-
exports.AuthError = AuthError
|
|
2555
|
-
exports.ColorOrMarkdown = ColorOrMarkdown
|
|
2556
|
-
exports.InputError = InputError
|
|
2557
|
-
exports.RangeStyles = RangeStyles
|
|
2558
|
-
exports.SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES =
|
|
2559
|
-
SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES
|
|
2560
|
-
exports.SafeArborist = SafeArborist
|
|
2561
|
-
exports.applyRange = applyRange
|
|
2562
|
-
exports.captureException = captureException
|
|
2563
|
-
exports.filterGlobResultToSupportedFiles = filterGlobResultToSupportedFiles
|
|
2564
|
-
exports.findBestPatchVersion = findBestPatchVersion
|
|
2565
|
-
exports.findPackageNode = findPackageNode
|
|
2566
|
-
exports.findPackageNodes = findPackageNodes
|
|
2567
|
-
exports.findUp = findUp
|
|
2568
|
-
exports.formatSeverityCount = formatSeverityCount
|
|
2569
|
-
exports.getAlertsMapFromArborist = getAlertsMapFromArborist
|
|
2570
|
-
exports.getAlertsMapFromPnpmLockfile = getAlertsMapFromPnpmLockfile
|
|
2571
|
-
exports.getAlertsMapFromPurls = getAlertsMapFromPurls
|
|
2572
|
-
exports.getConfigValue = getConfigValue
|
|
2573
|
-
exports.getCveInfoByAlertsMap = getCveInfoByAlertsMap
|
|
2574
|
-
exports.getDefaultToken = getDefaultToken
|
|
2575
|
-
exports.getPublicToken = getPublicToken
|
|
2576
|
-
exports.getSeverityCount = getSeverityCount
|
|
2577
|
-
exports.getSocketDevAlertUrl = getSocketDevAlertUrl
|
|
2578
|
-
exports.getSocketDevPackageOverviewUrl = getSocketDevPackageOverviewUrl
|
|
2579
|
-
exports.globWithGitIgnore = globWithGitIgnore
|
|
2580
|
-
exports.globWorkspace = globWorkspace
|
|
2581
|
-
exports.isReadOnlyConfig = isReadOnlyConfig
|
|
2582
|
-
exports.overrideCachedConfig = overrideCachedConfig
|
|
2583
|
-
exports.overrideConfigApiToken = overrideConfigApiToken
|
|
2584
|
-
exports.pathsToGlobPatterns = pathsToGlobPatterns
|
|
2585
|
-
exports.readFileBinary = readFileBinary
|
|
2586
|
-
exports.readFileUtf8 = readFileUtf8
|
|
2587
|
-
exports.removeNodeModules = removeNodeModules
|
|
2588
|
-
exports.safeReadFile = safeReadFile
|
|
2589
|
-
exports.sensitiveConfigKeys = sensitiveConfigKeys
|
|
2590
|
-
exports.setupSdk = setupSdk
|
|
2591
|
-
exports.supportedConfigKeys = supportedConfigKeys
|
|
2592
|
-
exports.updateConfigValue = updateConfigValue
|
|
2593
|
-
exports.updateNode = updateNode
|
|
2594
|
-
exports.updatePackageJsonFromNode = updatePackageJsonFromNode
|
|
2595
|
-
//# debugId=958a7911-f71e-4666-9f2e-6ffcd2e9511c
|
|
2596
|
-
//# sourceMappingURL=shadow-npm-inject.js.map
|