@socketsecurity/cli-with-sentry 0.14.154 → 0.14.155
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.config/tsconfig.dts.tsbuildinfo +1 -1
- package/dist/cli.js +1289 -2453
- package/dist/cli.js.map +1 -1
- package/dist/constants.js +7 -6
- package/dist/constants.js.map +1 -1
- package/dist/instrument-with-sentry.js +10 -3
- package/dist/instrument-with-sentry.js.map +1 -1
- package/dist/shadow-bin.js +5 -7
- package/dist/shadow-bin.js.map +1 -1
- package/dist/shadow-npm-inject.js +130 -1646
- package/dist/shadow-npm-inject.js.map +1 -1
- package/dist/types/commands/analytics/cmd-analytics.d.mts.map +1 -1
- package/dist/types/commands/analytics/fetch-org-analytics.d.mts.map +1 -1
- package/dist/types/commands/analytics/fetch-repo-analytics.d.mts.map +1 -1
- package/dist/types/commands/analytics/handle-analytics.d.mts.map +1 -1
- package/dist/types/commands/analytics/output-analytics.d.mts +15 -16
- package/dist/types/commands/analytics/output-analytics.d.mts.map +1 -1
- package/dist/types/commands/audit-log/fetch-audit-log.d.mts.map +1 -1
- package/dist/types/commands/cdxgen/cmd-cdxgen.d.mts.map +1 -1
- package/dist/types/commands/ci/fetch-default-org-slug.d.mts.map +1 -1
- package/dist/types/commands/dependencies/fetch-dependencies.d.mts.map +1 -1
- package/dist/types/commands/diff-scan/fetch-diff-scan.d.mts.map +1 -1
- package/dist/types/commands/fix/git.d.mts +9 -1
- package/dist/types/commands/fix/git.d.mts.map +1 -1
- package/dist/types/commands/fix/npm-fix.d.mts.map +1 -1
- package/dist/types/commands/fix/open-pr.d.mts +30 -16
- package/dist/types/commands/fix/open-pr.d.mts.map +1 -1
- package/dist/types/commands/fix/pnpm-fix.d.mts.map +1 -1
- package/dist/types/commands/info/fetch-package-info.d.mts.map +1 -1
- package/dist/types/commands/login/attempt-login.d.mts.map +1 -1
- package/dist/types/commands/npm/wrap-npm.d.mts.map +1 -1
- package/dist/types/commands/npx/wrap-npx.d.mts.map +1 -1
- package/dist/types/commands/optimize/deps-includes-by-agent.d.mts +1 -1
- package/dist/types/commands/optimize/get-overrides-by-agent.d.mts +1 -1
- package/dist/types/commands/optimize/lockfile-includes-by-agent.d.mts +1 -1
- package/dist/types/commands/optimize/ls-by-agent.d.mts +1 -1
- package/dist/types/commands/optimize/update-manifest-by-agent.d.mts +1 -1
- package/dist/types/commands/organization/fetch-license-policy.d.mts.map +1 -1
- package/dist/types/commands/organization/fetch-organization-list.d.mts.map +1 -1
- package/dist/types/commands/organization/fetch-quota.d.mts.map +1 -1
- package/dist/types/commands/organization/fetch-security-policy.d.mts.map +1 -1
- package/dist/types/commands/package/fetch-purl-deep-score.d.mts.map +1 -1
- package/dist/types/commands/package/fetch-purls-shallow-score.d.mts.map +1 -1
- package/dist/types/commands/repos/fetch-create-repo.d.mts.map +1 -1
- package/dist/types/commands/repos/fetch-delete-repo.d.mts.map +1 -1
- package/dist/types/commands/repos/fetch-list-repos.d.mts.map +1 -1
- package/dist/types/commands/repos/fetch-update-repo.d.mts.map +1 -1
- package/dist/types/commands/repos/fetch-view-repo.d.mts.map +1 -1
- package/dist/types/commands/repos/handle-create-repo.d.mts.map +1 -1
- package/dist/types/commands/repos/output-create-repo.d.mts +1 -1
- package/dist/types/commands/repos/output-create-repo.d.mts.map +1 -1
- package/dist/types/commands/scan/fetch-create-org-full-scan.d.mts.map +1 -1
- package/dist/types/commands/scan/fetch-delete-org-full-scan.d.mts.map +1 -1
- package/dist/types/commands/scan/fetch-diff-scan.d.mts.map +1 -1
- package/dist/types/commands/scan/fetch-list-scans.d.mts.map +1 -1
- package/dist/types/commands/scan/fetch-report-data.d.mts.map +1 -1
- package/dist/types/commands/scan/fetch-scan-metadata.d.mts.map +1 -1
- package/dist/types/commands/scan/fetch-supported-scan-file-names.d.mts.map +1 -1
- package/dist/types/commands/scan/stream-scan.d.mts +1 -1
- package/dist/types/commands/scan/stream-scan.d.mts.map +1 -1
- package/dist/types/commands/scan/suggest-org-slug.d.mts.map +1 -1
- package/dist/types/commands/threat-feed/output-threat-feed.d.mts.map +1 -1
- package/dist/types/constants.d.mts +1 -1
- package/dist/types/constants.d.mts.map +1 -1
- package/dist/types/shadow/npm/arborist/lib/dep-valid.d.mts +2 -2
- package/dist/types/shadow/npm/arborist/lib/dep-valid.d.mts.map +1 -1
- package/dist/types/{utils → shadow/npm}/arborist-helpers.d.mts +19 -3
- package/dist/types/shadow/npm/arborist-helpers.d.mts.map +1 -0
- package/dist/types/{utils/npm.d.mts → shadow/npm/install.d.mts} +2 -2
- package/dist/types/shadow/npm/install.d.mts.map +1 -0
- package/dist/types/shadow/npm/paths.d.mts +0 -6
- package/dist/types/shadow/npm/paths.d.mts.map +1 -1
- package/dist/types/utils/agent.d.mts +2 -2
- package/dist/types/utils/agent.d.mts.map +1 -1
- package/dist/types/utils/alerts-map.d.mts +0 -11
- package/dist/types/utils/alerts-map.d.mts.map +1 -1
- package/dist/types/utils/api.d.mts +15 -5
- package/dist/types/utils/api.d.mts.map +1 -1
- package/dist/types/utils/npm-paths.d.mts +7 -0
- package/dist/types/utils/npm-paths.d.mts.map +1 -0
- package/dist/types/utils/pnpm.d.mts +2 -1
- package/dist/types/utils/pnpm.d.mts.map +1 -1
- package/dist/types/utils/translations.d.mts.map +1 -1
- package/dist/utils.js +3169 -0
- package/dist/utils.js.map +1 -0
- package/dist/vendor.js +1284 -1231
- package/dist/vendor.js.map +1 -1
- package/external/@socketsecurity/registry/external/browserslist.js +382 -366
- package/external/@socketsecurity/registry/external/browserslist.js.map +1 -1
- package/external/@socketsecurity/registry/lib/constants/maintained-node-versions.js +7 -8
- package/external/@socketsecurity/registry/lib/fs.d.ts +6 -4
- package/external/@socketsecurity/registry/package.json +5 -5
- package/package.json +19 -19
- package/dist/shadow-npm-paths.js +0 -291
- package/dist/shadow-npm-paths.js.map +0 -1
- package/dist/types/utils/arborist-helpers.d.mts.map +0 -1
- package/dist/types/utils/npm.d.mts.map +0 -1
|
@@ -1,777 +1,96 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const Module = require('node:module')
|
|
4
|
-
const
|
|
5
|
-
const
|
|
4
|
+
const path = require('node:path')
|
|
5
|
+
const path$1 = require('../external/@socketsecurity/registry/lib/path')
|
|
6
6
|
const constants = require('./constants.js')
|
|
7
|
-
const
|
|
7
|
+
const utils = require('./utils.js')
|
|
8
|
+
const logger = require('../external/@socketsecurity/registry/lib/logger')
|
|
8
9
|
const vendor = require('./vendor.js')
|
|
9
10
|
const registry = require('../external/@socketsecurity/registry')
|
|
10
11
|
const objects = require('../external/@socketsecurity/registry/lib/objects')
|
|
11
|
-
const debug = require('../external/@socketsecurity/registry/lib/debug')
|
|
12
|
-
const packages = require('../external/@socketsecurity/registry/lib/packages')
|
|
13
|
-
const prompts = require('../external/@socketsecurity/registry/lib/prompts')
|
|
14
|
-
const strings = require('../external/@socketsecurity/registry/lib/strings')
|
|
15
|
-
const fs = require('node:fs')
|
|
16
|
-
const os = require('node:os')
|
|
17
|
-
const path = require('node:path')
|
|
18
|
-
const fs$1 = require('../external/@socketsecurity/registry/lib/fs')
|
|
19
|
-
const promises = require('node:timers/promises')
|
|
20
|
-
const sorts = require('../external/@socketsecurity/registry/lib/sorts')
|
|
21
12
|
|
|
22
13
|
const _documentCurrentScript =
|
|
23
14
|
typeof document !== 'undefined' ? document.currentScript : null
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
'.git',
|
|
30
|
-
// Git repository files, see <https://git-scm.com/>
|
|
31
|
-
'.log',
|
|
32
|
-
// Log files emitted by tools such as `tsserver`, see <https://github.com/Microsoft/TypeScript/wiki/Standalone-Server-%28tsserver%29>
|
|
33
|
-
'.nyc_output',
|
|
34
|
-
// Temporary directory where nyc stores coverage data, see <https://github.com/bcoe/nyc>
|
|
35
|
-
'.sass-cache',
|
|
36
|
-
// Cache folder for node-sass, see <https://github.com/sass/node-sass>
|
|
37
|
-
'.yarn',
|
|
38
|
-
// Where node modules are installed when using Yarn, see <https://yarnpkg.com/>
|
|
39
|
-
'bower_components',
|
|
40
|
-
// Where Bower packages are installed, see <http://bower.io/>
|
|
41
|
-
'coverage',
|
|
42
|
-
// Standard output directory for code coverage reports, see <https://github.com/gotwarlost/istanbul>
|
|
43
|
-
'node_modules',
|
|
44
|
-
// Where Node modules are installed, see <https://nodejs.org/>
|
|
45
|
-
// Taken from globby:
|
|
46
|
-
// https://github.com/sindresorhus/globby/blob/v14.0.2/ignore.js#L11-L16
|
|
47
|
-
'flow-typed'
|
|
48
|
-
]
|
|
49
|
-
const ignoredDirPatterns = ignoredDirs.map(i => `**/${i}`)
|
|
50
|
-
async function getWorkspaceGlobs(agent, cwd = process.cwd()) {
|
|
51
|
-
let workspacePatterns
|
|
52
|
-
if (agent === PNPM) {
|
|
53
|
-
for (const workspacePath of [
|
|
54
|
-
path.join(cwd, `${PNPM_WORKSPACE}.yaml`),
|
|
55
|
-
path.join(cwd, `${PNPM_WORKSPACE}.yml`)
|
|
56
|
-
]) {
|
|
57
|
-
// eslint-disable-next-line no-await-in-loop
|
|
58
|
-
const yml = await safeReadFile(workspacePath)
|
|
59
|
-
if (yml) {
|
|
60
|
-
try {
|
|
61
|
-
workspacePatterns = vendor.distExports$1.parse(yml)?.packages
|
|
62
|
-
} catch {}
|
|
63
|
-
if (workspacePatterns) {
|
|
64
|
-
break
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
} else {
|
|
69
|
-
workspacePatterns = (
|
|
70
|
-
await packages.readPackageJson(cwd, {
|
|
71
|
-
throws: false
|
|
72
|
-
})
|
|
73
|
-
)?.['workspaces']
|
|
74
|
-
}
|
|
75
|
-
return Array.isArray(workspacePatterns)
|
|
76
|
-
? workspacePatterns
|
|
77
|
-
.filter(strings.isNonEmptyString)
|
|
78
|
-
.map(workspacePatternToGlobPattern)
|
|
79
|
-
: []
|
|
80
|
-
}
|
|
81
|
-
function ignoreFileLinesToGlobPatterns(lines, filepath, cwd) {
|
|
82
|
-
const base = path.relative(cwd, path.dirname(filepath)).replace(/\\/g, '/')
|
|
83
|
-
const patterns = []
|
|
84
|
-
for (let i = 0, { length } = lines; i < length; i += 1) {
|
|
85
|
-
const pattern = lines[i].trim()
|
|
86
|
-
if (pattern.length > 0 && pattern.charCodeAt(0) !== 35 /*'#'*/) {
|
|
87
|
-
patterns.push(
|
|
88
|
-
ignorePatternToMinimatch(
|
|
89
|
-
pattern.length && pattern.charCodeAt(0) === 33 /*'!'*/
|
|
90
|
-
? `!${path.posix.join(base, pattern.slice(1))}`
|
|
91
|
-
: path.posix.join(base, pattern)
|
|
92
|
-
)
|
|
93
|
-
)
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
return patterns
|
|
97
|
-
}
|
|
98
|
-
function ignoreFileToGlobPatterns(content, filepath, cwd) {
|
|
99
|
-
return ignoreFileLinesToGlobPatterns(content.split(/\r?\n/), filepath, cwd)
|
|
100
|
-
}
|
|
15
|
+
const DiffAction = utils.createEnum({
|
|
16
|
+
add: 'ADD',
|
|
17
|
+
change: 'CHANGE',
|
|
18
|
+
remove: 'REMOVE'
|
|
19
|
+
})
|
|
101
20
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
patternToTest === '' ||
|
|
113
|
-
patternToTest === '**' ||
|
|
114
|
-
patternToTest === '/**' ||
|
|
115
|
-
patternToTest === '**'
|
|
116
|
-
) {
|
|
117
|
-
return `${negatedPrefix}${patternToTest}`
|
|
118
|
-
}
|
|
119
|
-
const firstIndexOfSlash = patternToTest.indexOf('/')
|
|
120
|
-
const matchEverywherePrefix =
|
|
121
|
-
firstIndexOfSlash === -1 || firstIndexOfSlash === patternToTest.length - 1
|
|
122
|
-
? '**/'
|
|
123
|
-
: ''
|
|
124
|
-
const patternWithoutLeadingSlash =
|
|
125
|
-
firstIndexOfSlash === 0 ? patternToTest.slice(1) : patternToTest
|
|
126
|
-
// Escape `{` and `(` because in gitignore patterns they are just
|
|
127
|
-
// literal characters without any specific syntactic meaning,
|
|
128
|
-
// while in minimatch patterns they can form brace expansion or extglob syntax.
|
|
129
|
-
//
|
|
130
|
-
// For example, gitignore pattern `src/{a,b}.js` ignores file `src/{a,b}.js`.
|
|
131
|
-
// But, the same minimatch pattern `src/{a,b}.js` ignores files `src/a.js` and `src/b.js`.
|
|
132
|
-
// Minimatch pattern `src/\{a,b}.js` is equivalent to gitignore pattern `src/{a,b}.js`.
|
|
133
|
-
const escapedPatternWithoutLeadingSlash =
|
|
134
|
-
patternWithoutLeadingSlash.replaceAll(
|
|
135
|
-
/(?=((?:\\.|[^{(])*))\1([{(])/guy,
|
|
136
|
-
'$1\\$2'
|
|
21
|
+
let _arboristPkgPath
|
|
22
|
+
function getArboristPackagePath() {
|
|
23
|
+
if (_arboristPkgPath === undefined) {
|
|
24
|
+
const pkgName = '@npmcli/arborist'
|
|
25
|
+
const mainPathWithForwardSlashes = path$1.normalizePath(
|
|
26
|
+
utils.getNpmRequire().resolve(pkgName)
|
|
27
|
+
)
|
|
28
|
+
const arboristPkgPathWithForwardSlashes = mainPathWithForwardSlashes.slice(
|
|
29
|
+
0,
|
|
30
|
+
mainPathWithForwardSlashes.lastIndexOf(pkgName) + pkgName.length
|
|
137
31
|
)
|
|
138
|
-
const matchInsideSuffix = patternToTest.endsWith('/**') ? '/*' : ''
|
|
139
|
-
return `${negatedPrefix}${matchEverywherePrefix}${escapedPatternWithoutLeadingSlash}${matchInsideSuffix}`
|
|
140
|
-
}
|
|
141
|
-
function workspacePatternToGlobPattern(workspace) {
|
|
142
|
-
const { length } = workspace
|
|
143
|
-
if (!length) {
|
|
144
|
-
return ''
|
|
145
|
-
}
|
|
146
|
-
// If the workspace ends with "/"
|
|
147
|
-
if (workspace.charCodeAt(length - 1) === 47 /*'/'*/) {
|
|
148
|
-
return `${workspace}/*/package.json`
|
|
149
|
-
}
|
|
150
|
-
// If the workspace ends with "/**"
|
|
151
|
-
if (
|
|
152
|
-
workspace.charCodeAt(length - 1) === 42 /*'*'*/ &&
|
|
153
|
-
workspace.charCodeAt(length - 2) === 42 /*'*'*/ &&
|
|
154
|
-
workspace.charCodeAt(length - 3) === 47 /*'/'*/
|
|
155
|
-
) {
|
|
156
|
-
return `${workspace}/*/**/package.json`
|
|
157
|
-
}
|
|
158
|
-
// Things like "packages/a" or "packages/*"
|
|
159
|
-
return `${workspace}/package.json`
|
|
160
|
-
}
|
|
161
|
-
async function filterGlobResultToSupportedFiles(entries, supportedFiles) {
|
|
162
|
-
const patterns = ['golang', NPM$3, 'maven', 'pypi', 'gem', 'nuget'].reduce(
|
|
163
|
-
(r, n) => {
|
|
164
|
-
const supported = supportedFiles[n]
|
|
165
|
-
r.push(
|
|
166
|
-
...(supported
|
|
167
|
-
? Object.values(supported).map(p => `**/${p.pattern}`)
|
|
168
|
-
: [])
|
|
169
|
-
)
|
|
170
|
-
return r
|
|
171
|
-
},
|
|
172
|
-
[]
|
|
173
|
-
)
|
|
174
|
-
return entries.filter(p => vendor.micromatchExports.some(p, patterns))
|
|
175
|
-
}
|
|
176
|
-
async function globWithGitIgnore(patterns, options) {
|
|
177
|
-
const {
|
|
178
|
-
cwd = process.cwd(),
|
|
179
|
-
socketConfig,
|
|
180
|
-
...additionalOptions
|
|
181
|
-
} = {
|
|
182
|
-
__proto__: null,
|
|
183
|
-
...options
|
|
184
|
-
}
|
|
185
|
-
const projectIgnorePaths = socketConfig?.projectIgnorePaths
|
|
186
|
-
const ignoreFiles = await vendor.distExports.glob(['**/.gitignore'], {
|
|
187
|
-
absolute: true,
|
|
188
|
-
cwd,
|
|
189
|
-
expandDirectories: true
|
|
190
|
-
})
|
|
191
|
-
const ignores = [
|
|
192
|
-
...ignoredDirPatterns,
|
|
193
|
-
...(Array.isArray(projectIgnorePaths)
|
|
194
|
-
? ignoreFileLinesToGlobPatterns(
|
|
195
|
-
projectIgnorePaths,
|
|
196
|
-
path.join(cwd, '.gitignore'),
|
|
197
|
-
cwd
|
|
198
|
-
)
|
|
199
|
-
: []),
|
|
200
|
-
...(
|
|
201
|
-
await Promise.all(
|
|
202
|
-
ignoreFiles.map(async filepath =>
|
|
203
|
-
ignoreFileToGlobPatterns(
|
|
204
|
-
await fs.promises.readFile(filepath, 'utf8'),
|
|
205
|
-
filepath,
|
|
206
|
-
cwd
|
|
207
|
-
)
|
|
208
|
-
)
|
|
209
|
-
)
|
|
210
|
-
).flat()
|
|
211
|
-
]
|
|
212
|
-
const hasNegatedPattern = ignores.some(p => p.charCodeAt(0) === 33 /*'!'*/)
|
|
213
|
-
const globOptions = {
|
|
214
|
-
absolute: true,
|
|
215
|
-
cwd,
|
|
216
|
-
expandDirectories: false,
|
|
217
|
-
ignore: hasNegatedPattern ? [] : ignores,
|
|
218
|
-
...additionalOptions
|
|
219
|
-
}
|
|
220
|
-
const result = await vendor.distExports.glob(patterns, globOptions)
|
|
221
|
-
if (!hasNegatedPattern) {
|
|
222
|
-
return result
|
|
223
|
-
}
|
|
224
|
-
const { absolute } = globOptions
|
|
225
|
-
|
|
226
|
-
// Note: the input files must be INSIDE the cwd. If you get strange looking
|
|
227
|
-
// relative path errors here, most likely your path is outside the given cwd.
|
|
228
|
-
const filtered = vendor
|
|
229
|
-
.ignoreExports()
|
|
230
|
-
.add(ignores)
|
|
231
|
-
.filter(absolute ? result.map(p => path.relative(cwd, p)) : result)
|
|
232
|
-
return absolute ? filtered.map(p => path.resolve(cwd, p)) : filtered
|
|
233
|
-
}
|
|
234
|
-
async function globNodeModules(cwd = process.cwd()) {
|
|
235
|
-
return await vendor.distExports.glob('**/node_modules/**', {
|
|
236
|
-
absolute: true,
|
|
237
|
-
cwd
|
|
238
|
-
})
|
|
239
|
-
}
|
|
240
|
-
async function globWorkspace(agent, cwd = process.cwd()) {
|
|
241
|
-
const workspaceGlobs = await getWorkspaceGlobs(agent, cwd)
|
|
242
|
-
return workspaceGlobs.length
|
|
243
|
-
? await vendor.distExports.glob(workspaceGlobs, {
|
|
244
|
-
absolute: true,
|
|
245
|
-
cwd,
|
|
246
|
-
ignore: ['**/node_modules/**', '**/bower_components/**']
|
|
247
|
-
})
|
|
248
|
-
: []
|
|
249
|
-
}
|
|
250
|
-
function pathsToGlobPatterns(paths) {
|
|
251
|
-
// TODO: Does not support `~/` paths.
|
|
252
|
-
return paths.map(p => (p === '.' || p === './' ? '**/*' : p))
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
const { abortSignal } = constants
|
|
256
|
-
async function removeNodeModules(cwd = process.cwd()) {
|
|
257
|
-
const nodeModulesPaths = await globNodeModules(cwd)
|
|
258
|
-
await Promise.all(nodeModulesPaths.map(p => fs$1.remove(p)))
|
|
259
|
-
}
|
|
260
|
-
async function findUp(name, { cwd = process.cwd(), signal = abortSignal }) {
|
|
261
|
-
let dir = path.resolve(cwd)
|
|
262
|
-
const { root } = path.parse(dir)
|
|
263
|
-
const names = [name].flat()
|
|
264
|
-
while (dir && dir !== root) {
|
|
265
|
-
for (const name of names) {
|
|
266
|
-
if (signal?.aborted) {
|
|
267
|
-
return undefined
|
|
268
|
-
}
|
|
269
|
-
const filePath = path.join(dir, name)
|
|
270
|
-
try {
|
|
271
|
-
// eslint-disable-next-line no-await-in-loop
|
|
272
|
-
const stats = await fs.promises.stat(filePath)
|
|
273
|
-
if (stats.isFile()) {
|
|
274
|
-
return filePath
|
|
275
|
-
}
|
|
276
|
-
} catch {}
|
|
277
|
-
}
|
|
278
|
-
dir = path.dirname(dir)
|
|
279
|
-
}
|
|
280
|
-
return undefined
|
|
281
|
-
}
|
|
282
|
-
async function readFileBinary(filepath, options) {
|
|
283
|
-
return await fs.promises.readFile(filepath, {
|
|
284
|
-
signal: abortSignal,
|
|
285
|
-
...options,
|
|
286
|
-
encoding: 'binary'
|
|
287
|
-
})
|
|
288
|
-
}
|
|
289
|
-
async function readFileUtf8(filepath, options) {
|
|
290
|
-
return await fs.promises.readFile(filepath, {
|
|
291
|
-
signal: abortSignal,
|
|
292
|
-
...options,
|
|
293
|
-
encoding: 'utf8'
|
|
294
|
-
})
|
|
295
|
-
}
|
|
296
|
-
async function safeReadFile(filepath, options) {
|
|
297
|
-
try {
|
|
298
|
-
return await fs.promises.readFile(filepath, {
|
|
299
|
-
encoding: 'utf8',
|
|
300
|
-
signal: abortSignal,
|
|
301
|
-
...(typeof options === 'string'
|
|
302
|
-
? {
|
|
303
|
-
encoding: options
|
|
304
|
-
}
|
|
305
|
-
: options)
|
|
306
|
-
})
|
|
307
|
-
} catch {}
|
|
308
|
-
return undefined
|
|
309
|
-
}
|
|
310
|
-
function safeReadFileSync(filepath, options) {
|
|
311
|
-
try {
|
|
312
|
-
return fs.readFileSync(filepath, {
|
|
313
|
-
encoding: 'utf8',
|
|
314
|
-
...(typeof options === 'string'
|
|
315
|
-
? {
|
|
316
|
-
encoding: options
|
|
317
|
-
}
|
|
318
|
-
: options)
|
|
319
|
-
})
|
|
320
|
-
} catch {}
|
|
321
|
-
return undefined
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
const { LOCALAPPDATA, SOCKET_APP_DIR } = constants
|
|
325
|
-
const supportedConfigKeys = new Map([
|
|
326
|
-
['apiBaseUrl', 'Base URL of the API endpoint'],
|
|
327
|
-
['apiProxy', 'A proxy through which to access the API'],
|
|
328
|
-
['apiToken', 'The API token required to access most API endpoints'],
|
|
329
|
-
[
|
|
330
|
-
'defaultOrg',
|
|
331
|
-
'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.'
|
|
332
|
-
],
|
|
333
|
-
[
|
|
334
|
-
'enforcedOrgs',
|
|
335
|
-
'Orgs in this list have their security policies enforced on this machine'
|
|
336
|
-
],
|
|
337
|
-
['isTestingV1', 'For development of testing the next major bump']
|
|
338
|
-
])
|
|
339
|
-
const sensitiveConfigKeys = new Set(['apiToken'])
|
|
340
|
-
let _cachedConfig
|
|
341
|
-
// When using --config or SOCKET_CLI_CONFIG, do not persist the config.
|
|
342
|
-
let _readOnlyConfig = false
|
|
343
|
-
function overrideCachedConfig(jsonConfig) {
|
|
344
|
-
debug.debugLog('Overriding entire config, marking config as read-only')
|
|
345
|
-
let config
|
|
346
|
-
try {
|
|
347
|
-
config = JSON.parse(String(jsonConfig))
|
|
348
|
-
if (!config || typeof config !== 'object') {
|
|
349
|
-
// `null` is valid json, so are primitive values. They're not valid config objects :)
|
|
350
|
-
return {
|
|
351
|
-
ok: false,
|
|
352
|
-
message: 'Could not parse Config as JSON',
|
|
353
|
-
cause:
|
|
354
|
-
"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."
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
} catch {
|
|
358
|
-
// Force set an empty config to prevent accidentally using system settings
|
|
359
|
-
_cachedConfig = {}
|
|
360
|
-
_readOnlyConfig = true
|
|
361
|
-
return {
|
|
362
|
-
ok: false,
|
|
363
|
-
message: 'Could not parse Config as JSON',
|
|
364
|
-
cause:
|
|
365
|
-
"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."
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
// @ts-ignore Override an illegal object.
|
|
370
|
-
_cachedConfig = config
|
|
371
|
-
_readOnlyConfig = true
|
|
372
|
-
|
|
373
|
-
// Normalize apiKey to apiToken.
|
|
374
|
-
if (_cachedConfig['apiKey']) {
|
|
375
|
-
if (_cachedConfig['apiToken']) {
|
|
376
|
-
logger.logger.warn(
|
|
377
|
-
'Note: The config override had both apiToken and apiKey. Using the apiToken value. Remove the apiKey to get rid of this message.'
|
|
378
|
-
)
|
|
379
|
-
}
|
|
380
|
-
_cachedConfig['apiToken'] = _cachedConfig['apiKey']
|
|
381
|
-
delete _cachedConfig['apiKey']
|
|
382
|
-
}
|
|
383
|
-
return {
|
|
384
|
-
ok: true,
|
|
385
|
-
data: undefined
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
function overrideConfigApiToken(apiToken) {
|
|
389
|
-
debug.debugLog('Overriding API token, marking config as read-only')
|
|
390
|
-
// Set token to the local cached config and mark it read-only so it doesn't persist
|
|
391
|
-
_cachedConfig = {
|
|
392
|
-
...vendor.configExports,
|
|
393
|
-
...(apiToken === undefined
|
|
394
|
-
? {}
|
|
395
|
-
: {
|
|
396
|
-
apiToken: String(apiToken)
|
|
397
|
-
})
|
|
398
|
-
}
|
|
399
|
-
_readOnlyConfig = true
|
|
400
|
-
}
|
|
401
|
-
function getConfigValues() {
|
|
402
|
-
if (_cachedConfig === undefined) {
|
|
403
|
-
_cachedConfig = {}
|
|
404
|
-
// Order: env var > --config flag > file
|
|
405
|
-
const configPath = getConfigPath()
|
|
406
|
-
if (configPath) {
|
|
407
|
-
const raw = safeReadFileSync(configPath)
|
|
408
|
-
if (raw) {
|
|
409
|
-
try {
|
|
410
|
-
Object.assign(
|
|
411
|
-
_cachedConfig,
|
|
412
|
-
JSON.parse(Buffer.from(raw, 'base64').toString())
|
|
413
|
-
)
|
|
414
|
-
} catch {
|
|
415
|
-
logger.logger.warn(`Failed to parse config at ${configPath}`)
|
|
416
|
-
}
|
|
417
|
-
// Normalize apiKey to apiToken and persist it.
|
|
418
|
-
// This is a one time migration per user.
|
|
419
|
-
if (_cachedConfig['apiKey']) {
|
|
420
|
-
const token = _cachedConfig['apiKey']
|
|
421
|
-
delete _cachedConfig['apiKey']
|
|
422
|
-
updateConfigValue('apiToken', token)
|
|
423
|
-
}
|
|
424
|
-
} else {
|
|
425
|
-
fs.mkdirSync(path.dirname(configPath), {
|
|
426
|
-
recursive: true
|
|
427
|
-
})
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
return _cachedConfig
|
|
432
|
-
}
|
|
433
|
-
let _configPath
|
|
434
|
-
let _warnedConfigPathWin32Missing = false
|
|
435
|
-
function getConfigPath() {
|
|
436
|
-
// Get the OS app data folder:
|
|
437
|
-
// - Win: %LOCALAPPDATA% or fail?
|
|
438
|
-
// - Mac: %XDG_DATA_HOME% or fallback to "~/Library/Application Support/"
|
|
439
|
-
// - Linux: %XDG_DATA_HOME% or fallback to "~/.local/share/"
|
|
440
|
-
// Note: LOCALAPPDATA is typically: C:\Users\USERNAME\AppData
|
|
441
|
-
// Note: XDG stands for "X Desktop Group", nowadays "freedesktop.org"
|
|
442
|
-
// On most systems that path is: $HOME/.local/share
|
|
443
|
-
// Then append `socket/settings`, so:
|
|
444
|
-
// - Win: %LOCALAPPDATA%\socket\settings or return undefined
|
|
445
|
-
// - Mac: %XDG_DATA_HOME%/socket/settings or "~/Library/Application Support/socket/settings"
|
|
446
|
-
// - Linux: %XDG_DATA_HOME%/socket/settings or "~/.local/share/socket/settings"
|
|
447
|
-
|
|
448
|
-
if (_configPath === undefined) {
|
|
449
32
|
// Lazily access constants.WIN32.
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
dataHome = path.join(
|
|
464
|
-
os.homedir(),
|
|
465
|
-
...(process.platform === 'darwin'
|
|
466
|
-
? ['Library', 'Application Support']
|
|
467
|
-
: ['.local', 'share'])
|
|
468
|
-
)
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
_configPath = dataHome ? path.join(dataHome, SOCKET_APP_DIR) : undefined
|
|
472
|
-
}
|
|
473
|
-
return _configPath
|
|
474
|
-
}
|
|
475
|
-
function normalizeConfigKey(key) {
|
|
476
|
-
// Note: apiKey was the old name of the token. When we load a config with
|
|
477
|
-
// property apiKey, we'll copy that to apiToken and delete the old property.
|
|
478
|
-
const normalizedKey = key === 'apiKey' ? 'apiToken' : key
|
|
479
|
-
if (!supportedConfigKeys.has(normalizedKey)) {
|
|
480
|
-
return {
|
|
481
|
-
ok: false,
|
|
482
|
-
message: `Invalid config key: ${normalizedKey}`,
|
|
483
|
-
data: undefined
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
return {
|
|
487
|
-
ok: true,
|
|
488
|
-
data: key
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
function findSocketYmlSync(dir = process.cwd()) {
|
|
492
|
-
let prevDir = null
|
|
493
|
-
while (dir !== prevDir) {
|
|
494
|
-
let ymlPath = path.join(dir, 'socket.yml')
|
|
495
|
-
let yml = safeReadFileSync(ymlPath)
|
|
496
|
-
if (yml === undefined) {
|
|
497
|
-
ymlPath = path.join(dir, 'socket.yaml')
|
|
498
|
-
yml = safeReadFileSync(ymlPath)
|
|
499
|
-
}
|
|
500
|
-
if (typeof yml === 'string') {
|
|
501
|
-
try {
|
|
502
|
-
return {
|
|
503
|
-
path: ymlPath,
|
|
504
|
-
parsed: vendor.configExports.parseSocketConfig(yml)
|
|
505
|
-
}
|
|
506
|
-
} catch {
|
|
507
|
-
throw new Error(`Found file but was unable to parse ${ymlPath}`)
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
prevDir = dir
|
|
511
|
-
dir = path.join(dir, '..')
|
|
512
|
-
}
|
|
513
|
-
return null
|
|
514
|
-
}
|
|
515
|
-
function getConfigValue(key) {
|
|
516
|
-
const localConfig = getConfigValues()
|
|
517
|
-
const keyResult = normalizeConfigKey(key)
|
|
518
|
-
if (!keyResult.ok) {
|
|
519
|
-
return keyResult
|
|
520
|
-
}
|
|
521
|
-
return {
|
|
522
|
-
ok: true,
|
|
523
|
-
data: localConfig[keyResult.data]
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
// This version squashes errors, returning undefined instead.
|
|
527
|
-
// Should be used when we can reasonably predict the call can't fail.
|
|
528
|
-
function getConfigValueOrUndef(key) {
|
|
529
|
-
const localConfig = getConfigValues()
|
|
530
|
-
const keyResult = normalizeConfigKey(key)
|
|
531
|
-
if (!keyResult.ok) {
|
|
532
|
-
return undefined
|
|
533
|
-
}
|
|
534
|
-
return localConfig[keyResult.data]
|
|
535
|
-
}
|
|
536
|
-
function isReadOnlyConfig() {
|
|
537
|
-
return _readOnlyConfig
|
|
538
|
-
}
|
|
539
|
-
let _pendingSave = false
|
|
540
|
-
function updateConfigValue(key, value) {
|
|
541
|
-
const localConfig = getConfigValues()
|
|
542
|
-
const keyResult = normalizeConfigKey(key)
|
|
543
|
-
if (!keyResult.ok) {
|
|
544
|
-
return keyResult
|
|
545
|
-
}
|
|
546
|
-
localConfig[keyResult.data] = value
|
|
547
|
-
if (_readOnlyConfig) {
|
|
548
|
-
return {
|
|
549
|
-
ok: true,
|
|
550
|
-
message: `Config key '${key}' was updated`,
|
|
551
|
-
data: 'Change applied but not persisted; current config is overridden through env var or flag'
|
|
552
|
-
}
|
|
553
|
-
}
|
|
554
|
-
if (!_pendingSave) {
|
|
555
|
-
_pendingSave = true
|
|
556
|
-
process.nextTick(() => {
|
|
557
|
-
_pendingSave = false
|
|
558
|
-
const configPath = getConfigPath()
|
|
559
|
-
if (configPath) {
|
|
560
|
-
fs.writeFileSync(
|
|
561
|
-
configPath,
|
|
562
|
-
Buffer.from(JSON.stringify(localConfig)).toString('base64')
|
|
563
|
-
)
|
|
564
|
-
}
|
|
565
|
-
})
|
|
566
|
-
}
|
|
567
|
-
return {
|
|
568
|
-
ok: true,
|
|
569
|
-
message: `Config key '${key}' was updated`,
|
|
570
|
-
data: undefined
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
function isTestingV1() {
|
|
574
|
-
return !!getConfigValueOrUndef('isTestingV1')
|
|
575
|
-
}
|
|
576
|
-
|
|
577
|
-
const {
|
|
578
|
-
kInternalsSymbol: kInternalsSymbol$1,
|
|
579
|
-
[kInternalsSymbol$1]: { getSentry }
|
|
580
|
-
} = constants
|
|
581
|
-
class AuthError extends Error {}
|
|
582
|
-
class InputError extends Error {
|
|
583
|
-
constructor(message, body) {
|
|
584
|
-
super(message)
|
|
585
|
-
this.body = body
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
async function captureException(exception, hint) {
|
|
589
|
-
const result = captureExceptionSync(exception, hint)
|
|
590
|
-
// "Sleep" for a second, just in case, hopefully enough time to initiate fetch.
|
|
591
|
-
await promises.setTimeout(1000)
|
|
592
|
-
return result
|
|
593
|
-
}
|
|
594
|
-
function captureExceptionSync(exception, hint) {
|
|
595
|
-
const Sentry = getSentry()
|
|
596
|
-
if (!Sentry) {
|
|
597
|
-
return ''
|
|
598
|
-
}
|
|
599
|
-
debug.debugLog('captureException: Sending exception to Sentry')
|
|
600
|
-
return Sentry.captureException(exception, hint)
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
const { SOCKET_PUBLIC_API_TOKEN } = constants
|
|
604
|
-
|
|
605
|
-
// The API server that should be used for operations.
|
|
606
|
-
function getDefaultApiBaseUrl() {
|
|
607
|
-
const baseUrl =
|
|
608
|
-
// Lazily access constants.ENV.SOCKET_SECURITY_API_BASE_URL.
|
|
609
|
-
constants.ENV.SOCKET_SECURITY_API_BASE_URL ||
|
|
610
|
-
getConfigValueOrUndef('apiBaseUrl')
|
|
611
|
-
return strings.isNonEmptyString(baseUrl) ? baseUrl : undefined
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
// The API server that should be used for operations.
|
|
615
|
-
function getDefaultHttpProxy() {
|
|
616
|
-
const apiProxy =
|
|
617
|
-
// Lazily access constants.ENV.SOCKET_SECURITY_API_PROXY.
|
|
618
|
-
constants.ENV.SOCKET_SECURITY_API_PROXY || getConfigValueOrUndef('apiProxy')
|
|
619
|
-
return strings.isNonEmptyString(apiProxy) ? apiProxy : undefined
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
// This API key should be stored globally for the duration of the CLI execution.
|
|
623
|
-
let _defaultToken
|
|
624
|
-
function getDefaultToken() {
|
|
625
|
-
// Lazily access constants.ENV.SOCKET_CLI_NO_API_TOKEN.
|
|
626
|
-
if (constants.ENV.SOCKET_CLI_NO_API_TOKEN) {
|
|
627
|
-
_defaultToken = undefined
|
|
628
|
-
} else {
|
|
629
|
-
const key =
|
|
630
|
-
// Lazily access constants.ENV.SOCKET_SECURITY_API_TOKEN.
|
|
631
|
-
constants.ENV.SOCKET_SECURITY_API_TOKEN ||
|
|
632
|
-
getConfigValueOrUndef('apiToken') ||
|
|
633
|
-
_defaultToken
|
|
634
|
-
_defaultToken = strings.isNonEmptyString(key) ? key : undefined
|
|
33
|
+
_arboristPkgPath = constants.WIN32
|
|
34
|
+
? path.normalize(arboristPkgPathWithForwardSlashes)
|
|
35
|
+
: arboristPkgPathWithForwardSlashes
|
|
36
|
+
}
|
|
37
|
+
return _arboristPkgPath
|
|
38
|
+
}
|
|
39
|
+
let _arboristClassPath
|
|
40
|
+
function getArboristClassPath() {
|
|
41
|
+
if (_arboristClassPath === undefined) {
|
|
42
|
+
_arboristClassPath = path.join(
|
|
43
|
+
getArboristPackagePath(),
|
|
44
|
+
'lib/arborist/index.js'
|
|
45
|
+
)
|
|
635
46
|
}
|
|
636
|
-
return
|
|
47
|
+
return _arboristClassPath
|
|
637
48
|
}
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
async function setupSdk(
|
|
646
|
-
apiToken = getDefaultToken(),
|
|
647
|
-
apiBaseUrl = getDefaultApiBaseUrl(),
|
|
648
|
-
proxy = getDefaultHttpProxy()
|
|
649
|
-
) {
|
|
650
|
-
if (typeof apiToken !== 'string' && vendor.isInteractiveExports()) {
|
|
651
|
-
apiToken = await prompts.password({
|
|
652
|
-
message:
|
|
653
|
-
'Enter your Socket.dev API key (not saved, use socket login to persist)'
|
|
654
|
-
})
|
|
655
|
-
_defaultToken = apiToken
|
|
656
|
-
}
|
|
657
|
-
if (!apiToken) {
|
|
658
|
-
// TODO: eliminate this throw in favor of CResult (or anything else)
|
|
659
|
-
throw new AuthError('You need to provide an API key')
|
|
49
|
+
let _arboristDepValidPath
|
|
50
|
+
function getArboristDepValidPath() {
|
|
51
|
+
if (_arboristDepValidPath === undefined) {
|
|
52
|
+
_arboristDepValidPath = path.join(
|
|
53
|
+
getArboristPackagePath(),
|
|
54
|
+
'lib/dep-valid.js'
|
|
55
|
+
)
|
|
660
56
|
}
|
|
661
|
-
return
|
|
662
|
-
agent: proxy
|
|
663
|
-
? new vendor.HttpsProxyAgent({
|
|
664
|
-
proxy
|
|
665
|
-
})
|
|
666
|
-
: undefined,
|
|
667
|
-
baseUrl: apiBaseUrl,
|
|
668
|
-
userAgent: vendor.distExports$2.createUserAgentFromPkgJson({
|
|
669
|
-
// Lazily access constants.ENV.INLINED_SOCKET_CLI_NAME.
|
|
670
|
-
name: constants.ENV.INLINED_SOCKET_CLI_NAME,
|
|
671
|
-
// Lazily access constants.ENV.INLINED_SOCKET_CLI_VERSION.
|
|
672
|
-
version: constants.ENV.INLINED_SOCKET_CLI_VERSION,
|
|
673
|
-
// Lazily access constants.ENV.INLINED_SOCKET_CLI_HOMEPAGE.
|
|
674
|
-
homepage: constants.ENV.INLINED_SOCKET_CLI_HOMEPAGE
|
|
675
|
-
})
|
|
676
|
-
})
|
|
57
|
+
return _arboristDepValidPath
|
|
677
58
|
}
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
case 'caret':
|
|
683
|
-
return `^${version}`
|
|
684
|
-
case 'gt':
|
|
685
|
-
return `>${version}`
|
|
686
|
-
case 'gte':
|
|
687
|
-
return `>=${version}`
|
|
688
|
-
case 'lt':
|
|
689
|
-
return `<${version}`
|
|
690
|
-
case 'lte':
|
|
691
|
-
return `<=${version}`
|
|
692
|
-
case 'preserve': {
|
|
693
|
-
const range = new vendor.semverExports.Range(refRange)
|
|
694
|
-
const { raw } = range
|
|
695
|
-
const comparators = [...range.set].flat()
|
|
696
|
-
const { length } = comparators
|
|
697
|
-
if (length === 1) {
|
|
698
|
-
const char = /^[<>]=?/.exec(raw)?.[0]
|
|
699
|
-
if (char) {
|
|
700
|
-
return `${char}${version}`
|
|
701
|
-
}
|
|
702
|
-
} else if (length === 2) {
|
|
703
|
-
const char = /^[~^]/.exec(raw)?.[0]
|
|
704
|
-
if (char) {
|
|
705
|
-
return `${char}${version}`
|
|
706
|
-
}
|
|
707
|
-
}
|
|
708
|
-
return version
|
|
709
|
-
}
|
|
710
|
-
case 'tilde':
|
|
711
|
-
return `~${version}`
|
|
712
|
-
case 'pin':
|
|
713
|
-
default:
|
|
714
|
-
return version
|
|
59
|
+
let _arboristEdgeClassPath
|
|
60
|
+
function getArboristEdgeClassPath() {
|
|
61
|
+
if (_arboristEdgeClassPath === undefined) {
|
|
62
|
+
_arboristEdgeClassPath = path.join(getArboristPackagePath(), 'lib/edge.js')
|
|
715
63
|
}
|
|
64
|
+
return _arboristEdgeClassPath
|
|
716
65
|
}
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
if (
|
|
720
|
-
|
|
721
|
-
return vendor.semverExports.major(coerced)
|
|
722
|
-
} catch (e) {
|
|
723
|
-
debug.debugLog(`Error parsing '${version}':\n`, e)
|
|
724
|
-
}
|
|
66
|
+
let _arboristNodeClassPath
|
|
67
|
+
function getArboristNodeClassPath() {
|
|
68
|
+
if (_arboristNodeClassPath === undefined) {
|
|
69
|
+
_arboristNodeClassPath = path.join(getArboristPackagePath(), 'lib/node.js')
|
|
725
70
|
}
|
|
726
|
-
return
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
function idToPurl(id) {
|
|
730
|
-
return `pkg:npm/${id}`
|
|
731
|
-
}
|
|
732
|
-
function resolvePackageVersion(purlObj) {
|
|
733
|
-
const { version } = purlObj
|
|
734
|
-
return version
|
|
735
|
-
? (vendor.semverExports.coerce(stripPeerSuffix(version))?.version ?? '')
|
|
736
|
-
: ''
|
|
737
|
-
}
|
|
738
|
-
function stripLeadingSlash(path) {
|
|
739
|
-
return path.startsWith('/') ? path.slice(1) : path
|
|
740
|
-
}
|
|
741
|
-
function stripPeerSuffix(depPath) {
|
|
742
|
-
const idx = depPath.indexOf('(')
|
|
743
|
-
return idx === -1 ? depPath : depPath.slice(0, idx)
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
function createEnum(obj) {
|
|
747
|
-
return Object.freeze({
|
|
748
|
-
__proto__: null,
|
|
749
|
-
...obj
|
|
750
|
-
})
|
|
71
|
+
return _arboristNodeClassPath
|
|
751
72
|
}
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
73
|
+
let _arboristOverrideSetClassPath
|
|
74
|
+
function getArboristOverrideSetClassPath() {
|
|
75
|
+
if (_arboristOverrideSetClassPath === undefined) {
|
|
76
|
+
_arboristOverrideSetClassPath = path.join(
|
|
77
|
+
getArboristPackagePath(),
|
|
78
|
+
'lib/override-set.js'
|
|
79
|
+
)
|
|
756
80
|
}
|
|
757
|
-
return
|
|
81
|
+
return _arboristOverrideSetClassPath
|
|
758
82
|
}
|
|
759
83
|
|
|
760
|
-
const DiffAction = createEnum({
|
|
761
|
-
add: 'ADD',
|
|
762
|
-
change: 'CHANGE',
|
|
763
|
-
remove: 'REMOVE'
|
|
764
|
-
})
|
|
765
|
-
|
|
766
84
|
const require$6 = Module.createRequire(
|
|
767
|
-
|
|
768
|
-
? require('u' + 'rl').pathToFileURL(__filename).href
|
|
769
|
-
: (_documentCurrentScript &&
|
|
770
|
-
_documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' &&
|
|
771
|
-
_documentCurrentScript.src) ||
|
|
772
|
-
new URL('shadow-npm-inject.js', document.baseURI).href
|
|
85
|
+
require('u' + 'rl').pathToFileURL(__filename).href
|
|
773
86
|
)
|
|
774
|
-
|
|
87
|
+
let _depValid
|
|
88
|
+
function depValid(child, requested, accept, requester) {
|
|
89
|
+
if (_depValid === undefined) {
|
|
90
|
+
_depValid = require$6(getArboristDepValidPath())
|
|
91
|
+
}
|
|
92
|
+
return _depValid(child, requested, accept, requester)
|
|
93
|
+
}
|
|
775
94
|
|
|
776
95
|
const { UNDEFINED_TOKEN } = constants
|
|
777
96
|
function tryRequire(req, ...ids) {
|
|
@@ -800,7 +119,7 @@ let _log = UNDEFINED_TOKEN
|
|
|
800
119
|
function getLogger() {
|
|
801
120
|
if (_log === UNDEFINED_TOKEN) {
|
|
802
121
|
_log = tryRequire(
|
|
803
|
-
|
|
122
|
+
utils.getNpmRequire(),
|
|
804
123
|
[
|
|
805
124
|
'proc-log/lib/index.js',
|
|
806
125
|
// The proc-log DefinitelyTyped definition is incorrect. The type definition
|
|
@@ -814,14 +133,9 @@ function getLogger() {
|
|
|
814
133
|
}
|
|
815
134
|
|
|
816
135
|
const require$5 = Module.createRequire(
|
|
817
|
-
|
|
818
|
-
? require('u' + 'rl').pathToFileURL(__filename).href
|
|
819
|
-
: (_documentCurrentScript &&
|
|
820
|
-
_documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' &&
|
|
821
|
-
_documentCurrentScript.src) ||
|
|
822
|
-
new URL('shadow-npm-inject.js', document.baseURI).href
|
|
136
|
+
require('u' + 'rl').pathToFileURL(__filename).href
|
|
823
137
|
)
|
|
824
|
-
const OverrideSet = require$5(
|
|
138
|
+
const OverrideSet = require$5(getArboristOverrideSetClassPath())
|
|
825
139
|
|
|
826
140
|
// Implementation code not related to patch https://github.com/npm/cli/pull/8089
|
|
827
141
|
// is based on https://github.com/npm/cli/blob/v11.0.0/workspaces/arborist/lib/override-set.js:
|
|
@@ -951,14 +265,9 @@ class SafeOverrideSet extends OverrideSet {
|
|
|
951
265
|
}
|
|
952
266
|
|
|
953
267
|
const require$4 = Module.createRequire(
|
|
954
|
-
|
|
955
|
-
? require('u' + 'rl').pathToFileURL(__filename).href
|
|
956
|
-
: (_documentCurrentScript &&
|
|
957
|
-
_documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' &&
|
|
958
|
-
_documentCurrentScript.src) ||
|
|
959
|
-
new URL('shadow-npm-inject.js', document.baseURI).href
|
|
268
|
+
require('u' + 'rl').pathToFileURL(__filename).href
|
|
960
269
|
)
|
|
961
|
-
const Node = require$4(
|
|
270
|
+
const Node = require$4(getArboristNodeClassPath())
|
|
962
271
|
|
|
963
272
|
// Implementation code not related to patch https://github.com/npm/cli/pull/8089
|
|
964
273
|
// is based on https://github.com/npm/cli/blob/v11.0.0/workspaces/arborist/lib/node.js:
|
|
@@ -1266,14 +575,9 @@ class SafeNode extends Node {
|
|
|
1266
575
|
}
|
|
1267
576
|
|
|
1268
577
|
const require$3 = Module.createRequire(
|
|
1269
|
-
|
|
1270
|
-
? require('u' + 'rl').pathToFileURL(__filename).href
|
|
1271
|
-
: (_documentCurrentScript &&
|
|
1272
|
-
_documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' &&
|
|
1273
|
-
_documentCurrentScript.src) ||
|
|
1274
|
-
new URL('shadow-npm-inject.js', document.baseURI).href
|
|
578
|
+
require('u' + 'rl').pathToFileURL(__filename).href
|
|
1275
579
|
)
|
|
1276
|
-
const Edge = require$3(
|
|
580
|
+
const Edge = require$3(getArboristEdgeClassPath())
|
|
1277
581
|
|
|
1278
582
|
// The Edge class makes heavy use of private properties which subclasses do NOT
|
|
1279
583
|
// have access to. So we have to recreate any functionality that relies on those
|
|
@@ -1533,7 +837,7 @@ class SafeEdge extends Edge {
|
|
|
1533
837
|
}
|
|
1534
838
|
}
|
|
1535
839
|
|
|
1536
|
-
const { LOOP_SENTINEL, NPM: NPM$
|
|
840
|
+
const { LOOP_SENTINEL, NPM: NPM$1, NPM_REGISTRY_URL } = constants
|
|
1537
841
|
function getUrlOrigin(input) {
|
|
1538
842
|
try {
|
|
1539
843
|
// TODO: URL.parse is available in Node 22.1.0. We can use it when we drop Node 18.
|
|
@@ -1549,16 +853,18 @@ function findBestPatchVersion(
|
|
|
1549
853
|
vulnerableVersionRange,
|
|
1550
854
|
_firstPatchedVersionIdentifier
|
|
1551
855
|
) {
|
|
1552
|
-
const manifestData = registry.getManifestData(NPM$
|
|
856
|
+
const manifestData = registry.getManifestData(NPM$1, node.name)
|
|
1553
857
|
let eligibleVersions
|
|
1554
858
|
if (manifestData && manifestData.name === manifestData.package) {
|
|
1555
|
-
const major = getMajor(manifestData.version)
|
|
859
|
+
const major = utils.getMajor(manifestData.version)
|
|
1556
860
|
if (typeof major !== 'number') {
|
|
1557
861
|
return null
|
|
1558
862
|
}
|
|
1559
|
-
eligibleVersions = availableVersions.filter(
|
|
863
|
+
eligibleVersions = availableVersions.filter(
|
|
864
|
+
v => utils.getMajor(v) === major
|
|
865
|
+
)
|
|
1560
866
|
} else {
|
|
1561
|
-
const major = getMajor(node.version)
|
|
867
|
+
const major = utils.getMajor(node.version)
|
|
1562
868
|
if (typeof major !== 'number') {
|
|
1563
869
|
return null
|
|
1564
870
|
}
|
|
@@ -1566,7 +872,7 @@ function findBestPatchVersion(
|
|
|
1566
872
|
v =>
|
|
1567
873
|
// Filter for versions that are within the current major version and
|
|
1568
874
|
// are NOT in the vulnerable range.
|
|
1569
|
-
getMajor(v) === major &&
|
|
875
|
+
utils.getMajor(v) === major &&
|
|
1570
876
|
(!vulnerableVersionRange ||
|
|
1571
877
|
!vendor.semverExports.satisfies(v, vulnerableVersionRange))
|
|
1572
878
|
)
|
|
@@ -1613,6 +919,43 @@ function findPackageNodes(tree, name, version) {
|
|
|
1613
919
|
}
|
|
1614
920
|
return matches
|
|
1615
921
|
}
|
|
922
|
+
async function getAlertsMapFromArborist(arb, options_) {
|
|
923
|
+
const options = {
|
|
924
|
+
__proto__: null,
|
|
925
|
+
consolidate: false,
|
|
926
|
+
limit: Infinity,
|
|
927
|
+
nothrow: false,
|
|
928
|
+
...options_
|
|
929
|
+
}
|
|
930
|
+
const include = {
|
|
931
|
+
__proto__: null,
|
|
932
|
+
existing: false,
|
|
933
|
+
...options.include
|
|
934
|
+
}
|
|
935
|
+
const needInfoOn = getDetailsFromDiff(arb.diff, {
|
|
936
|
+
include: {
|
|
937
|
+
unchanged: include.existing
|
|
938
|
+
}
|
|
939
|
+
})
|
|
940
|
+
const purls = needInfoOn.map(d => utils.idToPurl(d.node.pkgid))
|
|
941
|
+
let overrides
|
|
942
|
+
const overridesMap = (
|
|
943
|
+
arb.actualTree ??
|
|
944
|
+
arb.idealTree ??
|
|
945
|
+
(await arb.loadActual())
|
|
946
|
+
)?.overrides?.children
|
|
947
|
+
if (overridesMap) {
|
|
948
|
+
overrides = Object.fromEntries(
|
|
949
|
+
[...overridesMap.entries()].map(([key, overrideSet]) => {
|
|
950
|
+
return [key, overrideSet.value]
|
|
951
|
+
})
|
|
952
|
+
)
|
|
953
|
+
}
|
|
954
|
+
return await utils.getAlertsMapFromPurls(purls, {
|
|
955
|
+
overrides,
|
|
956
|
+
...options
|
|
957
|
+
})
|
|
958
|
+
}
|
|
1616
959
|
function getDetailsFromDiff(diff_, options) {
|
|
1617
960
|
const details = []
|
|
1618
961
|
// `diff_` is `null` when `npm install --package-lock-only` is passed.
|
|
@@ -1706,7 +1049,7 @@ function updateNode(node, newVersion, newVersionPackument) {
|
|
|
1706
1049
|
node.package.version = newVersion
|
|
1707
1050
|
// Update node.resolved.
|
|
1708
1051
|
const purlObj = vendor.packageurlJsExports.PackageURL.fromString(
|
|
1709
|
-
idToPurl(node.name)
|
|
1052
|
+
utils.idToPurl(node.name)
|
|
1710
1053
|
)
|
|
1711
1054
|
node.resolved = `${NPM_REGISTRY_URL}/${node.name}/-/${purlObj.name}-${newVersion}.tgz`
|
|
1712
1055
|
// Update node.integrity with the targetPackument.dist.integrity value if available
|
|
@@ -1774,7 +1117,7 @@ function updatePackageJsonFromNode(
|
|
|
1774
1117
|
if (depObject) {
|
|
1775
1118
|
const oldRange = depObject[name]
|
|
1776
1119
|
if (oldRange) {
|
|
1777
|
-
const newRange = applyRange(oldRange, newVersion, rangeStyle)
|
|
1120
|
+
const newRange = utils.applyRange(oldRange, newVersion, rangeStyle)
|
|
1778
1121
|
if (oldRange !== newRange) {
|
|
1779
1122
|
result = true
|
|
1780
1123
|
editablePkgJson.update({
|
|
@@ -1790,826 +1133,8 @@ function updatePackageJsonFromNode(
|
|
|
1790
1133
|
return result
|
|
1791
1134
|
}
|
|
1792
1135
|
|
|
1793
|
-
function extractPurlsFromPnpmLockfileV6(lockfile) {
|
|
1794
|
-
const deps = new Set()
|
|
1795
|
-
for (const importer of Object.values(lockfile.importers || {})) {
|
|
1796
|
-
if (importer.dependencies) {
|
|
1797
|
-
for (const { 0: alias, 1: ref } of Object.entries(
|
|
1798
|
-
importer.dependencies
|
|
1799
|
-
)) {
|
|
1800
|
-
const id = resolvePnpmPackageId(alias, ref)
|
|
1801
|
-
if (id) {
|
|
1802
|
-
deps.add(idToPurl(id))
|
|
1803
|
-
}
|
|
1804
|
-
}
|
|
1805
|
-
}
|
|
1806
|
-
if (importer.devDependencies) {
|
|
1807
|
-
for (const { 0: alias, 1: ref } of Object.entries(
|
|
1808
|
-
importer.devDependencies
|
|
1809
|
-
)) {
|
|
1810
|
-
const id = resolvePnpmPackageId(alias, ref)
|
|
1811
|
-
if (id) {
|
|
1812
|
-
deps.add(idToPurl(id))
|
|
1813
|
-
}
|
|
1814
|
-
}
|
|
1815
|
-
}
|
|
1816
|
-
if (importer.optionalDependencies) {
|
|
1817
|
-
for (const { 0: alias, 1: ref } of Object.entries(
|
|
1818
|
-
importer.optionalDependencies
|
|
1819
|
-
)) {
|
|
1820
|
-
const id = resolvePnpmPackageId(alias, ref)
|
|
1821
|
-
if (id) {
|
|
1822
|
-
deps.add(idToPurl(id))
|
|
1823
|
-
}
|
|
1824
|
-
}
|
|
1825
|
-
}
|
|
1826
|
-
}
|
|
1827
|
-
if (lockfile.packages) {
|
|
1828
|
-
for (const pkgPath of Object.keys(lockfile.packages)) {
|
|
1829
|
-
const id = resolvePnpmPackageIdFromPath(pkgPath, '')
|
|
1830
|
-
if (id) {
|
|
1831
|
-
deps.add(idToPurl(id))
|
|
1832
|
-
}
|
|
1833
|
-
}
|
|
1834
|
-
}
|
|
1835
|
-
return Array.from(deps)
|
|
1836
|
-
}
|
|
1837
|
-
function extractPurlsFromPnpmLockfileV9(lockfile) {
|
|
1838
|
-
const depTypes = vendor.libExports$1.detectDepTypes(lockfile)
|
|
1839
|
-
return Object.keys(depTypes).map(refId => {
|
|
1840
|
-
const purlObj = vendor.packageurlJsExports.PackageURL.fromString(
|
|
1841
|
-
idToPurl(refId)
|
|
1842
|
-
)
|
|
1843
|
-
const name = packages.resolvePackageName(purlObj)
|
|
1844
|
-
const version = resolvePackageVersion(purlObj)
|
|
1845
|
-
return idToPurl(`${name}@${version}`)
|
|
1846
|
-
})
|
|
1847
|
-
}
|
|
1848
|
-
function extractPurlsFromPnpmLockfile(lockfile) {
|
|
1849
|
-
return parsePnpmLockfileVersion(lockfile.lockfileVersion) >= 9
|
|
1850
|
-
? extractPurlsFromPnpmLockfileV9(lockfile)
|
|
1851
|
-
: extractPurlsFromPnpmLockfileV6(lockfile)
|
|
1852
|
-
}
|
|
1853
|
-
function parsePnpmLockfileVersion(version) {
|
|
1854
|
-
return parseInt(version.split('.')[0] ?? '', 10) || 0
|
|
1855
|
-
}
|
|
1856
|
-
function resolvePnpmPackageId(alias, ref) {
|
|
1857
|
-
return ref.startsWith('/')
|
|
1858
|
-
? resolvePnpmPackageIdFromPath(ref, alias)
|
|
1859
|
-
: `${alias}@${stripPeerSuffix(ref)}`
|
|
1860
|
-
}
|
|
1861
|
-
function resolvePnpmPackageIdFromPath(ref, alias) {
|
|
1862
|
-
const relative = vendor.libExports$2.refToRelative(ref, alias)
|
|
1863
|
-
if (relative) {
|
|
1864
|
-
const id = stripLeadingSlash(relative)
|
|
1865
|
-
const purlObj = vendor.packageurlJsExports.PackageURL.fromString(
|
|
1866
|
-
idToPurl(id)
|
|
1867
|
-
)
|
|
1868
|
-
const name = packages.resolvePackageName(purlObj)
|
|
1869
|
-
const version = resolvePackageVersion(purlObj)
|
|
1870
|
-
return `${name}@${version}`
|
|
1871
|
-
}
|
|
1872
|
-
return null
|
|
1873
|
-
}
|
|
1874
|
-
|
|
1875
|
-
const {
|
|
1876
|
-
ALERT_TYPE_CRITICAL_CVE,
|
|
1877
|
-
ALERT_TYPE_CVE,
|
|
1878
|
-
ALERT_TYPE_MEDIUM_CVE,
|
|
1879
|
-
ALERT_TYPE_MILD_CVE
|
|
1880
|
-
} = constants
|
|
1881
|
-
function isArtifactAlertCve(alert) {
|
|
1882
|
-
const { type } = alert
|
|
1883
|
-
return (
|
|
1884
|
-
type === ALERT_TYPE_CVE ||
|
|
1885
|
-
type === ALERT_TYPE_MEDIUM_CVE ||
|
|
1886
|
-
type === ALERT_TYPE_MILD_CVE ||
|
|
1887
|
-
type === ALERT_TYPE_CRITICAL_CVE
|
|
1888
|
-
)
|
|
1889
|
-
}
|
|
1890
|
-
|
|
1891
|
-
const ALERT_FIX_TYPE = createEnum({
|
|
1892
|
-
cve: 'cve',
|
|
1893
|
-
remove: 'remove',
|
|
1894
|
-
upgrade: 'upgrade'
|
|
1895
|
-
})
|
|
1896
|
-
|
|
1897
|
-
function stringJoinWithSeparateFinalSeparator(list, separator = ' and ') {
|
|
1898
|
-
const values = list.filter(Boolean)
|
|
1899
|
-
const { length } = values
|
|
1900
|
-
if (!length) {
|
|
1901
|
-
return ''
|
|
1902
|
-
}
|
|
1903
|
-
if (length === 1) {
|
|
1904
|
-
return values[0]
|
|
1905
|
-
}
|
|
1906
|
-
const finalValue = values.pop()
|
|
1907
|
-
return `${values.join(', ')}${separator}${finalValue}`
|
|
1908
|
-
}
|
|
1909
|
-
|
|
1910
|
-
const ALERT_SEVERITY = createEnum({
|
|
1911
|
-
critical: 'critical',
|
|
1912
|
-
high: 'high',
|
|
1913
|
-
middle: 'middle',
|
|
1914
|
-
low: 'low'
|
|
1915
|
-
})
|
|
1916
|
-
// Ordered from most severe to least.
|
|
1917
|
-
const ALERT_SEVERITIES_SORTED = Object.freeze([
|
|
1918
|
-
'critical',
|
|
1919
|
-
'high',
|
|
1920
|
-
'middle',
|
|
1921
|
-
'low'
|
|
1922
|
-
])
|
|
1923
|
-
function getDesiredSeverities(lowestToInclude) {
|
|
1924
|
-
const result = []
|
|
1925
|
-
for (const severity of ALERT_SEVERITIES_SORTED) {
|
|
1926
|
-
result.push(severity)
|
|
1927
|
-
if (severity === lowestToInclude) {
|
|
1928
|
-
break
|
|
1929
|
-
}
|
|
1930
|
-
}
|
|
1931
|
-
return result
|
|
1932
|
-
}
|
|
1933
|
-
function formatSeverityCount(severityCount) {
|
|
1934
|
-
const summary = []
|
|
1935
|
-
for (const severity of ALERT_SEVERITIES_SORTED) {
|
|
1936
|
-
if (severityCount[severity]) {
|
|
1937
|
-
summary.push(`${severityCount[severity]} ${severity}`)
|
|
1938
|
-
}
|
|
1939
|
-
}
|
|
1940
|
-
return stringJoinWithSeparateFinalSeparator(summary)
|
|
1941
|
-
}
|
|
1942
|
-
function getSeverityCount(issues, lowestToInclude) {
|
|
1943
|
-
const severityCount = pick(
|
|
1944
|
-
{
|
|
1945
|
-
low: 0,
|
|
1946
|
-
middle: 0,
|
|
1947
|
-
high: 0,
|
|
1948
|
-
critical: 0
|
|
1949
|
-
},
|
|
1950
|
-
getDesiredSeverities(lowestToInclude)
|
|
1951
|
-
)
|
|
1952
|
-
for (const issue of issues) {
|
|
1953
|
-
const { value } = issue
|
|
1954
|
-
if (!value) {
|
|
1955
|
-
continue
|
|
1956
|
-
}
|
|
1957
|
-
const { severity } = value
|
|
1958
|
-
if (severityCount[severity] !== undefined) {
|
|
1959
|
-
severityCount[severity] += 1
|
|
1960
|
-
}
|
|
1961
|
-
}
|
|
1962
|
-
return severityCount
|
|
1963
|
-
}
|
|
1964
|
-
|
|
1965
|
-
class ColorOrMarkdown {
|
|
1966
|
-
constructor(useMarkdown) {
|
|
1967
|
-
this.useMarkdown = !!useMarkdown
|
|
1968
|
-
}
|
|
1969
|
-
bold(text) {
|
|
1970
|
-
return this.useMarkdown
|
|
1971
|
-
? `**${text}**`
|
|
1972
|
-
: vendor.yoctocolorsCjsExports.bold(`${text}`)
|
|
1973
|
-
}
|
|
1974
|
-
header(text, level = 1) {
|
|
1975
|
-
return this.useMarkdown
|
|
1976
|
-
? `\n${''.padStart(level, '#')} ${text}\n`
|
|
1977
|
-
: vendor.yoctocolorsCjsExports.underline(
|
|
1978
|
-
`\n${level === 1 ? vendor.yoctocolorsCjsExports.bold(text) : text}\n`
|
|
1979
|
-
)
|
|
1980
|
-
}
|
|
1981
|
-
hyperlink(text, url, { fallback = true, fallbackToUrl } = {}) {
|
|
1982
|
-
if (url) {
|
|
1983
|
-
return this.useMarkdown
|
|
1984
|
-
? `[${text}](${url})`
|
|
1985
|
-
: vendor.terminalLinkExports(text, url, {
|
|
1986
|
-
fallback: fallbackToUrl ? (_text, url) => url : fallback
|
|
1987
|
-
})
|
|
1988
|
-
}
|
|
1989
|
-
return text
|
|
1990
|
-
}
|
|
1991
|
-
indent(...args) {
|
|
1992
|
-
return vendor.indentStringExports(...args)
|
|
1993
|
-
}
|
|
1994
|
-
italic(text) {
|
|
1995
|
-
return this.useMarkdown
|
|
1996
|
-
? `_${text}_`
|
|
1997
|
-
: vendor.yoctocolorsCjsExports.italic(`${text}`)
|
|
1998
|
-
}
|
|
1999
|
-
json(value) {
|
|
2000
|
-
return this.useMarkdown
|
|
2001
|
-
? '```json\n' + JSON.stringify(value) + '\n```'
|
|
2002
|
-
: JSON.stringify(value)
|
|
2003
|
-
}
|
|
2004
|
-
list(items) {
|
|
2005
|
-
const indentedContent = items.map(item => this.indent(item).trimStart())
|
|
2006
|
-
return this.useMarkdown
|
|
2007
|
-
? `* ${indentedContent.join('\n* ')}\n`
|
|
2008
|
-
: `${indentedContent.join('\n')}\n`
|
|
2009
|
-
}
|
|
2010
|
-
}
|
|
2011
|
-
|
|
2012
|
-
function getSocketDevAlertUrl(alertType) {
|
|
2013
|
-
return `https://socket.dev/alerts/${alertType}`
|
|
2014
|
-
}
|
|
2015
|
-
function getSocketDevPackageOverviewUrl(eco, name, version) {
|
|
2016
|
-
return `https://socket.dev/${eco}/package/${name}${version ? `/overview/${version}` : ''}`
|
|
2017
|
-
}
|
|
2018
|
-
|
|
2019
|
-
let _translations
|
|
2020
|
-
function getTranslations() {
|
|
2021
|
-
if (_translations === undefined) {
|
|
2022
|
-
_translations = require(
|
|
2023
|
-
// Lazily access constants.rootPath.
|
|
2024
|
-
path.join(constants.rootPath, 'translations.json')
|
|
2025
|
-
)
|
|
2026
|
-
}
|
|
2027
|
-
return _translations
|
|
2028
|
-
}
|
|
2029
|
-
|
|
2030
|
-
const ALERT_SEVERITY_COLOR = createEnum({
|
|
2031
|
-
critical: 'magenta',
|
|
2032
|
-
high: 'red',
|
|
2033
|
-
middle: 'yellow',
|
|
2034
|
-
low: 'white'
|
|
2035
|
-
})
|
|
2036
|
-
const ALERT_SEVERITY_ORDER = createEnum({
|
|
2037
|
-
critical: 0,
|
|
2038
|
-
high: 1,
|
|
2039
|
-
middle: 2,
|
|
2040
|
-
low: 3,
|
|
2041
|
-
none: 4
|
|
2042
|
-
})
|
|
2043
|
-
const { CVE_ALERT_PROPS_FIRST_PATCHED_VERSION_IDENTIFIER, NPM: NPM$1 } =
|
|
2044
|
-
constants
|
|
2045
|
-
const MIN_ABOVE_THE_FOLD_COUNT = 3
|
|
2046
|
-
const MIN_ABOVE_THE_FOLD_ALERT_COUNT = 1
|
|
2047
|
-
const format = new ColorOrMarkdown(false)
|
|
2048
|
-
function alertsHaveBlocked(alerts) {
|
|
2049
|
-
return alerts.find(a => a.blocked) !== undefined
|
|
2050
|
-
}
|
|
2051
|
-
function alertsHaveSeverity(alerts, severity) {
|
|
2052
|
-
return alerts.find(a => a.raw.severity === severity) !== undefined
|
|
2053
|
-
}
|
|
2054
|
-
function alertSeverityComparator(a, b) {
|
|
2055
|
-
return getAlertSeverityOrder(a) - getAlertSeverityOrder(b)
|
|
2056
|
-
}
|
|
2057
|
-
function getAlertSeverityOrder(alert) {
|
|
2058
|
-
const { severity } = alert.raw
|
|
2059
|
-
return severity === ALERT_SEVERITY.critical
|
|
2060
|
-
? 0
|
|
2061
|
-
: severity === ALERT_SEVERITY.high
|
|
2062
|
-
? 1
|
|
2063
|
-
: severity === ALERT_SEVERITY.middle
|
|
2064
|
-
? 2
|
|
2065
|
-
: severity === ALERT_SEVERITY.low
|
|
2066
|
-
? 3
|
|
2067
|
-
: 4
|
|
2068
|
-
}
|
|
2069
|
-
function getAlertsSeverityOrder(alerts) {
|
|
2070
|
-
return alertsHaveBlocked(alerts) ||
|
|
2071
|
-
alertsHaveSeverity(alerts, ALERT_SEVERITY.critical)
|
|
2072
|
-
? 0
|
|
2073
|
-
: alertsHaveSeverity(alerts, ALERT_SEVERITY.high)
|
|
2074
|
-
? 1
|
|
2075
|
-
: alertsHaveSeverity(alerts, ALERT_SEVERITY.middle)
|
|
2076
|
-
? 2
|
|
2077
|
-
: alertsHaveSeverity(alerts, ALERT_SEVERITY.low)
|
|
2078
|
-
? 3
|
|
2079
|
-
: 4
|
|
2080
|
-
}
|
|
2081
|
-
function getHiddenRiskCounts(hiddenAlerts) {
|
|
2082
|
-
const riskCounts = {
|
|
2083
|
-
critical: 0,
|
|
2084
|
-
high: 0,
|
|
2085
|
-
middle: 0,
|
|
2086
|
-
low: 0
|
|
2087
|
-
}
|
|
2088
|
-
for (const alert of hiddenAlerts) {
|
|
2089
|
-
switch (getAlertSeverityOrder(alert)) {
|
|
2090
|
-
case ALERT_SEVERITY_ORDER.critical:
|
|
2091
|
-
riskCounts.critical += 1
|
|
2092
|
-
break
|
|
2093
|
-
case ALERT_SEVERITY_ORDER.high:
|
|
2094
|
-
riskCounts.high += 1
|
|
2095
|
-
break
|
|
2096
|
-
case ALERT_SEVERITY_ORDER.middle:
|
|
2097
|
-
riskCounts.middle += 1
|
|
2098
|
-
break
|
|
2099
|
-
case ALERT_SEVERITY_ORDER.low:
|
|
2100
|
-
riskCounts.low += 1
|
|
2101
|
-
break
|
|
2102
|
-
}
|
|
2103
|
-
}
|
|
2104
|
-
return riskCounts
|
|
2105
|
-
}
|
|
2106
|
-
function getHiddenRisksDescription(riskCounts) {
|
|
2107
|
-
const descriptions = []
|
|
2108
|
-
if (riskCounts.critical) {
|
|
2109
|
-
descriptions.push(`${riskCounts.critical} ${getSeverityLabel('critical')}`)
|
|
2110
|
-
}
|
|
2111
|
-
if (riskCounts.high) {
|
|
2112
|
-
descriptions.push(`${riskCounts.high} ${getSeverityLabel('high')}`)
|
|
2113
|
-
}
|
|
2114
|
-
if (riskCounts.middle) {
|
|
2115
|
-
descriptions.push(`${riskCounts.middle} ${getSeverityLabel('middle')}`)
|
|
2116
|
-
}
|
|
2117
|
-
if (riskCounts.low) {
|
|
2118
|
-
descriptions.push(`${riskCounts.low} ${getSeverityLabel('low')}`)
|
|
2119
|
-
}
|
|
2120
|
-
return `(${descriptions.join('; ')})`
|
|
2121
|
-
}
|
|
2122
|
-
function getSeverityLabel(severity) {
|
|
2123
|
-
return severity === 'middle' ? 'moderate' : severity
|
|
2124
|
-
}
|
|
2125
|
-
async function addArtifactToAlertsMap(artifact, alertsByPkgId, options) {
|
|
2126
|
-
// Make TypeScript happy.
|
|
2127
|
-
if (!artifact.name || !artifact.version || !artifact.alerts?.length) {
|
|
2128
|
-
return alertsByPkgId
|
|
2129
|
-
}
|
|
2130
|
-
const {
|
|
2131
|
-
consolidate = false,
|
|
2132
|
-
include: _include,
|
|
2133
|
-
overrides
|
|
2134
|
-
} = {
|
|
2135
|
-
__proto__: null,
|
|
2136
|
-
...options
|
|
2137
|
-
}
|
|
2138
|
-
const include = {
|
|
2139
|
-
__proto__: null,
|
|
2140
|
-
blocked: true,
|
|
2141
|
-
critical: true,
|
|
2142
|
-
cve: true,
|
|
2143
|
-
unfixable: true,
|
|
2144
|
-
upgradable: false,
|
|
2145
|
-
..._include
|
|
2146
|
-
}
|
|
2147
|
-
const name = packages.resolvePackageName(artifact)
|
|
2148
|
-
const { version } = artifact
|
|
2149
|
-
const pkgId = `${name}@${version}`
|
|
2150
|
-
const major = vendor.semverExports.major(version)
|
|
2151
|
-
const socketYml = findSocketYmlSync()
|
|
2152
|
-
const enabledState = {
|
|
2153
|
-
__proto__: null,
|
|
2154
|
-
...socketYml?.parsed.issueRules
|
|
2155
|
-
}
|
|
2156
|
-
let sockPkgAlerts = []
|
|
2157
|
-
for (const alert of artifact.alerts) {
|
|
2158
|
-
const action = alert.action ?? ''
|
|
2159
|
-
const enabledFlag = enabledState[alert.type]
|
|
2160
|
-
if (
|
|
2161
|
-
(action === 'ignore' && enabledFlag !== true) ||
|
|
2162
|
-
enabledFlag === false
|
|
2163
|
-
) {
|
|
2164
|
-
continue
|
|
2165
|
-
}
|
|
2166
|
-
const blocked = action === 'error'
|
|
2167
|
-
const critical = alert.severity === ALERT_SEVERITY.critical
|
|
2168
|
-
const cve = isArtifactAlertCve(alert)
|
|
2169
|
-
const fixType = alert.fix?.type ?? ''
|
|
2170
|
-
const fixableCve = fixType === ALERT_FIX_TYPE.cve
|
|
2171
|
-
const fixableUpgrade = fixType === ALERT_FIX_TYPE.upgrade
|
|
2172
|
-
const fixable = fixableCve || fixableUpgrade
|
|
2173
|
-
const upgradable = fixableUpgrade && !objects.hasOwn(overrides, name)
|
|
2174
|
-
if (
|
|
2175
|
-
(include.blocked && blocked) ||
|
|
2176
|
-
(include.critical && critical) ||
|
|
2177
|
-
(include.cve && cve) ||
|
|
2178
|
-
(include.unfixable && !fixable) ||
|
|
2179
|
-
(include.upgradable && upgradable)
|
|
2180
|
-
) {
|
|
2181
|
-
sockPkgAlerts.push({
|
|
2182
|
-
name,
|
|
2183
|
-
version,
|
|
2184
|
-
key: alert.key,
|
|
2185
|
-
type: alert.type,
|
|
2186
|
-
blocked,
|
|
2187
|
-
critical,
|
|
2188
|
-
fixable,
|
|
2189
|
-
raw: alert,
|
|
2190
|
-
upgradable
|
|
2191
|
-
})
|
|
2192
|
-
}
|
|
2193
|
-
}
|
|
2194
|
-
if (!sockPkgAlerts.length) {
|
|
2195
|
-
return alertsByPkgId
|
|
2196
|
-
}
|
|
2197
|
-
if (consolidate) {
|
|
2198
|
-
const highestForCve = new Map()
|
|
2199
|
-
const highestForUpgrade = new Map()
|
|
2200
|
-
const unfixableAlerts = []
|
|
2201
|
-
for (const sockPkgAlert of sockPkgAlerts) {
|
|
2202
|
-
const alert = sockPkgAlert.raw
|
|
2203
|
-
const fixType = alert.fix?.type ?? ''
|
|
2204
|
-
if (fixType === ALERT_FIX_TYPE.cve) {
|
|
2205
|
-
const patchedVersion =
|
|
2206
|
-
alert.props[CVE_ALERT_PROPS_FIRST_PATCHED_VERSION_IDENTIFIER]
|
|
2207
|
-
const patchedMajor = vendor.semverExports.major(patchedVersion)
|
|
2208
|
-
const oldHighest = highestForCve.get(patchedMajor)
|
|
2209
|
-
const highest = oldHighest?.version ?? '0.0.0'
|
|
2210
|
-
if (vendor.semverExports.gt(patchedVersion, highest)) {
|
|
2211
|
-
highestForCve.set(patchedMajor, {
|
|
2212
|
-
alert: sockPkgAlert,
|
|
2213
|
-
version: patchedVersion
|
|
2214
|
-
})
|
|
2215
|
-
}
|
|
2216
|
-
} else if (fixType === ALERT_FIX_TYPE.upgrade) {
|
|
2217
|
-
const oldHighest = highestForUpgrade.get(major)
|
|
2218
|
-
const highest = oldHighest?.version ?? '0.0.0'
|
|
2219
|
-
if (vendor.semverExports.gt(version, highest)) {
|
|
2220
|
-
highestForUpgrade.set(major, {
|
|
2221
|
-
alert: sockPkgAlert,
|
|
2222
|
-
version
|
|
2223
|
-
})
|
|
2224
|
-
}
|
|
2225
|
-
} else {
|
|
2226
|
-
unfixableAlerts.push(sockPkgAlert)
|
|
2227
|
-
}
|
|
2228
|
-
}
|
|
2229
|
-
sockPkgAlerts = [
|
|
2230
|
-
...unfixableAlerts,
|
|
2231
|
-
...[...highestForCve.values()].map(d => d.alert),
|
|
2232
|
-
...[...highestForUpgrade.values()].map(d => d.alert)
|
|
2233
|
-
]
|
|
2234
|
-
}
|
|
2235
|
-
if (sockPkgAlerts.length) {
|
|
2236
|
-
sockPkgAlerts.sort((a, b) => sorts.naturalCompare(a.type, b.type))
|
|
2237
|
-
alertsByPkgId.set(pkgId, sockPkgAlerts)
|
|
2238
|
-
}
|
|
2239
|
-
return alertsByPkgId
|
|
2240
|
-
}
|
|
2241
|
-
function getCveInfoByAlertsMap(alertsMap, options) {
|
|
2242
|
-
const { exclude: _exclude, limit = Infinity } = {
|
|
2243
|
-
__proto__: null,
|
|
2244
|
-
...options
|
|
2245
|
-
}
|
|
2246
|
-
const exclude = {
|
|
2247
|
-
__proto__: null,
|
|
2248
|
-
upgradable: true,
|
|
2249
|
-
..._exclude
|
|
2250
|
-
}
|
|
2251
|
-
let count = 0
|
|
2252
|
-
let infoByPkg = null
|
|
2253
|
-
alertsMapLoop: for (const [pkgId, sockPkgAlerts] of alertsMap) {
|
|
2254
|
-
const purlObj = vendor.packageurlJsExports.PackageURL.fromString(
|
|
2255
|
-
idToPurl(pkgId)
|
|
2256
|
-
)
|
|
2257
|
-
const name = packages.resolvePackageName(purlObj)
|
|
2258
|
-
for (const sockPkgAlert of sockPkgAlerts) {
|
|
2259
|
-
const alert = sockPkgAlert.raw
|
|
2260
|
-
if (
|
|
2261
|
-
alert.fix?.type !== ALERT_FIX_TYPE.cve ||
|
|
2262
|
-
(exclude.upgradable && registry.getManifestData(NPM$1, name))
|
|
2263
|
-
) {
|
|
2264
|
-
continue
|
|
2265
|
-
}
|
|
2266
|
-
if (!infoByPkg) {
|
|
2267
|
-
infoByPkg = new Map()
|
|
2268
|
-
}
|
|
2269
|
-
let infos = infoByPkg.get(name)
|
|
2270
|
-
if (!infos) {
|
|
2271
|
-
infos = []
|
|
2272
|
-
infoByPkg.set(name, infos)
|
|
2273
|
-
}
|
|
2274
|
-
const { firstPatchedVersionIdentifier, vulnerableVersionRange } =
|
|
2275
|
-
alert.props
|
|
2276
|
-
try {
|
|
2277
|
-
infos.push({
|
|
2278
|
-
firstPatchedVersionIdentifier,
|
|
2279
|
-
vulnerableVersionRange: new vendor.semverExports.Range(
|
|
2280
|
-
// Replace ', ' in a range like '>= 1.0.0, < 1.8.2' with ' ' so that
|
|
2281
|
-
// semver.Range will parse it without erroring.
|
|
2282
|
-
vulnerableVersionRange.replace(/, +/g, ' ')
|
|
2283
|
-
).format()
|
|
2284
|
-
})
|
|
2285
|
-
if (++count >= limit) {
|
|
2286
|
-
break alertsMapLoop
|
|
2287
|
-
}
|
|
2288
|
-
} catch (e) {
|
|
2289
|
-
debug.debugLog('getCveInfoByAlertsMap', {
|
|
2290
|
-
firstPatchedVersionIdentifier,
|
|
2291
|
-
vulnerableVersionRange
|
|
2292
|
-
})
|
|
2293
|
-
debug.debugLog(e)
|
|
2294
|
-
}
|
|
2295
|
-
}
|
|
2296
|
-
}
|
|
2297
|
-
return infoByPkg
|
|
2298
|
-
}
|
|
2299
|
-
function logAlertsMap(alertsMap, options) {
|
|
2300
|
-
const { hideAt = 'middle', output = process.stderr } = {
|
|
2301
|
-
__proto__: null,
|
|
2302
|
-
...options
|
|
2303
|
-
}
|
|
2304
|
-
const translations = getTranslations()
|
|
2305
|
-
const sortedEntries = [...alertsMap.entries()].sort(
|
|
2306
|
-
(a, b) => getAlertsSeverityOrder(a[1]) - getAlertsSeverityOrder(b[1])
|
|
2307
|
-
)
|
|
2308
|
-
const aboveTheFoldPkgIds = new Set()
|
|
2309
|
-
const viewableAlertsByPkgId = new Map()
|
|
2310
|
-
const hiddenAlertsByPkgId = new Map()
|
|
2311
|
-
for (let i = 0, { length } = sortedEntries; i < length; i += 1) {
|
|
2312
|
-
const { 0: pkgId, 1: alerts } = sortedEntries[i]
|
|
2313
|
-
const hiddenAlerts = []
|
|
2314
|
-
const viewableAlerts = alerts.filter(a => {
|
|
2315
|
-
const keep =
|
|
2316
|
-
a.blocked || getAlertSeverityOrder(a) < ALERT_SEVERITY_ORDER[hideAt]
|
|
2317
|
-
if (!keep) {
|
|
2318
|
-
hiddenAlerts.push(a)
|
|
2319
|
-
}
|
|
2320
|
-
return keep
|
|
2321
|
-
})
|
|
2322
|
-
if (hiddenAlerts.length) {
|
|
2323
|
-
hiddenAlertsByPkgId.set(pkgId, hiddenAlerts.sort(alertSeverityComparator))
|
|
2324
|
-
}
|
|
2325
|
-
if (!viewableAlerts.length) {
|
|
2326
|
-
continue
|
|
2327
|
-
}
|
|
2328
|
-
viewableAlerts.sort(alertSeverityComparator)
|
|
2329
|
-
viewableAlertsByPkgId.set(pkgId, viewableAlerts)
|
|
2330
|
-
if (
|
|
2331
|
-
viewableAlerts.find(
|
|
2332
|
-
a => a.blocked || getAlertSeverityOrder(a) < ALERT_SEVERITY_ORDER.middle
|
|
2333
|
-
)
|
|
2334
|
-
) {
|
|
2335
|
-
aboveTheFoldPkgIds.add(pkgId)
|
|
2336
|
-
}
|
|
2337
|
-
}
|
|
2338
|
-
|
|
2339
|
-
// If MIN_ABOVE_THE_FOLD_COUNT is NOT met add more from viewable pkg ids.
|
|
2340
|
-
for (const { 0: pkgId } of viewableAlertsByPkgId.entries()) {
|
|
2341
|
-
if (aboveTheFoldPkgIds.size >= MIN_ABOVE_THE_FOLD_COUNT) {
|
|
2342
|
-
break
|
|
2343
|
-
}
|
|
2344
|
-
aboveTheFoldPkgIds.add(pkgId)
|
|
2345
|
-
}
|
|
2346
|
-
// If MIN_ABOVE_THE_FOLD_COUNT is STILL NOT met add more from hidden pkg ids.
|
|
2347
|
-
for (const { 0: pkgId, 1: hiddenAlerts } of hiddenAlertsByPkgId.entries()) {
|
|
2348
|
-
if (aboveTheFoldPkgIds.size >= MIN_ABOVE_THE_FOLD_COUNT) {
|
|
2349
|
-
break
|
|
2350
|
-
}
|
|
2351
|
-
aboveTheFoldPkgIds.add(pkgId)
|
|
2352
|
-
const viewableAlerts = viewableAlertsByPkgId.get(pkgId) ?? []
|
|
2353
|
-
if (viewableAlerts.length < MIN_ABOVE_THE_FOLD_ALERT_COUNT) {
|
|
2354
|
-
const neededCount = MIN_ABOVE_THE_FOLD_ALERT_COUNT - viewableAlerts.length
|
|
2355
|
-
let removedHiddenAlerts
|
|
2356
|
-
if (hiddenAlerts.length - neededCount > 0) {
|
|
2357
|
-
removedHiddenAlerts = hiddenAlerts.splice(
|
|
2358
|
-
0,
|
|
2359
|
-
MIN_ABOVE_THE_FOLD_ALERT_COUNT
|
|
2360
|
-
)
|
|
2361
|
-
} else {
|
|
2362
|
-
removedHiddenAlerts = hiddenAlerts
|
|
2363
|
-
hiddenAlertsByPkgId.delete(pkgId)
|
|
2364
|
-
}
|
|
2365
|
-
viewableAlertsByPkgId.set(pkgId, [
|
|
2366
|
-
...viewableAlerts,
|
|
2367
|
-
...removedHiddenAlerts
|
|
2368
|
-
])
|
|
2369
|
-
}
|
|
2370
|
-
}
|
|
2371
|
-
const mentionedPkgIdsWithHiddenAlerts = new Set()
|
|
2372
|
-
for (
|
|
2373
|
-
let i = 0,
|
|
2374
|
-
prevAboveTheFold = true,
|
|
2375
|
-
entries = [...viewableAlertsByPkgId.entries()],
|
|
2376
|
-
{ length } = entries;
|
|
2377
|
-
i < length;
|
|
2378
|
-
i += 1
|
|
2379
|
-
) {
|
|
2380
|
-
const { 0: pkgId, 1: alerts } = entries[i]
|
|
2381
|
-
const lines = new Set()
|
|
2382
|
-
for (const alert of alerts) {
|
|
2383
|
-
const { type } = alert
|
|
2384
|
-
const severity = alert.raw.severity ?? ''
|
|
2385
|
-
const attributes = [
|
|
2386
|
-
...(severity
|
|
2387
|
-
? [
|
|
2388
|
-
vendor.yoctocolorsCjsExports[ALERT_SEVERITY_COLOR[severity]](
|
|
2389
|
-
getSeverityLabel(severity)
|
|
2390
|
-
)
|
|
2391
|
-
]
|
|
2392
|
-
: []),
|
|
2393
|
-
...(alert.blocked
|
|
2394
|
-
? [
|
|
2395
|
-
vendor.yoctocolorsCjsExports.bold(
|
|
2396
|
-
vendor.yoctocolorsCjsExports.red('blocked')
|
|
2397
|
-
)
|
|
2398
|
-
]
|
|
2399
|
-
: []),
|
|
2400
|
-
...(alert.fixable ? ['fixable'] : [])
|
|
2401
|
-
]
|
|
2402
|
-
const maybeAttributes = attributes.length
|
|
2403
|
-
? ` ${vendor.yoctocolorsCjsExports.italic(`(${attributes.join('; ')})`)}`
|
|
2404
|
-
: ''
|
|
2405
|
-
// Based data from { pageProps: { alertTypes } } of:
|
|
2406
|
-
// https://socket.dev/_next/data/94666139314b6437ee4491a0864e72b264547585/en-US.json
|
|
2407
|
-
const info = translations.alerts[type]
|
|
2408
|
-
const title = info?.title ?? type
|
|
2409
|
-
const maybeDesc = info?.description ? ` - ${info.description}` : ''
|
|
2410
|
-
const content = `${title}${maybeAttributes}${maybeDesc}`
|
|
2411
|
-
// TODO: emoji seems to mis-align terminals sometimes
|
|
2412
|
-
lines.add(` ${content}`)
|
|
2413
|
-
}
|
|
2414
|
-
const purlObj = vendor.packageurlJsExports.PackageURL.fromString(
|
|
2415
|
-
idToPurl(pkgId)
|
|
2416
|
-
)
|
|
2417
|
-
const hyperlink = format.hyperlink(
|
|
2418
|
-
pkgId,
|
|
2419
|
-
getSocketDevPackageOverviewUrl(
|
|
2420
|
-
NPM$1,
|
|
2421
|
-
packages.resolvePackageName(purlObj),
|
|
2422
|
-
purlObj.version
|
|
2423
|
-
)
|
|
2424
|
-
)
|
|
2425
|
-
const isAboveTheFold = aboveTheFoldPkgIds.has(pkgId)
|
|
2426
|
-
if (isAboveTheFold) {
|
|
2427
|
-
aboveTheFoldPkgIds.add(pkgId)
|
|
2428
|
-
output.write(`${i ? '\n' : ''}${hyperlink}:\n`)
|
|
2429
|
-
} else {
|
|
2430
|
-
output.write(`${prevAboveTheFold ? '\n' : ''}${hyperlink}:\n`)
|
|
2431
|
-
}
|
|
2432
|
-
for (const line of lines) {
|
|
2433
|
-
output.write(`${line}\n`)
|
|
2434
|
-
}
|
|
2435
|
-
const hiddenAlerts = hiddenAlertsByPkgId.get(pkgId) ?? []
|
|
2436
|
-
const { length: hiddenAlertsCount } = hiddenAlerts
|
|
2437
|
-
if (hiddenAlertsCount) {
|
|
2438
|
-
mentionedPkgIdsWithHiddenAlerts.add(pkgId)
|
|
2439
|
-
if (hiddenAlertsCount === 1) {
|
|
2440
|
-
output.write(
|
|
2441
|
-
` ${vendor.yoctocolorsCjsExports.dim(`+1 Hidden ${getSeverityLabel(hiddenAlerts[0].raw.severity ?? 'low')} risk alert`)}\n`
|
|
2442
|
-
)
|
|
2443
|
-
} else {
|
|
2444
|
-
output.write(
|
|
2445
|
-
` ${vendor.yoctocolorsCjsExports.dim(`+${hiddenAlertsCount} Hidden alerts ${vendor.yoctocolorsCjsExports.italic(getHiddenRisksDescription(getHiddenRiskCounts(hiddenAlerts)))}`)}\n`
|
|
2446
|
-
)
|
|
2447
|
-
}
|
|
2448
|
-
}
|
|
2449
|
-
prevAboveTheFold = isAboveTheFold
|
|
2450
|
-
}
|
|
2451
|
-
const additionalHiddenCount =
|
|
2452
|
-
hiddenAlertsByPkgId.size - mentionedPkgIdsWithHiddenAlerts.size
|
|
2453
|
-
if (additionalHiddenCount) {
|
|
2454
|
-
const totalRiskCounts = {
|
|
2455
|
-
critical: 0,
|
|
2456
|
-
high: 0,
|
|
2457
|
-
middle: 0,
|
|
2458
|
-
low: 0
|
|
2459
|
-
}
|
|
2460
|
-
for (const { 0: pkgId, 1: alerts } of hiddenAlertsByPkgId.entries()) {
|
|
2461
|
-
if (mentionedPkgIdsWithHiddenAlerts.has(pkgId)) {
|
|
2462
|
-
continue
|
|
2463
|
-
}
|
|
2464
|
-
const riskCounts = getHiddenRiskCounts(alerts)
|
|
2465
|
-
totalRiskCounts.critical += riskCounts.critical
|
|
2466
|
-
totalRiskCounts.high += riskCounts.high
|
|
2467
|
-
totalRiskCounts.middle += riskCounts.middle
|
|
2468
|
-
totalRiskCounts.low += riskCounts.low
|
|
2469
|
-
}
|
|
2470
|
-
output.write(
|
|
2471
|
-
`${aboveTheFoldPkgIds.size ? '\n' : ''}${vendor.yoctocolorsCjsExports.dim(`${aboveTheFoldPkgIds.size ? '+' : ''}${additionalHiddenCount} Packages with hidden alerts ${vendor.yoctocolorsCjsExports.italic(getHiddenRisksDescription(totalRiskCounts))}`)}\n`
|
|
2472
|
-
)
|
|
2473
|
-
}
|
|
2474
|
-
output.write('\n')
|
|
2475
|
-
}
|
|
2476
|
-
|
|
2477
|
-
async function getAlertsMapFromArborist(arb, options_) {
|
|
2478
|
-
const options = {
|
|
2479
|
-
__proto__: null,
|
|
2480
|
-
consolidate: false,
|
|
2481
|
-
limit: Infinity,
|
|
2482
|
-
nothrow: false,
|
|
2483
|
-
...options_
|
|
2484
|
-
}
|
|
2485
|
-
const include = {
|
|
2486
|
-
__proto__: null,
|
|
2487
|
-
existing: false,
|
|
2488
|
-
...options.include
|
|
2489
|
-
}
|
|
2490
|
-
const needInfoOn = getDetailsFromDiff(arb.diff, {
|
|
2491
|
-
include: {
|
|
2492
|
-
unchanged: include.existing
|
|
2493
|
-
}
|
|
2494
|
-
})
|
|
2495
|
-
const purls = needInfoOn.map(d => idToPurl(d.node.pkgid))
|
|
2496
|
-
let overrides
|
|
2497
|
-
const overridesMap = (
|
|
2498
|
-
arb.actualTree ??
|
|
2499
|
-
arb.idealTree ??
|
|
2500
|
-
(await arb.loadActual())
|
|
2501
|
-
)?.overrides?.children
|
|
2502
|
-
if (overridesMap) {
|
|
2503
|
-
overrides = Object.fromEntries(
|
|
2504
|
-
[...overridesMap.entries()].map(([key, overrideSet]) => {
|
|
2505
|
-
return [key, overrideSet.value]
|
|
2506
|
-
})
|
|
2507
|
-
)
|
|
2508
|
-
}
|
|
2509
|
-
return await getAlertsMapFromPurls(purls, {
|
|
2510
|
-
overrides,
|
|
2511
|
-
...options
|
|
2512
|
-
})
|
|
2513
|
-
}
|
|
2514
|
-
async function getAlertsMapFromPnpmLockfile(lockfile, options_) {
|
|
2515
|
-
const options = {
|
|
2516
|
-
__proto__: null,
|
|
2517
|
-
consolidate: false,
|
|
2518
|
-
limit: Infinity,
|
|
2519
|
-
nothrow: false,
|
|
2520
|
-
...options_
|
|
2521
|
-
}
|
|
2522
|
-
const purls = extractPurlsFromPnpmLockfile(lockfile)
|
|
2523
|
-
return await getAlertsMapFromPurls(purls, {
|
|
2524
|
-
overrides: lockfile.overrides,
|
|
2525
|
-
...options
|
|
2526
|
-
})
|
|
2527
|
-
}
|
|
2528
|
-
async function getAlertsMapFromPurls(purls, options_) {
|
|
2529
|
-
const options = {
|
|
2530
|
-
__proto__: null,
|
|
2531
|
-
consolidate: false,
|
|
2532
|
-
nothrow: false,
|
|
2533
|
-
...options_
|
|
2534
|
-
}
|
|
2535
|
-
const include = {
|
|
2536
|
-
__proto__: null,
|
|
2537
|
-
actions: undefined,
|
|
2538
|
-
blocked: true,
|
|
2539
|
-
critical: true,
|
|
2540
|
-
cve: true,
|
|
2541
|
-
existing: false,
|
|
2542
|
-
unfixable: true,
|
|
2543
|
-
upgradable: false,
|
|
2544
|
-
...options.include
|
|
2545
|
-
}
|
|
2546
|
-
const { spinner } = options
|
|
2547
|
-
const uniqPurls = arrays.arrayUnique(purls)
|
|
2548
|
-
let { length: remaining } = uniqPurls
|
|
2549
|
-
const alertsByPkgId = new Map()
|
|
2550
|
-
if (!remaining) {
|
|
2551
|
-
return alertsByPkgId
|
|
2552
|
-
}
|
|
2553
|
-
const getText = () => `Looking up data for ${remaining} packages`
|
|
2554
|
-
spinner?.start(getText())
|
|
2555
|
-
const sockSdk = await setupSdk(getPublicToken())
|
|
2556
|
-
const toAlertsMapOptions = {
|
|
2557
|
-
overrides: options.overrides,
|
|
2558
|
-
consolidate: options.consolidate,
|
|
2559
|
-
include,
|
|
2560
|
-
spinner
|
|
2561
|
-
}
|
|
2562
|
-
for await (const batchResult of sockSdk.batchPackageStream(
|
|
2563
|
-
{
|
|
2564
|
-
alerts: 'true',
|
|
2565
|
-
compact: 'true',
|
|
2566
|
-
...(include.actions
|
|
2567
|
-
? {
|
|
2568
|
-
actions: include.actions.join(',')
|
|
2569
|
-
}
|
|
2570
|
-
: {}),
|
|
2571
|
-
...(include.unfixable
|
|
2572
|
-
? {}
|
|
2573
|
-
: {
|
|
2574
|
-
fixable: 'true'
|
|
2575
|
-
})
|
|
2576
|
-
},
|
|
2577
|
-
{
|
|
2578
|
-
components: uniqPurls.map(purl => ({
|
|
2579
|
-
purl
|
|
2580
|
-
}))
|
|
2581
|
-
}
|
|
2582
|
-
)) {
|
|
2583
|
-
if (batchResult.success) {
|
|
2584
|
-
await addArtifactToAlertsMap(
|
|
2585
|
-
batchResult.data,
|
|
2586
|
-
alertsByPkgId,
|
|
2587
|
-
toAlertsMapOptions
|
|
2588
|
-
)
|
|
2589
|
-
} else if (!options.nothrow) {
|
|
2590
|
-
const statusCode = batchResult.status ?? 'unknown'
|
|
2591
|
-
const statusMessage = batchResult.error ?? 'No status message'
|
|
2592
|
-
throw new Error(
|
|
2593
|
-
`Socket API server error (${statusCode}): ${statusMessage}`
|
|
2594
|
-
)
|
|
2595
|
-
}
|
|
2596
|
-
remaining -= 1
|
|
2597
|
-
if (spinner && remaining > 0) {
|
|
2598
|
-
spinner.start()
|
|
2599
|
-
spinner.setText(getText())
|
|
2600
|
-
}
|
|
2601
|
-
}
|
|
2602
|
-
spinner?.stop()
|
|
2603
|
-
return alertsByPkgId
|
|
2604
|
-
}
|
|
2605
|
-
|
|
2606
1136
|
const require$2 = Module.createRequire(
|
|
2607
|
-
|
|
2608
|
-
? require('u' + 'rl').pathToFileURL(__filename).href
|
|
2609
|
-
: (_documentCurrentScript &&
|
|
2610
|
-
_documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' &&
|
|
2611
|
-
_documentCurrentScript.src) ||
|
|
2612
|
-
new URL('shadow-npm-inject.js', document.baseURI).href
|
|
1137
|
+
require('u' + 'rl').pathToFileURL(__filename).href
|
|
2613
1138
|
)
|
|
2614
1139
|
const {
|
|
2615
1140
|
NPM,
|
|
@@ -2634,7 +1159,7 @@ const SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES = {
|
|
|
2634
1159
|
}
|
|
2635
1160
|
const kCtorArgs = Symbol('ctorArgs')
|
|
2636
1161
|
const kRiskyReify = Symbol('riskyReify')
|
|
2637
|
-
const Arborist = require$2(
|
|
1162
|
+
const Arborist = require$2(getArboristClassPath())
|
|
2638
1163
|
|
|
2639
1164
|
// Implementation code not related to our custom behavior is based on
|
|
2640
1165
|
// https://github.com/npm/cli/blob/v11.0.0/workspaces/arborist/lib/arborist/index.js:
|
|
@@ -2722,7 +1247,7 @@ class SafeArborist extends Arborist {
|
|
|
2722
1247
|
process.exitCode = 1
|
|
2723
1248
|
// Lazily access constants.ENV.SOCKET_CLI_VIEW_ALL_RISKS.
|
|
2724
1249
|
const viewAllRisks = constants.ENV.SOCKET_CLI_VIEW_ALL_RISKS
|
|
2725
|
-
logAlertsMap(alertsMap, {
|
|
1250
|
+
utils.logAlertsMap(alertsMap, {
|
|
2726
1251
|
hideAt: viewAllRisks ? 'none' : 'middle',
|
|
2727
1252
|
output: process.stderr
|
|
2728
1253
|
})
|
|
@@ -2744,78 +1269,37 @@ class SafeArborist extends Arborist {
|
|
|
2744
1269
|
}
|
|
2745
1270
|
|
|
2746
1271
|
const require$1 = Module.createRequire(
|
|
2747
|
-
|
|
2748
|
-
? require('u' + 'rl').pathToFileURL(__filename).href
|
|
2749
|
-
: (_documentCurrentScript &&
|
|
2750
|
-
_documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' &&
|
|
2751
|
-
_documentCurrentScript.src) ||
|
|
2752
|
-
new URL('shadow-npm-inject.js', document.baseURI).href
|
|
1272
|
+
require('u' + 'rl').pathToFileURL(__filename).href
|
|
2753
1273
|
)
|
|
2754
1274
|
function installSafeArborist() {
|
|
2755
1275
|
// Override '@npmcli/arborist' module exports with patched variants based on
|
|
2756
1276
|
// https://github.com/npm/cli/pull/8089.
|
|
2757
1277
|
const cache = require$1.cache
|
|
2758
|
-
cache[
|
|
1278
|
+
cache[getArboristClassPath()] = {
|
|
2759
1279
|
exports: SafeArborist
|
|
2760
1280
|
}
|
|
2761
|
-
cache[
|
|
1281
|
+
cache[getArboristEdgeClassPath()] = {
|
|
2762
1282
|
exports: SafeEdge
|
|
2763
1283
|
}
|
|
2764
|
-
cache[
|
|
1284
|
+
cache[getArboristNodeClassPath()] = {
|
|
2765
1285
|
exports: SafeNode
|
|
2766
1286
|
}
|
|
2767
|
-
cache[
|
|
1287
|
+
cache[getArboristOverrideSetClassPath()] = {
|
|
2768
1288
|
exports: SafeOverrideSet
|
|
2769
1289
|
}
|
|
2770
1290
|
}
|
|
2771
1291
|
|
|
2772
1292
|
installSafeArborist()
|
|
2773
1293
|
|
|
2774
|
-
exports.ALERT_SEVERITY = ALERT_SEVERITY
|
|
2775
1294
|
exports.Arborist = Arborist
|
|
2776
|
-
exports.AuthError = AuthError
|
|
2777
|
-
exports.ColorOrMarkdown = ColorOrMarkdown
|
|
2778
|
-
exports.InputError = InputError
|
|
2779
|
-
exports.RangeStyles = RangeStyles
|
|
2780
1295
|
exports.SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES =
|
|
2781
1296
|
SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES
|
|
2782
1297
|
exports.SafeArborist = SafeArborist
|
|
2783
|
-
exports.applyRange = applyRange
|
|
2784
|
-
exports.captureException = captureException
|
|
2785
|
-
exports.filterGlobResultToSupportedFiles = filterGlobResultToSupportedFiles
|
|
2786
1298
|
exports.findBestPatchVersion = findBestPatchVersion
|
|
2787
1299
|
exports.findPackageNode = findPackageNode
|
|
2788
1300
|
exports.findPackageNodes = findPackageNodes
|
|
2789
|
-
exports.findUp = findUp
|
|
2790
|
-
exports.formatSeverityCount = formatSeverityCount
|
|
2791
1301
|
exports.getAlertsMapFromArborist = getAlertsMapFromArborist
|
|
2792
|
-
exports.getAlertsMapFromPnpmLockfile = getAlertsMapFromPnpmLockfile
|
|
2793
|
-
exports.getAlertsMapFromPurls = getAlertsMapFromPurls
|
|
2794
|
-
exports.getConfigValue = getConfigValue
|
|
2795
|
-
exports.getConfigValueOrUndef = getConfigValueOrUndef
|
|
2796
|
-
exports.getCveInfoByAlertsMap = getCveInfoByAlertsMap
|
|
2797
|
-
exports.getDefaultToken = getDefaultToken
|
|
2798
|
-
exports.getPublicToken = getPublicToken
|
|
2799
|
-
exports.getSeverityCount = getSeverityCount
|
|
2800
|
-
exports.getSocketDevAlertUrl = getSocketDevAlertUrl
|
|
2801
|
-
exports.getSocketDevPackageOverviewUrl = getSocketDevPackageOverviewUrl
|
|
2802
|
-
exports.globWithGitIgnore = globWithGitIgnore
|
|
2803
|
-
exports.globWorkspace = globWorkspace
|
|
2804
|
-
exports.idToPurl = idToPurl
|
|
2805
|
-
exports.isReadOnlyConfig = isReadOnlyConfig
|
|
2806
|
-
exports.isTestingV1 = isTestingV1
|
|
2807
|
-
exports.overrideCachedConfig = overrideCachedConfig
|
|
2808
|
-
exports.overrideConfigApiToken = overrideConfigApiToken
|
|
2809
|
-
exports.pathsToGlobPatterns = pathsToGlobPatterns
|
|
2810
|
-
exports.readFileBinary = readFileBinary
|
|
2811
|
-
exports.readFileUtf8 = readFileUtf8
|
|
2812
|
-
exports.removeNodeModules = removeNodeModules
|
|
2813
|
-
exports.safeReadFile = safeReadFile
|
|
2814
|
-
exports.sensitiveConfigKeys = sensitiveConfigKeys
|
|
2815
|
-
exports.setupSdk = setupSdk
|
|
2816
|
-
exports.supportedConfigKeys = supportedConfigKeys
|
|
2817
|
-
exports.updateConfigValue = updateConfigValue
|
|
2818
1302
|
exports.updateNode = updateNode
|
|
2819
1303
|
exports.updatePackageJsonFromNode = updatePackageJsonFromNode
|
|
2820
|
-
//# debugId=
|
|
1304
|
+
//# debugId=abb3ad9d-815d-4325-99e6-528b98325c45
|
|
2821
1305
|
//# sourceMappingURL=shadow-npm-inject.js.map
|