@socketsecurity/cli-with-sentry 0.14.67 → 0.14.68
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/blessed/lib/alias.js +521 -0
- package/dist/blessed/lib/blessed.js +34 -0
- package/dist/blessed/lib/colors.js +492 -0
- package/dist/blessed/lib/events.js +197 -0
- package/dist/blessed/lib/gpmclient.js +247 -0
- package/dist/blessed/lib/helpers.js +172 -0
- package/dist/blessed/lib/keys.js +514 -0
- package/dist/blessed/lib/program.js +4532 -0
- package/dist/blessed/lib/tput.js +3113 -0
- package/dist/blessed/lib/unicode.js +914 -0
- package/dist/blessed/lib/widget.js +62 -0
- package/dist/blessed/lib/widgets/ansiimage.js +175 -0
- package/dist/blessed/lib/widgets/bigtext.js +172 -0
- package/dist/blessed/lib/widgets/box.js +36 -0
- package/dist/blessed/lib/widgets/button.js +64 -0
- package/dist/blessed/lib/widgets/checkbox.js +97 -0
- package/dist/blessed/lib/widgets/element.js +2873 -0
- package/dist/blessed/lib/widgets/filemanager.js +225 -0
- package/dist/blessed/lib/widgets/form.js +303 -0
- package/dist/blessed/lib/widgets/image.js +73 -0
- package/dist/blessed/lib/widgets/input.js +36 -0
- package/dist/blessed/lib/widgets/layout.js +251 -0
- package/dist/blessed/lib/widgets/line.js +61 -0
- package/dist/blessed/lib/widgets/list.js +654 -0
- package/dist/blessed/lib/widgets/listbar.js +454 -0
- package/dist/blessed/lib/widgets/listtable.js +267 -0
- package/dist/blessed/lib/widgets/loading.js +90 -0
- package/dist/blessed/lib/widgets/log.js +84 -0
- package/dist/blessed/lib/widgets/message.js +147 -0
- package/dist/blessed/lib/widgets/node.js +316 -0
- package/dist/blessed/lib/widgets/overlayimage.js +796 -0
- package/dist/blessed/lib/widgets/progressbar.js +168 -0
- package/dist/blessed/lib/widgets/prompt.js +129 -0
- package/dist/blessed/lib/widgets/question.js +131 -0
- package/dist/blessed/lib/widgets/radiobutton.js +64 -0
- package/dist/blessed/lib/widgets/radioset.js +38 -0
- package/dist/blessed/lib/widgets/screen.js +2489 -0
- package/dist/blessed/lib/widgets/scrollablebox.js +417 -0
- package/dist/blessed/lib/widgets/scrollabletext.js +37 -0
- package/dist/blessed/lib/widgets/table.js +385 -0
- package/dist/blessed/lib/widgets/terminal.js +454 -0
- package/dist/blessed/lib/widgets/text.js +37 -0
- package/dist/blessed/lib/widgets/textarea.js +378 -0
- package/dist/blessed/lib/widgets/textbox.js +81 -0
- package/dist/blessed/lib/widgets/video.js +132 -0
- package/dist/blessed/usr/fonts/AUTHORS +1 -0
- package/dist/blessed/usr/fonts/LICENSE +94 -0
- package/dist/blessed/usr/fonts/README +340 -0
- package/dist/blessed/usr/fonts/ter-u14b.json +17826 -0
- package/dist/blessed/usr/fonts/ter-u14n.json +17826 -0
- package/dist/blessed/usr/linux +0 -0
- package/dist/blessed/usr/windows-ansi +0 -0
- package/dist/blessed/usr/xterm +0 -0
- package/dist/blessed/usr/xterm-256color +0 -0
- package/dist/blessed/usr/xterm.termcap +243 -0
- package/dist/blessed/usr/xterm.terminfo +1977 -0
- package/dist/blessed/vendor/tng.js +1878 -0
- package/dist/constants.d.ts +271 -207
- package/dist/constants.js +271 -227
- package/dist/constants.js.map +1 -1
- package/dist/instrument-with-sentry.d.ts +1 -1
- package/dist/instrument-with-sentry.js +27 -24
- package/dist/instrument-with-sentry.js.map +1 -1
- package/dist/module-sync/artifact.d.ts +60 -26
- package/dist/module-sync/cli.d.ts +1 -1
- package/dist/module-sync/cli.js +6624 -4527
- package/dist/module-sync/cli.js.map +1 -1
- package/dist/module-sync/cmd.d.ts +4 -4
- package/dist/module-sync/config.d.ts +30 -17
- package/dist/module-sync/edge.d.ts +73 -60
- package/dist/module-sync/errors.d.ts +26 -11
- package/dist/module-sync/fs.d.ts +61 -0
- package/dist/module-sync/index.d.ts +31 -20
- package/dist/module-sync/node.d.ts +118 -83
- package/dist/module-sync/override-set.d.ts +39 -33
- package/dist/module-sync/package-environment.d.ts +83 -52
- package/dist/module-sync/path-resolve.d.ts +14 -9
- package/dist/module-sync/sdk.d.ts +9 -5
- package/dist/module-sync/shadow-bin.d.ts +5 -2
- package/dist/module-sync/shadow-bin.js +82 -66
- package/dist/module-sync/shadow-bin.js.map +1 -1
- package/dist/module-sync/shadow-npm-inject.d.ts +1 -1
- package/dist/module-sync/shadow-npm-inject.js +1176 -983
- package/dist/module-sync/shadow-npm-inject.js.map +1 -1
- package/dist/module-sync/shadow-npm-paths.d.ts +28 -14
- package/dist/module-sync/shadow-npm-paths.js +285 -208
- package/dist/module-sync/shadow-npm-paths.js.map +1 -1
- package/dist/module-sync/socket-package-alert.d.ts +95 -39
- package/dist/module-sync/types.d.ts +75 -47
- package/dist/module-sync/vendor.js +11181 -0
- package/dist/{require → module-sync}/vendor.js.map +1 -1
- package/dist/require/cli.d.ts +1 -1
- package/dist/require/cli.js +6624 -4525
- package/dist/require/cli.js.map +1 -1
- package/dist/require/vendor.js +2 -9145
- package/package.json +46 -38
|
@@ -1,143 +1,173 @@
|
|
|
1
|
-
'use strict'
|
|
1
|
+
'use strict'
|
|
2
2
|
|
|
3
3
|
function _socketInterop(e) {
|
|
4
4
|
let c = 0
|
|
5
5
|
for (const k in e ?? {}) {
|
|
6
6
|
c = c === 0 && k === 'default' ? 1 : 0
|
|
7
|
-
if (!c && k !== '__esModule')
|
|
7
|
+
if (!c && k !== '__esModule') {
|
|
8
|
+
break
|
|
9
|
+
}
|
|
8
10
|
}
|
|
9
11
|
return c ? e.default : e
|
|
10
12
|
}
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
14
|
+
const shadowNpmPaths = require('./shadow-npm-paths.js')
|
|
15
|
+
const process$1 = require('node:process')
|
|
16
|
+
const commonTags = _socketInterop(require('common-tags'))
|
|
17
|
+
const logger = require('@socketsecurity/registry/lib/logger')
|
|
18
|
+
const constants = require('./constants.js')
|
|
19
|
+
const semver = _socketInterop(require('semver'))
|
|
20
|
+
const packageurlJs = require('@socketregistry/packageurl-js')
|
|
21
|
+
const registry = require('@socketsecurity/registry')
|
|
22
|
+
const arrays = require('@socketsecurity/registry/lib/arrays')
|
|
23
|
+
const debug = require('@socketsecurity/registry/lib/debug')
|
|
24
|
+
const objects = require('@socketsecurity/registry/lib/objects')
|
|
25
|
+
const npa = _socketInterop(require('npm-package-arg'))
|
|
26
|
+
const hpagent = _socketInterop(require('hpagent'))
|
|
27
|
+
const isInteractive = require('@socketregistry/is-interactive/index.cjs')
|
|
28
|
+
const registryConstants = require('@socketsecurity/registry/lib/constants')
|
|
29
|
+
const prompts = require('@socketsecurity/registry/lib/prompts')
|
|
30
|
+
const strings = require('@socketsecurity/registry/lib/strings')
|
|
31
|
+
const sdk = require('@socketsecurity/sdk')
|
|
32
|
+
const fs = require('node:fs')
|
|
33
|
+
const os = require('node:os')
|
|
34
|
+
const path = require('node:path')
|
|
35
|
+
const config = require('@socketsecurity/config')
|
|
36
|
+
const promises = require('node:timers/promises')
|
|
37
|
+
const colors = _socketInterop(require('yoctocolors-cjs'))
|
|
38
|
+
const packages = require('@socketsecurity/registry/lib/packages')
|
|
39
|
+
const sorts = require('@socketsecurity/registry/lib/sorts')
|
|
40
|
+
const terminalLink = _socketInterop(require('terminal-link'))
|
|
41
|
+
const indentString = require('@socketregistry/indent-string/index.cjs')
|
|
39
42
|
|
|
40
|
-
const {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
signal = abortSignal
|
|
46
|
-
}) {
|
|
47
|
-
let dir = path.resolve(cwd);
|
|
48
|
-
const {
|
|
49
|
-
root
|
|
50
|
-
} = path.parse(dir);
|
|
51
|
-
const names = [name].flat();
|
|
43
|
+
const { abortSignal } = constants
|
|
44
|
+
async function findUp(name, { cwd = process$1.cwd(), signal = abortSignal }) {
|
|
45
|
+
let dir = path.resolve(cwd)
|
|
46
|
+
const { root } = path.parse(dir)
|
|
47
|
+
const names = [name].flat()
|
|
52
48
|
while (dir && dir !== root) {
|
|
53
49
|
for (const name of names) {
|
|
54
50
|
if (signal?.aborted) {
|
|
55
|
-
return undefined
|
|
51
|
+
return undefined
|
|
56
52
|
}
|
|
57
|
-
const filePath = path.join(dir, name)
|
|
53
|
+
const filePath = path.join(dir, name)
|
|
58
54
|
try {
|
|
59
55
|
// eslint-disable-next-line no-await-in-loop
|
|
60
|
-
const stats = await fs.promises.stat(filePath)
|
|
56
|
+
const stats = await fs.promises.stat(filePath)
|
|
61
57
|
if (stats.isFile()) {
|
|
62
|
-
return filePath
|
|
58
|
+
return filePath
|
|
63
59
|
}
|
|
64
60
|
} catch {}
|
|
65
61
|
}
|
|
66
|
-
dir = path.dirname(dir)
|
|
62
|
+
dir = path.dirname(dir)
|
|
67
63
|
}
|
|
68
|
-
return undefined
|
|
64
|
+
return undefined
|
|
69
65
|
}
|
|
70
66
|
async function readFileBinary(filepath, options) {
|
|
71
67
|
return await fs.promises.readFile(filepath, {
|
|
72
68
|
signal: abortSignal,
|
|
73
69
|
...options,
|
|
74
70
|
encoding: 'binary'
|
|
75
|
-
})
|
|
71
|
+
})
|
|
76
72
|
}
|
|
77
73
|
async function readFileUtf8(filepath, options) {
|
|
78
74
|
return await fs.promises.readFile(filepath, {
|
|
79
75
|
signal: abortSignal,
|
|
80
76
|
...options,
|
|
81
77
|
encoding: 'utf8'
|
|
82
|
-
})
|
|
78
|
+
})
|
|
83
79
|
}
|
|
84
80
|
async function safeReadFile(filepath, options) {
|
|
85
81
|
try {
|
|
86
82
|
return await fs.promises.readFile(filepath, {
|
|
87
83
|
encoding: 'utf8',
|
|
88
84
|
signal: abortSignal,
|
|
89
|
-
...(typeof options === 'string'
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
85
|
+
...(typeof options === 'string'
|
|
86
|
+
? {
|
|
87
|
+
encoding: options
|
|
88
|
+
}
|
|
89
|
+
: options)
|
|
90
|
+
})
|
|
93
91
|
} catch {}
|
|
94
|
-
return undefined
|
|
92
|
+
return undefined
|
|
95
93
|
}
|
|
96
94
|
function safeReadFileSync(filepath, options) {
|
|
97
95
|
try {
|
|
98
96
|
return fs.readFileSync(filepath, {
|
|
99
97
|
encoding: 'utf8',
|
|
100
|
-
...(typeof options === 'string'
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
98
|
+
...(typeof options === 'string'
|
|
99
|
+
? {
|
|
100
|
+
encoding: options
|
|
101
|
+
}
|
|
102
|
+
: options)
|
|
103
|
+
})
|
|
104
104
|
} catch {}
|
|
105
|
-
return undefined
|
|
105
|
+
return undefined
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
-
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
108
|
+
const { LOCALAPPDATA, SOCKET_APP_DIR, XDG_DATA_HOME } = constants
|
|
109
|
+
const supportedConfigKeys = new Map([
|
|
110
|
+
['apiBaseUrl', 'Base URL of the API endpoint'],
|
|
111
|
+
['apiProxy', 'A proxy through which to access the API'],
|
|
112
|
+
['apiToken', 'The API token required to access most API endpoints'],
|
|
113
|
+
[
|
|
114
|
+
'defaultOrg',
|
|
115
|
+
'The default org slug to use when appropriate; usually the org your API token has access to. When set, all orgSlug arguments are implied to be this value.'
|
|
116
|
+
],
|
|
117
|
+
[
|
|
118
|
+
'enforcedOrgs',
|
|
119
|
+
'Orgs in this list have their security policies enforced on this machine'
|
|
120
|
+
]
|
|
121
|
+
])
|
|
122
|
+
const sensitiveConfigKeys = new Set(['apiToken'])
|
|
123
|
+
let _cachedConfig
|
|
124
|
+
// When using --config or SOCKET_CLI_CONFIG_OVERRIDE, do not persist the config.
|
|
125
|
+
let _readOnlyConfig = false
|
|
126
|
+
function overrideCachedConfig(config) {
|
|
127
|
+
_cachedConfig = {
|
|
128
|
+
...config
|
|
129
|
+
}
|
|
130
|
+
_readOnlyConfig = true
|
|
131
|
+
// Normalize apiKey to apiToken.
|
|
132
|
+
if (_cachedConfig['apiKey']) {
|
|
133
|
+
_cachedConfig['apiToken'] = _cachedConfig['apiKey']
|
|
134
|
+
delete _cachedConfig['apiKey']
|
|
135
|
+
}
|
|
136
|
+
}
|
|
120
137
|
function getConfigValues() {
|
|
121
|
-
if (
|
|
122
|
-
|
|
123
|
-
|
|
138
|
+
if (_cachedConfig === undefined) {
|
|
139
|
+
_cachedConfig = {}
|
|
140
|
+
// Order: env var > --config flag > file
|
|
141
|
+
const configPath = getConfigPath()
|
|
124
142
|
if (configPath) {
|
|
125
|
-
const raw = safeReadFileSync(configPath)
|
|
143
|
+
const raw = safeReadFileSync(configPath)
|
|
126
144
|
if (raw) {
|
|
127
145
|
try {
|
|
128
|
-
Object.assign(
|
|
146
|
+
Object.assign(
|
|
147
|
+
_cachedConfig,
|
|
148
|
+
JSON.parse(Buffer.from(raw, 'base64').toString())
|
|
149
|
+
)
|
|
129
150
|
} catch {
|
|
130
|
-
logger.logger.warn(`Failed to parse config at ${configPath}`)
|
|
151
|
+
logger.logger.warn(`Failed to parse config at ${configPath}`)
|
|
152
|
+
}
|
|
153
|
+
// Normalize apiKey to apiToken and persist it.
|
|
154
|
+
// This is a one time migration per user.
|
|
155
|
+
if (_cachedConfig['apiKey']) {
|
|
156
|
+
const token = _cachedConfig['apiKey']
|
|
157
|
+
delete _cachedConfig['apiKey']
|
|
158
|
+
updateConfigValue('apiToken', token)
|
|
131
159
|
}
|
|
132
160
|
} else {
|
|
133
161
|
fs.mkdirSync(path.dirname(configPath), {
|
|
134
162
|
recursive: true
|
|
135
|
-
})
|
|
163
|
+
})
|
|
136
164
|
}
|
|
137
165
|
}
|
|
138
166
|
}
|
|
139
|
-
return
|
|
167
|
+
return _cachedConfig
|
|
140
168
|
}
|
|
169
|
+
let _configPath
|
|
170
|
+
let _warnedConfigPathWin32Missing = false
|
|
141
171
|
function getConfigPath() {
|
|
142
172
|
// Get the OS app data folder:
|
|
143
173
|
// - Win: %LOCALAPPDATA% or fail?
|
|
@@ -151,219 +181,248 @@ function getConfigPath() {
|
|
|
151
181
|
// - Mac: %XDG_DATA_HOME%/socket/settings or "~/Library/Application Support/socket/settings"
|
|
152
182
|
// - Linux: %XDG_DATA_HOME%/socket/settings or "~/.local/share/socket/settings"
|
|
153
183
|
|
|
154
|
-
if (
|
|
184
|
+
if (_configPath === undefined) {
|
|
155
185
|
// Lazily access constants.WIN32.
|
|
156
|
-
const {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
186
|
+
const { WIN32 } = constants
|
|
187
|
+
let dataHome = WIN32
|
|
188
|
+
? // Lazily access constants.ENV[LOCALAPPDATA]
|
|
189
|
+
constants.ENV[LOCALAPPDATA]
|
|
190
|
+
: // Lazily access constants.ENV[XDG_DATA_HOME]
|
|
191
|
+
constants.ENV[XDG_DATA_HOME]
|
|
160
192
|
if (!dataHome) {
|
|
161
193
|
if (WIN32) {
|
|
162
|
-
if (!
|
|
163
|
-
|
|
164
|
-
logger.logger.warn(`Missing %${LOCALAPPDATA}%`)
|
|
194
|
+
if (!_warnedConfigPathWin32Missing) {
|
|
195
|
+
_warnedConfigPathWin32Missing = true
|
|
196
|
+
logger.logger.warn(`Missing %${LOCALAPPDATA}%`)
|
|
165
197
|
}
|
|
166
198
|
} else {
|
|
167
|
-
dataHome = path.join(
|
|
199
|
+
dataHome = path.join(
|
|
200
|
+
os.homedir(),
|
|
201
|
+
...(process$1.platform === 'darwin'
|
|
202
|
+
? ['Library', 'Application Support']
|
|
203
|
+
: ['.local', 'share'])
|
|
204
|
+
)
|
|
168
205
|
}
|
|
169
206
|
}
|
|
170
|
-
|
|
207
|
+
_configPath = dataHome ? path.join(dataHome, SOCKET_APP_DIR) : undefined
|
|
171
208
|
}
|
|
172
|
-
return
|
|
209
|
+
return _configPath
|
|
173
210
|
}
|
|
174
211
|
function normalizeConfigKey(key) {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
212
|
+
// Note: apiKey was the old name of the token. When we load a config with
|
|
213
|
+
// property apiKey, we'll copy that to apiToken and delete the old property.
|
|
214
|
+
const normalizedKey = key === 'apiKey' ? 'apiToken' : key
|
|
215
|
+
if (!supportedConfigKeys.has(normalizedKey)) {
|
|
216
|
+
throw new Error(`Invalid config key: ${normalizedKey}`)
|
|
178
217
|
}
|
|
179
|
-
return normalizedKey
|
|
218
|
+
return normalizedKey
|
|
180
219
|
}
|
|
181
|
-
function findSocketYmlSync() {
|
|
182
|
-
let prevDir = null
|
|
183
|
-
let dir = process$1.cwd();
|
|
220
|
+
function findSocketYmlSync(dir = process$1.cwd()) {
|
|
221
|
+
let prevDir = null
|
|
184
222
|
while (dir !== prevDir) {
|
|
185
|
-
let ymlPath = path.join(dir, 'socket.yml')
|
|
186
|
-
let yml = safeReadFileSync(ymlPath)
|
|
223
|
+
let ymlPath = path.join(dir, 'socket.yml')
|
|
224
|
+
let yml = safeReadFileSync(ymlPath)
|
|
187
225
|
if (yml === undefined) {
|
|
188
|
-
ymlPath = path.join(dir, 'socket.yaml')
|
|
189
|
-
yml = safeReadFileSync(ymlPath)
|
|
226
|
+
ymlPath = path.join(dir, 'socket.yaml')
|
|
227
|
+
yml = safeReadFileSync(ymlPath)
|
|
190
228
|
}
|
|
191
229
|
if (typeof yml === 'string') {
|
|
192
230
|
try {
|
|
193
231
|
return {
|
|
194
232
|
path: ymlPath,
|
|
195
233
|
parsed: config.parseSocketConfig(yml)
|
|
196
|
-
}
|
|
234
|
+
}
|
|
197
235
|
} catch {
|
|
198
|
-
throw new Error(`Found file but was unable to parse ${ymlPath}`)
|
|
236
|
+
throw new Error(`Found file but was unable to parse ${ymlPath}`)
|
|
199
237
|
}
|
|
200
238
|
}
|
|
201
|
-
prevDir = dir
|
|
202
|
-
dir = path.join(dir, '..')
|
|
239
|
+
prevDir = dir
|
|
240
|
+
dir = path.join(dir, '..')
|
|
203
241
|
}
|
|
204
|
-
return null
|
|
242
|
+
return null
|
|
205
243
|
}
|
|
206
244
|
function getConfigValue(key) {
|
|
207
|
-
|
|
245
|
+
const localConfig = getConfigValues()
|
|
246
|
+
return localConfig[normalizeConfigKey(key)]
|
|
208
247
|
}
|
|
248
|
+
let _pendingSave = false
|
|
209
249
|
function updateConfigValue(key, value) {
|
|
210
|
-
const localConfig = getConfigValues()
|
|
211
|
-
localConfig[normalizeConfigKey(key)] = value
|
|
212
|
-
if (
|
|
213
|
-
|
|
250
|
+
const localConfig = getConfigValues()
|
|
251
|
+
localConfig[normalizeConfigKey(key)] = value
|
|
252
|
+
if (_readOnlyConfig) {
|
|
253
|
+
logger.logger.warn(
|
|
254
|
+
'Not persisting config change; current config overridden through env var or flag'
|
|
255
|
+
)
|
|
256
|
+
} else if (!_pendingSave) {
|
|
257
|
+
_pendingSave = true
|
|
214
258
|
process$1.nextTick(() => {
|
|
215
|
-
|
|
216
|
-
const configPath = getConfigPath()
|
|
259
|
+
_pendingSave = false
|
|
260
|
+
const configPath = getConfigPath()
|
|
217
261
|
if (configPath) {
|
|
218
|
-
fs.writeFileSync(
|
|
262
|
+
fs.writeFileSync(
|
|
263
|
+
configPath,
|
|
264
|
+
Buffer.from(JSON.stringify(localConfig)).toString('base64')
|
|
265
|
+
)
|
|
219
266
|
}
|
|
220
|
-
})
|
|
267
|
+
})
|
|
221
268
|
}
|
|
222
269
|
}
|
|
223
270
|
|
|
224
271
|
const {
|
|
225
272
|
kInternalsSymbol: kInternalsSymbol$1,
|
|
226
|
-
[kInternalsSymbol$1]: {
|
|
227
|
-
|
|
228
|
-
}
|
|
229
|
-
} = constants;
|
|
273
|
+
[kInternalsSymbol$1]: { getSentry }
|
|
274
|
+
} = constants
|
|
230
275
|
class AuthError extends Error {}
|
|
231
276
|
class InputError extends Error {
|
|
232
277
|
constructor(message, body) {
|
|
233
|
-
super(message)
|
|
234
|
-
this.body = body
|
|
278
|
+
super(message)
|
|
279
|
+
this.body = body
|
|
235
280
|
}
|
|
236
281
|
}
|
|
237
282
|
async function captureException(exception, hint) {
|
|
238
|
-
const result = captureExceptionSync(exception, hint)
|
|
283
|
+
const result = captureExceptionSync(exception, hint)
|
|
239
284
|
// "Sleep" for a second, just in case, hopefully enough time to initiate fetch.
|
|
240
|
-
await promises.setTimeout(1000)
|
|
241
|
-
return result
|
|
285
|
+
await promises.setTimeout(1000)
|
|
286
|
+
return result
|
|
242
287
|
}
|
|
243
288
|
function captureExceptionSync(exception, hint) {
|
|
244
|
-
const Sentry = getSentry()
|
|
289
|
+
const Sentry = getSentry()
|
|
245
290
|
if (!Sentry) {
|
|
246
|
-
return ''
|
|
291
|
+
return ''
|
|
247
292
|
}
|
|
248
|
-
debug.debugLog('captureException: Sending exception to Sentry.')
|
|
249
|
-
return Sentry.captureException(exception, hint)
|
|
250
|
-
}
|
|
251
|
-
function isErrnoException(value) {
|
|
252
|
-
if (!(value instanceof Error)) {
|
|
253
|
-
return false;
|
|
254
|
-
}
|
|
255
|
-
return value.code !== undefined;
|
|
293
|
+
debug.debugLog('captureException: Sending exception to Sentry.')
|
|
294
|
+
return Sentry.captureException(exception, hint)
|
|
256
295
|
}
|
|
257
296
|
|
|
258
297
|
const {
|
|
259
298
|
SOCKET_CLI_NO_API_TOKEN,
|
|
299
|
+
SOCKET_SECURITY_API_BASE_URL,
|
|
300
|
+
SOCKET_SECURITY_API_PROXY,
|
|
260
301
|
SOCKET_SECURITY_API_TOKEN
|
|
261
|
-
} = constants
|
|
302
|
+
} = constants
|
|
262
303
|
|
|
263
304
|
// The API server that should be used for operations.
|
|
264
305
|
function getDefaultApiBaseUrl() {
|
|
265
|
-
const baseUrl =
|
|
266
|
-
|
|
306
|
+
const baseUrl =
|
|
307
|
+
// Lazily access constants.ENV[SOCKET_SECURITY_API_BASE_URL].
|
|
308
|
+
constants.ENV[SOCKET_SECURITY_API_BASE_URL] || getConfigValue('apiBaseUrl')
|
|
309
|
+
return strings.isNonEmptyString(baseUrl) ? baseUrl : undefined
|
|
267
310
|
}
|
|
268
311
|
|
|
269
312
|
// The API server that should be used for operations.
|
|
270
313
|
function getDefaultHttpProxy() {
|
|
271
|
-
const apiProxy =
|
|
272
|
-
|
|
314
|
+
const apiProxy =
|
|
315
|
+
// Lazily access constants.ENV[SOCKET_SECURITY_API_PROXY].
|
|
316
|
+
constants.ENV[SOCKET_SECURITY_API_PROXY] || getConfigValue('apiProxy')
|
|
317
|
+
return strings.isNonEmptyString(apiProxy) ? apiProxy : undefined
|
|
273
318
|
}
|
|
274
319
|
|
|
275
320
|
// This API key should be stored globally for the duration of the CLI execution.
|
|
276
|
-
let _defaultToken
|
|
321
|
+
let _defaultToken
|
|
277
322
|
function getDefaultToken() {
|
|
278
323
|
// Lazily access constants.ENV[SOCKET_CLI_NO_API_TOKEN].
|
|
279
324
|
if (constants.ENV[SOCKET_CLI_NO_API_TOKEN]) {
|
|
280
|
-
_defaultToken = undefined
|
|
325
|
+
_defaultToken = undefined
|
|
281
326
|
} else {
|
|
282
327
|
const key =
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
328
|
+
// Lazily access constants.ENV[SOCKET_SECURITY_API_TOKEN].
|
|
329
|
+
constants.ENV[SOCKET_SECURITY_API_TOKEN] ||
|
|
330
|
+
getConfigValue('apiToken') ||
|
|
331
|
+
_defaultToken
|
|
332
|
+
_defaultToken = strings.isNonEmptyString(key) ? key : undefined
|
|
286
333
|
}
|
|
287
|
-
return _defaultToken
|
|
334
|
+
return _defaultToken
|
|
288
335
|
}
|
|
289
336
|
function getPublicToken() {
|
|
290
337
|
return (
|
|
291
338
|
// Lazily access constants.ENV[SOCKET_SECURITY_API_TOKEN].
|
|
292
|
-
(constants.ENV[SOCKET_SECURITY_API_TOKEN] || getDefaultToken()) ??
|
|
293
|
-
|
|
339
|
+
(constants.ENV[SOCKET_SECURITY_API_TOKEN] || getDefaultToken()) ??
|
|
340
|
+
registryConstants.SOCKET_PUBLIC_API_TOKEN
|
|
341
|
+
)
|
|
294
342
|
}
|
|
295
|
-
async function setupSdk(
|
|
343
|
+
async function setupSdk(
|
|
344
|
+
apiToken = getDefaultToken(),
|
|
345
|
+
apiBaseUrl = getDefaultApiBaseUrl(),
|
|
346
|
+
proxy = getDefaultHttpProxy()
|
|
347
|
+
) {
|
|
296
348
|
if (typeof apiToken !== 'string' && isInteractive()) {
|
|
297
349
|
apiToken = await prompts.password({
|
|
298
|
-
message:
|
|
299
|
-
|
|
300
|
-
|
|
350
|
+
message:
|
|
351
|
+
'Enter your Socket.dev API key (not saved, use socket login to persist)'
|
|
352
|
+
})
|
|
353
|
+
_defaultToken = apiToken
|
|
301
354
|
}
|
|
302
355
|
if (!apiToken) {
|
|
303
|
-
throw new AuthError('You need to provide an API key')
|
|
356
|
+
throw new AuthError('You need to provide an API key')
|
|
304
357
|
}
|
|
305
358
|
return new sdk.SocketSdk(apiToken, {
|
|
306
|
-
agent: proxy
|
|
307
|
-
|
|
308
|
-
|
|
359
|
+
agent: proxy
|
|
360
|
+
? new hpagent.HttpsProxyAgent({
|
|
361
|
+
proxy
|
|
362
|
+
})
|
|
363
|
+
: undefined,
|
|
309
364
|
baseUrl: apiBaseUrl,
|
|
310
365
|
userAgent: sdk.createUserAgentFromPkgJson({
|
|
311
366
|
// The '@rollup/plugin-replace' will replace "process.env['INLINED_SOCKET_CLI_NAME']".
|
|
312
|
-
name:
|
|
367
|
+
name: '@socketsecurity/cli',
|
|
313
368
|
// The '@rollup/plugin-replace' will replace "process.env['INLINED_SOCKET_CLI_VERSION']".
|
|
314
|
-
version:
|
|
369
|
+
version: '0.14.68',
|
|
315
370
|
// The '@rollup/plugin-replace' will replace "process.env['INLINED_SOCKET_CLI_HOMEPAGE']".
|
|
316
|
-
homepage:
|
|
371
|
+
homepage: 'https://github.com/SocketDev/socket-cli'
|
|
317
372
|
})
|
|
318
|
-
})
|
|
373
|
+
})
|
|
319
374
|
}
|
|
320
375
|
|
|
321
|
-
|
|
322
|
-
DiffAction[
|
|
323
|
-
DiffAction[
|
|
324
|
-
DiffAction[
|
|
325
|
-
return DiffAction
|
|
326
|
-
}({})
|
|
376
|
+
const DiffAction = /*#__PURE__*/ (function (DiffAction) {
|
|
377
|
+
DiffAction['add'] = 'ADD'
|
|
378
|
+
DiffAction['change'] = 'CHANGE'
|
|
379
|
+
DiffAction['remove'] = 'REMOVE'
|
|
380
|
+
return DiffAction
|
|
381
|
+
})({})
|
|
327
382
|
|
|
328
|
-
const depValid = require(shadowNpmPaths.getArboristDepValidPath())
|
|
383
|
+
const depValid = require(shadowNpmPaths.getArboristDepValidPath())
|
|
329
384
|
|
|
330
|
-
const {
|
|
331
|
-
UNDEFINED_TOKEN
|
|
332
|
-
} = constants;
|
|
385
|
+
const { UNDEFINED_TOKEN } = constants
|
|
333
386
|
function tryRequire(req, ...ids) {
|
|
334
387
|
for (const data of ids) {
|
|
335
|
-
let id
|
|
336
|
-
let transformer
|
|
388
|
+
let id
|
|
389
|
+
let transformer
|
|
337
390
|
if (Array.isArray(data)) {
|
|
338
|
-
id = data[0]
|
|
339
|
-
transformer = data[1]
|
|
391
|
+
id = data[0]
|
|
392
|
+
transformer = data[1]
|
|
340
393
|
} else {
|
|
341
|
-
id = data
|
|
342
|
-
transformer = mod => mod
|
|
394
|
+
id = data
|
|
395
|
+
transformer = mod => mod
|
|
343
396
|
}
|
|
344
397
|
try {
|
|
345
398
|
// Check that the transformed value isn't `undefined` because older
|
|
346
399
|
// versions of packages like 'proc-log' may not export a `log` method.
|
|
347
|
-
const exported = transformer(req(id))
|
|
400
|
+
const exported = transformer(req(id))
|
|
348
401
|
if (exported !== undefined) {
|
|
349
|
-
return exported
|
|
402
|
+
return exported
|
|
350
403
|
}
|
|
351
404
|
} catch {}
|
|
352
405
|
}
|
|
353
|
-
return undefined
|
|
406
|
+
return undefined
|
|
354
407
|
}
|
|
355
|
-
let _log = UNDEFINED_TOKEN
|
|
408
|
+
let _log = UNDEFINED_TOKEN
|
|
356
409
|
function getLogger() {
|
|
357
410
|
if (_log === UNDEFINED_TOKEN) {
|
|
358
|
-
_log = tryRequire(
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
411
|
+
_log = tryRequire(
|
|
412
|
+
shadowNpmPaths.getNpmRequire(),
|
|
413
|
+
[
|
|
414
|
+
'proc-log/lib/index.js',
|
|
415
|
+
// The proc-log DefinitelyTyped definition is incorrect. The type definition
|
|
416
|
+
// is really that of its export log.
|
|
417
|
+
mod => mod.log
|
|
418
|
+
],
|
|
419
|
+
'npmlog/lib/log.js'
|
|
420
|
+
)
|
|
421
|
+
}
|
|
422
|
+
return _log
|
|
364
423
|
}
|
|
365
424
|
|
|
366
|
-
const OverrideSet = require(shadowNpmPaths.getArboristOverrideSetClassPath())
|
|
425
|
+
const OverrideSet = require(shadowNpmPaths.getArboristOverrideSetClassPath())
|
|
367
426
|
|
|
368
427
|
// Implementation code not related to patch https://github.com/npm/cli/pull/8089
|
|
369
428
|
// is based on https://github.com/npm/cli/blob/v11.0.0/workspaces/arborist/lib/override-set.js:
|
|
@@ -374,59 +433,64 @@ class SafeOverrideSet extends OverrideSet {
|
|
|
374
433
|
// If override sets contain one another then we can try to use the more
|
|
375
434
|
// specific one. If neither one is more specific, then we consider them to
|
|
376
435
|
// be in conflict.
|
|
377
|
-
return this.findSpecificOverrideSet(first, second) === undefined
|
|
436
|
+
return this.findSpecificOverrideSet(first, second) === undefined
|
|
378
437
|
}
|
|
379
438
|
|
|
380
439
|
// Patch adding findSpecificOverrideSet is based on
|
|
381
440
|
// https://github.com/npm/cli/pull/8089.
|
|
382
441
|
static findSpecificOverrideSet(first, second) {
|
|
383
|
-
for (
|
|
442
|
+
for (
|
|
443
|
+
let overrideSet = second;
|
|
444
|
+
overrideSet;
|
|
445
|
+
overrideSet = overrideSet.parent
|
|
446
|
+
) {
|
|
384
447
|
if (overrideSet.isEqual(first)) {
|
|
385
|
-
return second
|
|
448
|
+
return second
|
|
386
449
|
}
|
|
387
450
|
}
|
|
388
|
-
for (
|
|
451
|
+
for (
|
|
452
|
+
let overrideSet = first;
|
|
453
|
+
overrideSet;
|
|
454
|
+
overrideSet = overrideSet.parent
|
|
455
|
+
) {
|
|
389
456
|
if (overrideSet.isEqual(second)) {
|
|
390
|
-
return first
|
|
457
|
+
return first
|
|
391
458
|
}
|
|
392
459
|
}
|
|
393
460
|
// The override sets are incomparable. Neither one contains the other.
|
|
394
|
-
const log = getLogger()
|
|
395
|
-
log?.silly('Conflicting override sets', first, second)
|
|
396
|
-
return undefined
|
|
461
|
+
const log = getLogger()
|
|
462
|
+
log?.silly('Conflicting override sets', first, second)
|
|
463
|
+
return undefined
|
|
397
464
|
}
|
|
398
465
|
|
|
399
466
|
// Patch adding childrenAreEqual is based on
|
|
400
467
|
// https://github.com/npm/cli/pull/8089.
|
|
401
468
|
childrenAreEqual(otherOverrideSet) {
|
|
402
469
|
if (this.children.size !== otherOverrideSet.children.size) {
|
|
403
|
-
return false
|
|
470
|
+
return false
|
|
404
471
|
}
|
|
405
|
-
for (const {
|
|
406
|
-
|
|
407
|
-
1: childOverrideSet
|
|
408
|
-
} of this.children) {
|
|
409
|
-
const otherChildOverrideSet = otherOverrideSet.children.get(key);
|
|
472
|
+
for (const { 0: key, 1: childOverrideSet } of this.children) {
|
|
473
|
+
const otherChildOverrideSet = otherOverrideSet.children.get(key)
|
|
410
474
|
if (!otherChildOverrideSet) {
|
|
411
|
-
return false
|
|
475
|
+
return false
|
|
412
476
|
}
|
|
413
477
|
if (childOverrideSet.value !== otherChildOverrideSet.value) {
|
|
414
|
-
return false
|
|
478
|
+
return false
|
|
415
479
|
}
|
|
416
480
|
if (!childOverrideSet.childrenAreEqual(otherChildOverrideSet)) {
|
|
417
|
-
return false
|
|
481
|
+
return false
|
|
418
482
|
}
|
|
419
483
|
}
|
|
420
|
-
return true
|
|
484
|
+
return true
|
|
421
485
|
}
|
|
422
486
|
getEdgeRule(edge) {
|
|
423
487
|
for (const rule of this.ruleset.values()) {
|
|
424
488
|
if (rule.name !== edge.name) {
|
|
425
|
-
continue
|
|
489
|
+
continue
|
|
426
490
|
}
|
|
427
491
|
// If keySpec is * we found our override.
|
|
428
492
|
if (rule.keySpec === '*') {
|
|
429
|
-
return rule
|
|
493
|
+
return rule
|
|
430
494
|
}
|
|
431
495
|
// Patch replacing
|
|
432
496
|
// let spec = npa(`${edge.name}@${edge.spec}`)
|
|
@@ -435,53 +499,56 @@ class SafeOverrideSet extends OverrideSet {
|
|
|
435
499
|
// We need to use the rawSpec here, because the spec has the overrides
|
|
436
500
|
// applied to it already. The rawSpec can be undefined, so we need to use
|
|
437
501
|
// the fallback value of spec if it is.
|
|
438
|
-
let spec = npa(`${edge.name}@${edge.rawSpec || edge.spec}`)
|
|
502
|
+
let spec = npa(`${edge.name}@${edge.rawSpec || edge.spec}`)
|
|
439
503
|
if (spec.type === 'alias') {
|
|
440
|
-
spec = spec.subSpec
|
|
504
|
+
spec = spec.subSpec
|
|
441
505
|
}
|
|
442
506
|
if (spec.type === 'git') {
|
|
443
507
|
if (spec.gitRange && semver.intersects(spec.gitRange, rule.keySpec)) {
|
|
444
|
-
return rule
|
|
508
|
+
return rule
|
|
445
509
|
}
|
|
446
|
-
continue
|
|
510
|
+
continue
|
|
447
511
|
}
|
|
448
512
|
if (spec.type === 'range' || spec.type === 'version') {
|
|
449
513
|
if (semver.intersects(spec.fetchSpec, rule.keySpec)) {
|
|
450
|
-
return rule
|
|
514
|
+
return rule
|
|
451
515
|
}
|
|
452
|
-
continue
|
|
516
|
+
continue
|
|
453
517
|
}
|
|
454
518
|
// If we got this far, the spec type is one of tag, directory or file
|
|
455
519
|
// which means we have no real way to make version comparisons, so we
|
|
456
520
|
// just accept the override.
|
|
457
|
-
return rule
|
|
521
|
+
return rule
|
|
458
522
|
}
|
|
459
|
-
return this
|
|
523
|
+
return this
|
|
460
524
|
}
|
|
461
525
|
|
|
462
526
|
// Patch adding isEqual is based on
|
|
463
527
|
// https://github.com/npm/cli/pull/8089.
|
|
464
528
|
isEqual(otherOverrideSet) {
|
|
465
529
|
if (this === otherOverrideSet) {
|
|
466
|
-
return true
|
|
530
|
+
return true
|
|
467
531
|
}
|
|
468
532
|
if (!otherOverrideSet) {
|
|
469
|
-
return false
|
|
533
|
+
return false
|
|
470
534
|
}
|
|
471
|
-
if (
|
|
472
|
-
|
|
535
|
+
if (
|
|
536
|
+
this.key !== otherOverrideSet.key ||
|
|
537
|
+
this.value !== otherOverrideSet.value
|
|
538
|
+
) {
|
|
539
|
+
return false
|
|
473
540
|
}
|
|
474
541
|
if (!this.childrenAreEqual(otherOverrideSet)) {
|
|
475
|
-
return false
|
|
542
|
+
return false
|
|
476
543
|
}
|
|
477
544
|
if (!this.parent) {
|
|
478
|
-
return !otherOverrideSet.parent
|
|
545
|
+
return !otherOverrideSet.parent
|
|
479
546
|
}
|
|
480
|
-
return this.parent.isEqual(otherOverrideSet.parent)
|
|
547
|
+
return this.parent.isEqual(otherOverrideSet.parent)
|
|
481
548
|
}
|
|
482
549
|
}
|
|
483
550
|
|
|
484
|
-
const Node = require(shadowNpmPaths.getArboristNodeClassPath())
|
|
551
|
+
const Node = require(shadowNpmPaths.getArboristNodeClassPath())
|
|
485
552
|
|
|
486
553
|
// Implementation code not related to patch https://github.com/npm/cli/pull/8089
|
|
487
554
|
// is based on https://github.com/npm/cli/blob/v11.0.0/workspaces/arborist/lib/node.js:
|
|
@@ -492,28 +559,28 @@ class SafeNode extends Node {
|
|
|
492
559
|
canDedupe(preferDedupe = false) {
|
|
493
560
|
// Not allowed to mess with shrinkwraps or bundles.
|
|
494
561
|
if (this.inDepBundle || this.inShrinkwrap) {
|
|
495
|
-
return false
|
|
562
|
+
return false
|
|
496
563
|
}
|
|
497
564
|
// It's a top level pkg, or a dep of one.
|
|
498
565
|
if (!this.resolveParent?.resolveParent) {
|
|
499
|
-
return false
|
|
566
|
+
return false
|
|
500
567
|
}
|
|
501
568
|
// No one wants it, remove it.
|
|
502
569
|
if (this.edgesIn.size === 0) {
|
|
503
|
-
return true
|
|
570
|
+
return true
|
|
504
571
|
}
|
|
505
|
-
const other = this.resolveParent.resolveParent.resolve(this.name)
|
|
572
|
+
const other = this.resolveParent.resolveParent.resolve(this.name)
|
|
506
573
|
// Nothing else, need this one.
|
|
507
574
|
if (!other) {
|
|
508
|
-
return false
|
|
575
|
+
return false
|
|
509
576
|
}
|
|
510
577
|
// If it's the same thing, then always fine to remove.
|
|
511
578
|
if (other.matches(this)) {
|
|
512
|
-
return true
|
|
579
|
+
return true
|
|
513
580
|
}
|
|
514
581
|
// If the other thing can't replace this, then skip it.
|
|
515
582
|
if (!other.canReplace(this)) {
|
|
516
|
-
return false
|
|
583
|
+
return false
|
|
517
584
|
}
|
|
518
585
|
// Patch replacing
|
|
519
586
|
// if (preferDedupe || semver.gte(other.version, this.version)) {
|
|
@@ -523,14 +590,14 @@ class SafeNode extends Node {
|
|
|
523
590
|
//
|
|
524
591
|
// If we prefer dedupe, or if the version is equal, take the other.
|
|
525
592
|
if (preferDedupe || semver.eq(other.version, this.version)) {
|
|
526
|
-
return true
|
|
593
|
+
return true
|
|
527
594
|
}
|
|
528
595
|
// If our current version isn't the result of an override, then prefer to
|
|
529
596
|
// take the greater version.
|
|
530
597
|
if (!this.overridden && semver.gt(other.version, this.version)) {
|
|
531
|
-
return true
|
|
598
|
+
return true
|
|
532
599
|
}
|
|
533
|
-
return false
|
|
600
|
+
return false
|
|
534
601
|
}
|
|
535
602
|
|
|
536
603
|
// Is it safe to replace one node with another? check the edges to
|
|
@@ -544,7 +611,7 @@ class SafeNode extends Node {
|
|
|
544
611
|
// it with more tree construction, because it's a user request.
|
|
545
612
|
canReplaceWith(node, ignorePeers) {
|
|
546
613
|
if (this.name !== node.name || this.packageName !== node.packageName) {
|
|
547
|
-
return false
|
|
614
|
+
return false
|
|
548
615
|
}
|
|
549
616
|
// Patch replacing
|
|
550
617
|
// if (node.overrides !== this.overrides) {
|
|
@@ -558,11 +625,11 @@ class SafeNode extends Node {
|
|
|
558
625
|
// XXX need to check for two root nodes?
|
|
559
626
|
if (node.overrides) {
|
|
560
627
|
if (!node.overrides.isEqual(this.overrides)) {
|
|
561
|
-
return false
|
|
628
|
+
return false
|
|
562
629
|
}
|
|
563
630
|
} else {
|
|
564
631
|
if (this.overrides) {
|
|
565
|
-
return false
|
|
632
|
+
return false
|
|
566
633
|
}
|
|
567
634
|
}
|
|
568
635
|
}
|
|
@@ -570,29 +637,27 @@ class SafeNode extends Node {
|
|
|
570
637
|
// so that the condition we want to replace,
|
|
571
638
|
// if (this.overrides !== node.overrides) {
|
|
572
639
|
// , is not hit.`
|
|
573
|
-
const oldOverrideSet = this.overrides
|
|
574
|
-
let result = true
|
|
640
|
+
const oldOverrideSet = this.overrides
|
|
641
|
+
let result = true
|
|
575
642
|
if (oldOverrideSet !== node.overrides) {
|
|
576
|
-
this.overrides = node.overrides
|
|
643
|
+
this.overrides = node.overrides
|
|
577
644
|
}
|
|
578
645
|
try {
|
|
579
|
-
result = super.canReplaceWith(node, ignorePeers)
|
|
580
|
-
this.overrides = oldOverrideSet
|
|
646
|
+
result = super.canReplaceWith(node, ignorePeers)
|
|
647
|
+
this.overrides = oldOverrideSet
|
|
581
648
|
} catch (e) {
|
|
582
|
-
this.overrides = oldOverrideSet
|
|
583
|
-
throw e
|
|
649
|
+
this.overrides = oldOverrideSet
|
|
650
|
+
throw e
|
|
584
651
|
}
|
|
585
|
-
return result
|
|
652
|
+
return result
|
|
586
653
|
}
|
|
587
654
|
|
|
588
655
|
// Patch adding deleteEdgeIn is based on https://github.com/npm/cli/pull/8089.
|
|
589
656
|
deleteEdgeIn(edge) {
|
|
590
|
-
this.edgesIn.delete(edge)
|
|
591
|
-
const {
|
|
592
|
-
overrides
|
|
593
|
-
} = edge;
|
|
657
|
+
this.edgesIn.delete(edge)
|
|
658
|
+
const { overrides } = edge
|
|
594
659
|
if (overrides) {
|
|
595
|
-
this.updateOverridesEdgeInRemoved(overrides)
|
|
660
|
+
this.updateOverridesEdgeInRemoved(overrides)
|
|
596
661
|
}
|
|
597
662
|
}
|
|
598
663
|
addEdgeIn(edge) {
|
|
@@ -605,11 +670,11 @@ class SafeNode extends Node {
|
|
|
605
670
|
// We need to handle the case where the new edge in has an overrides field
|
|
606
671
|
// which is different from the current value.
|
|
607
672
|
if (!this.overrides || !this.overrides.isEqual(edge.overrides)) {
|
|
608
|
-
this.updateOverridesEdgeInAdded(edge.overrides)
|
|
673
|
+
this.updateOverridesEdgeInAdded(edge.overrides)
|
|
609
674
|
}
|
|
610
|
-
this.edgesIn.add(edge)
|
|
675
|
+
this.edgesIn.add(edge)
|
|
611
676
|
// Try to get metadata from the yarn.lock file.
|
|
612
|
-
this.root.meta?.addEdge(edge)
|
|
677
|
+
this.root.meta?.addEdge(edge)
|
|
613
678
|
}
|
|
614
679
|
|
|
615
680
|
// @ts-ignore: Incorrectly typed as a property instead of an accessor.
|
|
@@ -617,8 +682,12 @@ class SafeNode extends Node {
|
|
|
617
682
|
// Patch replacing
|
|
618
683
|
// return !!(this.overrides && this.overrides.value && this.overrides.name === this.name)
|
|
619
684
|
// is based on https://github.com/npm/cli/pull/8089.
|
|
620
|
-
if (
|
|
621
|
-
|
|
685
|
+
if (
|
|
686
|
+
!this.overrides ||
|
|
687
|
+
!this.overrides.value ||
|
|
688
|
+
this.overrides.name !== this.name
|
|
689
|
+
) {
|
|
690
|
+
return false
|
|
622
691
|
}
|
|
623
692
|
// The overrides rule is for a package with this name, but some override
|
|
624
693
|
// rules only apply to specific versions. To make sure this package was
|
|
@@ -626,13 +695,17 @@ class SafeNode extends Node {
|
|
|
626
695
|
// applied to it, in which case its overrides set is different than its
|
|
627
696
|
// source node.
|
|
628
697
|
for (const edge of this.edgesIn) {
|
|
629
|
-
if (
|
|
698
|
+
if (
|
|
699
|
+
edge.overrides &&
|
|
700
|
+
edge.overrides.name === this.name &&
|
|
701
|
+
edge.overrides.value === this.version
|
|
702
|
+
) {
|
|
630
703
|
if (!edge.overrides.isEqual(edge.from?.overrides)) {
|
|
631
|
-
return true
|
|
704
|
+
return true
|
|
632
705
|
}
|
|
633
706
|
}
|
|
634
707
|
}
|
|
635
|
-
return false
|
|
708
|
+
return false
|
|
636
709
|
}
|
|
637
710
|
set parent(newParent) {
|
|
638
711
|
// Patch removing
|
|
@@ -644,18 +717,16 @@ class SafeNode extends Node {
|
|
|
644
717
|
// The "parent" setter is a really large and complex function. To satisfy
|
|
645
718
|
// the patch we hold on to the old overrides value and set `this.overrides`
|
|
646
719
|
// to `undefined` so that the condition we want to remove is not hit.
|
|
647
|
-
const {
|
|
648
|
-
overrides
|
|
649
|
-
} = this;
|
|
720
|
+
const { overrides } = this
|
|
650
721
|
if (overrides) {
|
|
651
|
-
this.overrides = undefined
|
|
722
|
+
this.overrides = undefined
|
|
652
723
|
}
|
|
653
724
|
try {
|
|
654
|
-
super.parent = newParent
|
|
655
|
-
this.overrides = overrides
|
|
725
|
+
super.parent = newParent
|
|
726
|
+
this.overrides = overrides
|
|
656
727
|
} catch (e) {
|
|
657
|
-
this.overrides = overrides
|
|
658
|
-
throw e
|
|
728
|
+
this.overrides = overrides
|
|
729
|
+
throw e
|
|
659
730
|
}
|
|
660
731
|
}
|
|
661
732
|
|
|
@@ -664,9 +735,9 @@ class SafeNode extends Node {
|
|
|
664
735
|
recalculateOutEdgesOverrides() {
|
|
665
736
|
// For each edge out propagate the new overrides through.
|
|
666
737
|
for (const edge of this.edgesOut.values()) {
|
|
667
|
-
edge.reload(true)
|
|
738
|
+
edge.reload(true)
|
|
668
739
|
if (edge.to) {
|
|
669
|
-
edge.to.updateOverridesEdgeInAdded(edge.overrides)
|
|
740
|
+
edge.to.updateOverridesEdgeInAdded(edge.overrides)
|
|
670
741
|
}
|
|
671
742
|
}
|
|
672
743
|
}
|
|
@@ -685,14 +756,14 @@ class SafeNode extends Node {
|
|
|
685
756
|
if (!this.overrides) {
|
|
686
757
|
this.overrides = new SafeOverrideSet({
|
|
687
758
|
overrides: ''
|
|
688
|
-
})
|
|
759
|
+
})
|
|
689
760
|
}
|
|
690
761
|
try {
|
|
691
|
-
super.root = newRoot
|
|
692
|
-
this.overrides = undefined
|
|
762
|
+
super.root = newRoot
|
|
763
|
+
this.overrides = undefined
|
|
693
764
|
} catch (e) {
|
|
694
|
-
this.overrides = undefined
|
|
695
|
-
throw e
|
|
765
|
+
this.overrides = undefined
|
|
766
|
+
throw e
|
|
696
767
|
}
|
|
697
768
|
}
|
|
698
769
|
|
|
@@ -716,30 +787,33 @@ class SafeNode extends Node {
|
|
|
716
787
|
// undefined for any node at the end state of the tree. So if the new edge's
|
|
717
788
|
// overrides is undefined it will be updated later. So we can wait with
|
|
718
789
|
// updating the node's overrides field.
|
|
719
|
-
return false
|
|
790
|
+
return false
|
|
720
791
|
}
|
|
721
792
|
if (!this.overrides) {
|
|
722
|
-
this.overrides = otherOverrideSet
|
|
723
|
-
this.recalculateOutEdgesOverrides()
|
|
724
|
-
return true
|
|
793
|
+
this.overrides = otherOverrideSet
|
|
794
|
+
this.recalculateOutEdgesOverrides()
|
|
795
|
+
return true
|
|
725
796
|
}
|
|
726
797
|
if (this.overrides.isEqual(otherOverrideSet)) {
|
|
727
|
-
return false
|
|
798
|
+
return false
|
|
728
799
|
}
|
|
729
|
-
const newOverrideSet = SafeOverrideSet.findSpecificOverrideSet(
|
|
800
|
+
const newOverrideSet = SafeOverrideSet.findSpecificOverrideSet(
|
|
801
|
+
this.overrides,
|
|
802
|
+
otherOverrideSet
|
|
803
|
+
)
|
|
730
804
|
if (newOverrideSet) {
|
|
731
805
|
if (this.overrides.isEqual(newOverrideSet)) {
|
|
732
|
-
return false
|
|
806
|
+
return false
|
|
733
807
|
}
|
|
734
|
-
this.overrides = newOverrideSet
|
|
735
|
-
this.recalculateOutEdgesOverrides()
|
|
736
|
-
return true
|
|
808
|
+
this.overrides = newOverrideSet
|
|
809
|
+
this.recalculateOutEdgesOverrides()
|
|
810
|
+
return true
|
|
737
811
|
}
|
|
738
812
|
// This is an error condition. We can only get here if the new override set
|
|
739
813
|
// is in conflict with the existing.
|
|
740
|
-
const log = getLogger()
|
|
741
|
-
log?.silly('Conflicting override sets', this.name)
|
|
742
|
-
return false
|
|
814
|
+
const log = getLogger()
|
|
815
|
+
log?.silly('Conflicting override sets', this.name)
|
|
816
|
+
return false
|
|
743
817
|
}
|
|
744
818
|
|
|
745
819
|
// Patch adding updateOverridesEdgeInRemoved is based on
|
|
@@ -748,36 +822,37 @@ class SafeNode extends Node {
|
|
|
748
822
|
// If this edge's overrides isn't equal to this node's overrides,
|
|
749
823
|
// then removing it won't change newOverrideSet later.
|
|
750
824
|
if (!this.overrides || !this.overrides.isEqual(otherOverrideSet)) {
|
|
751
|
-
return false
|
|
825
|
+
return false
|
|
752
826
|
}
|
|
753
|
-
let newOverrideSet
|
|
827
|
+
let newOverrideSet
|
|
754
828
|
for (const edge of this.edgesIn) {
|
|
755
|
-
const {
|
|
756
|
-
overrides: edgeOverrides
|
|
757
|
-
} = edge;
|
|
829
|
+
const { overrides: edgeOverrides } = edge
|
|
758
830
|
if (newOverrideSet && edgeOverrides) {
|
|
759
|
-
newOverrideSet = SafeOverrideSet.findSpecificOverrideSet(
|
|
831
|
+
newOverrideSet = SafeOverrideSet.findSpecificOverrideSet(
|
|
832
|
+
edgeOverrides,
|
|
833
|
+
newOverrideSet
|
|
834
|
+
)
|
|
760
835
|
} else {
|
|
761
|
-
newOverrideSet = edgeOverrides
|
|
836
|
+
newOverrideSet = edgeOverrides
|
|
762
837
|
}
|
|
763
838
|
}
|
|
764
839
|
if (this.overrides.isEqual(newOverrideSet)) {
|
|
765
|
-
return false
|
|
840
|
+
return false
|
|
766
841
|
}
|
|
767
|
-
this.overrides = newOverrideSet
|
|
842
|
+
this.overrides = newOverrideSet
|
|
768
843
|
if (newOverrideSet) {
|
|
769
844
|
// Optimization: If there's any override set at all, then no non-extraneous
|
|
770
845
|
// node has an empty override set. So if we temporarily have no override set
|
|
771
846
|
// (for example, we removed all the edges in), there's no use updating all
|
|
772
847
|
// the edges out right now. Let's just wait until we have an actual override
|
|
773
848
|
// set later.
|
|
774
|
-
this.recalculateOutEdgesOverrides()
|
|
849
|
+
this.recalculateOutEdgesOverrides()
|
|
775
850
|
}
|
|
776
|
-
return true
|
|
851
|
+
return true
|
|
777
852
|
}
|
|
778
853
|
}
|
|
779
854
|
|
|
780
|
-
const Edge = require(shadowNpmPaths.getArboristEdgeClassPath())
|
|
855
|
+
const Edge = require(shadowNpmPaths.getArboristEdgeClassPath())
|
|
781
856
|
|
|
782
857
|
// The Edge class makes heavy use of private properties which subclasses do NOT
|
|
783
858
|
// have access to. So we have to recreate any functionality that relies on those
|
|
@@ -792,115 +867,129 @@ const Edge = require(shadowNpmPaths.getArboristEdgeClassPath());
|
|
|
792
867
|
// An edge in the dependency graph.
|
|
793
868
|
// Represents a dependency relationship of some kind.
|
|
794
869
|
class SafeEdge extends Edge {
|
|
795
|
-
#safeError
|
|
796
|
-
#safeExplanation
|
|
797
|
-
#safeFrom
|
|
798
|
-
#safeTo
|
|
870
|
+
#safeError
|
|
871
|
+
#safeExplanation
|
|
872
|
+
#safeFrom
|
|
873
|
+
#safeTo
|
|
799
874
|
constructor(options) {
|
|
800
|
-
const {
|
|
801
|
-
from
|
|
802
|
-
} = options;
|
|
875
|
+
const { from } = options
|
|
803
876
|
// Defer to supper to validate options and assign non-private values.
|
|
804
|
-
super(options)
|
|
877
|
+
super(options)
|
|
805
878
|
if (from.constructor !== SafeNode) {
|
|
806
|
-
Reflect.setPrototypeOf(from, SafeNode.prototype)
|
|
879
|
+
Reflect.setPrototypeOf(from, SafeNode.prototype)
|
|
807
880
|
}
|
|
808
|
-
this.#safeError = null
|
|
809
|
-
this.#safeExplanation = null
|
|
810
|
-
this.#safeFrom = from
|
|
811
|
-
this.#safeTo = null
|
|
812
|
-
this.reload(true)
|
|
881
|
+
this.#safeError = null
|
|
882
|
+
this.#safeExplanation = null
|
|
883
|
+
this.#safeFrom = from
|
|
884
|
+
this.#safeTo = null
|
|
885
|
+
this.reload(true)
|
|
813
886
|
}
|
|
814
887
|
get bundled() {
|
|
815
|
-
return !!this.#safeFrom?.package?.bundleDependencies?.includes(this.name)
|
|
888
|
+
return !!this.#safeFrom?.package?.bundleDependencies?.includes(this.name)
|
|
816
889
|
}
|
|
817
890
|
get error() {
|
|
818
891
|
if (!this.#safeError) {
|
|
819
892
|
if (!this.#safeTo) {
|
|
820
893
|
if (this.optional) {
|
|
821
|
-
this.#safeError = null
|
|
894
|
+
this.#safeError = null
|
|
822
895
|
} else {
|
|
823
|
-
this.#safeError = 'MISSING'
|
|
896
|
+
this.#safeError = 'MISSING'
|
|
824
897
|
}
|
|
825
|
-
} else if (
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
898
|
+
} else if (
|
|
899
|
+
this.peer &&
|
|
900
|
+
this.#safeFrom === this.#safeTo.parent &&
|
|
901
|
+
// Patch adding "?." use based on
|
|
902
|
+
// https://github.com/npm/cli/pull/8089.
|
|
903
|
+
!this.#safeFrom?.isTop
|
|
904
|
+
) {
|
|
905
|
+
this.#safeError = 'PEER LOCAL'
|
|
830
906
|
} else if (!this.satisfiedBy(this.#safeTo)) {
|
|
831
|
-
this.#safeError = 'INVALID'
|
|
907
|
+
this.#safeError = 'INVALID'
|
|
832
908
|
}
|
|
833
909
|
// Patch adding "else if" condition is based on
|
|
834
910
|
// https://github.com/npm/cli/pull/8089.
|
|
835
|
-
else if (
|
|
911
|
+
else if (
|
|
912
|
+
this.overrides &&
|
|
913
|
+
this.#safeTo.edgesOut.size &&
|
|
914
|
+
SafeOverrideSet.doOverrideSetsConflict(
|
|
915
|
+
this.overrides,
|
|
916
|
+
this.#safeTo.overrides
|
|
917
|
+
)
|
|
918
|
+
) {
|
|
836
919
|
// Any inconsistency between the edge's override set and the target's
|
|
837
920
|
// override set is potentially problematic. But we only say the edge is
|
|
838
921
|
// in error if the override sets are plainly conflicting. Note that if
|
|
839
922
|
// the target doesn't have any dependencies of their own, then this
|
|
840
923
|
// inconsistency is irrelevant.
|
|
841
|
-
this.#safeError = 'INVALID'
|
|
924
|
+
this.#safeError = 'INVALID'
|
|
842
925
|
} else {
|
|
843
|
-
this.#safeError = 'OK'
|
|
926
|
+
this.#safeError = 'OK'
|
|
844
927
|
}
|
|
845
928
|
}
|
|
846
929
|
if (this.#safeError === 'OK') {
|
|
847
|
-
return null
|
|
930
|
+
return null
|
|
848
931
|
}
|
|
849
|
-
return this.#safeError
|
|
932
|
+
return this.#safeError
|
|
850
933
|
}
|
|
851
934
|
|
|
852
935
|
// @ts-ignore: Incorrectly typed as a property instead of an accessor.
|
|
853
936
|
get from() {
|
|
854
|
-
return this.#safeFrom
|
|
937
|
+
return this.#safeFrom
|
|
855
938
|
}
|
|
856
939
|
|
|
857
940
|
// @ts-ignore: Incorrectly typed as a property instead of an accessor.
|
|
858
941
|
get spec() {
|
|
859
|
-
if (
|
|
942
|
+
if (
|
|
943
|
+
this.overrides?.value &&
|
|
944
|
+
this.overrides.value !== '*' &&
|
|
945
|
+
this.overrides.name === this.name
|
|
946
|
+
) {
|
|
860
947
|
if (this.overrides.value.startsWith('$')) {
|
|
861
|
-
const ref = this.overrides.value.slice(1)
|
|
948
|
+
const ref = this.overrides.value.slice(1)
|
|
862
949
|
// We may be a virtual root, if we are we want to resolve reference
|
|
863
950
|
// overrides from the real root, not the virtual one.
|
|
864
951
|
//
|
|
865
952
|
// Patch adding "?." use based on
|
|
866
953
|
// https://github.com/npm/cli/pull/8089.
|
|
867
|
-
const pkg = this.#safeFrom?.sourceReference
|
|
954
|
+
const pkg = this.#safeFrom?.sourceReference
|
|
955
|
+
? this.#safeFrom?.sourceReference.root.package
|
|
956
|
+
: this.#safeFrom?.root?.package
|
|
868
957
|
if (pkg?.devDependencies?.[ref]) {
|
|
869
|
-
return pkg.devDependencies[ref]
|
|
958
|
+
return pkg.devDependencies[ref]
|
|
870
959
|
}
|
|
871
960
|
if (pkg?.optionalDependencies?.[ref]) {
|
|
872
|
-
return pkg.optionalDependencies[ref]
|
|
961
|
+
return pkg.optionalDependencies[ref]
|
|
873
962
|
}
|
|
874
963
|
if (pkg?.dependencies?.[ref]) {
|
|
875
|
-
return pkg.dependencies[ref]
|
|
964
|
+
return pkg.dependencies[ref]
|
|
876
965
|
}
|
|
877
966
|
if (pkg?.peerDependencies?.[ref]) {
|
|
878
|
-
return pkg.peerDependencies[ref]
|
|
967
|
+
return pkg.peerDependencies[ref]
|
|
879
968
|
}
|
|
880
|
-
throw new Error(`Unable to resolve reference ${this.overrides.value}`)
|
|
969
|
+
throw new Error(`Unable to resolve reference ${this.overrides.value}`)
|
|
881
970
|
}
|
|
882
|
-
return this.overrides.value
|
|
971
|
+
return this.overrides.value
|
|
883
972
|
}
|
|
884
|
-
return this.rawSpec
|
|
973
|
+
return this.rawSpec
|
|
885
974
|
}
|
|
886
975
|
|
|
887
976
|
// @ts-ignore: Incorrectly typed as a property instead of an accessor.
|
|
888
977
|
get to() {
|
|
889
|
-
return this.#safeTo
|
|
978
|
+
return this.#safeTo
|
|
890
979
|
}
|
|
891
980
|
detach() {
|
|
892
|
-
this.#safeExplanation = null
|
|
981
|
+
this.#safeExplanation = null
|
|
893
982
|
// Patch replacing
|
|
894
983
|
// if (this.#to) {
|
|
895
984
|
// this.#to.edgesIn.delete(this)
|
|
896
985
|
// }
|
|
897
986
|
// this.#from.edgesOut.delete(this.#name)
|
|
898
987
|
// is based on https://github.com/npm/cli/pull/8089.
|
|
899
|
-
this.#safeTo?.deleteEdgeIn(this)
|
|
900
|
-
this.#safeFrom?.edgesOut.delete(this.name)
|
|
901
|
-
this.#safeTo = null
|
|
902
|
-
this.#safeError = 'DETACHED'
|
|
903
|
-
this.#safeFrom = null
|
|
988
|
+
this.#safeTo?.deleteEdgeIn(this)
|
|
989
|
+
this.#safeFrom?.edgesOut.delete(this.name)
|
|
990
|
+
this.#safeTo = null
|
|
991
|
+
this.#safeError = 'DETACHED'
|
|
992
|
+
this.#safeFrom = null
|
|
904
993
|
}
|
|
905
994
|
|
|
906
995
|
// Return the edge data, and an explanation of how that edge came to be here.
|
|
@@ -916,66 +1005,66 @@ class SafeEdge extends Edge {
|
|
|
916
1005
|
error: undefined,
|
|
917
1006
|
from: undefined,
|
|
918
1007
|
rawSpec: undefined
|
|
919
|
-
}
|
|
1008
|
+
}
|
|
920
1009
|
if (this.rawSpec !== this.spec) {
|
|
921
|
-
explanation.rawSpec = this.rawSpec
|
|
922
|
-
explanation.overridden = true
|
|
1010
|
+
explanation.rawSpec = this.rawSpec
|
|
1011
|
+
explanation.overridden = true
|
|
923
1012
|
}
|
|
924
1013
|
if (this.bundled) {
|
|
925
|
-
explanation.bundled = this.bundled
|
|
1014
|
+
explanation.bundled = this.bundled
|
|
926
1015
|
}
|
|
927
1016
|
if (this.error) {
|
|
928
|
-
explanation.error = this.error
|
|
1017
|
+
explanation.error = this.error
|
|
929
1018
|
}
|
|
930
1019
|
if (this.#safeFrom) {
|
|
931
|
-
explanation.from = this.#safeFrom.explain()
|
|
1020
|
+
explanation.from = this.#safeFrom.explain()
|
|
932
1021
|
}
|
|
933
|
-
this.#safeExplanation = explanation
|
|
1022
|
+
this.#safeExplanation = explanation
|
|
934
1023
|
}
|
|
935
|
-
return this.#safeExplanation
|
|
1024
|
+
return this.#safeExplanation
|
|
936
1025
|
}
|
|
937
1026
|
reload(hard = false) {
|
|
938
|
-
this.#safeExplanation = null
|
|
1027
|
+
this.#safeExplanation = null
|
|
939
1028
|
// Patch replacing
|
|
940
1029
|
// if (this.#from.overrides) {
|
|
941
1030
|
// is based on https://github.com/npm/cli/pull/8089.
|
|
942
|
-
let needToUpdateOverrideSet = false
|
|
943
|
-
let newOverrideSet
|
|
944
|
-
let oldOverrideSet
|
|
1031
|
+
let needToUpdateOverrideSet = false
|
|
1032
|
+
let newOverrideSet
|
|
1033
|
+
let oldOverrideSet
|
|
945
1034
|
if (this.#safeFrom?.overrides) {
|
|
946
|
-
newOverrideSet = this.#safeFrom.overrides.getEdgeRule(this)
|
|
1035
|
+
newOverrideSet = this.#safeFrom.overrides.getEdgeRule(this)
|
|
947
1036
|
if (newOverrideSet && !newOverrideSet.isEqual(this.overrides)) {
|
|
948
1037
|
// If there's a new different override set we need to propagate it to
|
|
949
1038
|
// the nodes. If we're deleting the override set then there's no point
|
|
950
1039
|
// propagating it right now since it will be filled with another value
|
|
951
1040
|
// later.
|
|
952
|
-
needToUpdateOverrideSet = true
|
|
953
|
-
oldOverrideSet = this.overrides
|
|
954
|
-
this.overrides = newOverrideSet
|
|
1041
|
+
needToUpdateOverrideSet = true
|
|
1042
|
+
oldOverrideSet = this.overrides
|
|
1043
|
+
this.overrides = newOverrideSet
|
|
955
1044
|
}
|
|
956
1045
|
} else {
|
|
957
|
-
this.overrides = undefined
|
|
1046
|
+
this.overrides = undefined
|
|
958
1047
|
}
|
|
959
1048
|
// Patch adding "?." use based on
|
|
960
1049
|
// https://github.com/npm/cli/pull/8089.
|
|
961
|
-
const newTo = this.#safeFrom?.resolve(this.name)
|
|
1050
|
+
const newTo = this.#safeFrom?.resolve(this.name)
|
|
962
1051
|
if (newTo !== this.#safeTo) {
|
|
963
1052
|
// Patch replacing
|
|
964
1053
|
// this.#to.edgesIn.delete(this)
|
|
965
1054
|
// is based on https://github.com/npm/cli/pull/8089.
|
|
966
|
-
this.#safeTo?.deleteEdgeIn(this)
|
|
967
|
-
this.#safeTo = newTo ?? null
|
|
968
|
-
this.#safeError = null
|
|
969
|
-
this.#safeTo?.addEdgeIn(this)
|
|
1055
|
+
this.#safeTo?.deleteEdgeIn(this)
|
|
1056
|
+
this.#safeTo = newTo ?? null
|
|
1057
|
+
this.#safeError = null
|
|
1058
|
+
this.#safeTo?.addEdgeIn(this)
|
|
970
1059
|
} else if (hard) {
|
|
971
|
-
this.#safeError = null
|
|
1060
|
+
this.#safeError = null
|
|
972
1061
|
}
|
|
973
1062
|
// Patch adding "else if" condition based on
|
|
974
1063
|
// https://github.com/npm/cli/pull/8089.
|
|
975
1064
|
else if (needToUpdateOverrideSet && this.#safeTo) {
|
|
976
1065
|
// Propagate the new override set to the target node.
|
|
977
|
-
this.#safeTo.updateOverridesEdgeInRemoved(oldOverrideSet)
|
|
978
|
-
this.#safeTo.updateOverridesEdgeInAdded(newOverrideSet)
|
|
1066
|
+
this.#safeTo.updateOverridesEdgeInRemoved(oldOverrideSet)
|
|
1067
|
+
this.#safeTo.updateOverridesEdgeInAdded(newOverrideSet)
|
|
979
1068
|
}
|
|
980
1069
|
}
|
|
981
1070
|
satisfiedBy(node) {
|
|
@@ -985,12 +1074,12 @@ class SafeEdge extends Edge {
|
|
|
985
1074
|
// }
|
|
986
1075
|
// is based on https://github.com/npm/cli/pull/8089.
|
|
987
1076
|
if (node.name !== this.name || !this.#safeFrom) {
|
|
988
|
-
return false
|
|
1077
|
+
return false
|
|
989
1078
|
}
|
|
990
1079
|
// NOTE: this condition means we explicitly do not support overriding
|
|
991
1080
|
// bundled or shrinkwrapped dependencies
|
|
992
1081
|
if (node.hasShrinkwrap || node.inShrinkwrap || node.inBundle) {
|
|
993
|
-
return depValid(node, this.rawSpec, this.accept, this.#safeFrom)
|
|
1082
|
+
return depValid(node, this.rawSpec, this.accept, this.#safeFrom)
|
|
994
1083
|
}
|
|
995
1084
|
// Patch replacing
|
|
996
1085
|
// return depValid(node, this.spec, this.#accept, this.#from)
|
|
@@ -998,16 +1087,16 @@ class SafeEdge extends Edge {
|
|
|
998
1087
|
//
|
|
999
1088
|
// If there's no override we just use the spec.
|
|
1000
1089
|
if (!this.overrides?.keySpec) {
|
|
1001
|
-
return depValid(node, this.spec, this.accept, this.#safeFrom)
|
|
1090
|
+
return depValid(node, this.spec, this.accept, this.#safeFrom)
|
|
1002
1091
|
}
|
|
1003
1092
|
// There's some override. If the target node satisfies the overriding spec
|
|
1004
1093
|
// then it's okay.
|
|
1005
1094
|
if (depValid(node, this.spec, this.accept, this.#safeFrom)) {
|
|
1006
|
-
return true
|
|
1095
|
+
return true
|
|
1007
1096
|
}
|
|
1008
1097
|
// If it doesn't, then it should at least satisfy the original spec.
|
|
1009
1098
|
if (!depValid(node, this.rawSpec, this.accept, this.#safeFrom)) {
|
|
1010
|
-
return false
|
|
1099
|
+
return false
|
|
1011
1100
|
}
|
|
1012
1101
|
// It satisfies the original spec, not the overriding spec. We need to make
|
|
1013
1102
|
// sure it doesn't use the overridden spec.
|
|
@@ -1019,7 +1108,7 @@ class SafeEdge extends Edge {
|
|
|
1019
1108
|
// If the node is 8.23.0, then it's not okay because even though it's consistent
|
|
1020
1109
|
// with the rawSpec, it's also consistent with the keySpec.
|
|
1021
1110
|
// So we're looking for ^8.0.0 or 9.0.0 and not 8.23.0.
|
|
1022
|
-
return !depValid(node, this.overrides.keySpec, this.accept, this.#safeFrom)
|
|
1111
|
+
return !depValid(node, this.overrides.keySpec, this.accept, this.#safeFrom)
|
|
1023
1112
|
}
|
|
1024
1113
|
}
|
|
1025
1114
|
|
|
@@ -1028,364 +1117,260 @@ const {
|
|
|
1028
1117
|
ALERT_TYPE_CVE,
|
|
1029
1118
|
ALERT_TYPE_MEDIUM_CVE,
|
|
1030
1119
|
ALERT_TYPE_MILD_CVE
|
|
1031
|
-
} = constants
|
|
1120
|
+
} = constants
|
|
1032
1121
|
function isArtifactAlertCve(alert) {
|
|
1033
|
-
const {
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
ALERT_FIX_TYPE["cve"] = "cve";
|
|
1041
|
-
ALERT_FIX_TYPE["upgrade"] = "upgrade";
|
|
1042
|
-
return ALERT_FIX_TYPE;
|
|
1043
|
-
}({});
|
|
1044
|
-
|
|
1045
|
-
const ERROR_UX = {
|
|
1046
|
-
block: true,
|
|
1047
|
-
display: true
|
|
1048
|
-
};
|
|
1049
|
-
const IGNORE_UX = {
|
|
1050
|
-
block: false,
|
|
1051
|
-
display: false
|
|
1052
|
-
};
|
|
1053
|
-
const WARN_UX = {
|
|
1054
|
-
block: false,
|
|
1055
|
-
display: true
|
|
1056
|
-
};
|
|
1057
|
-
|
|
1058
|
-
// Iterates over all entries with ordered issue rule for deferral. Iterates over
|
|
1059
|
-
// all issue rules and finds the first defined value that does not defer otherwise
|
|
1060
|
-
// uses the defaultValue. Takes the value and converts into a UX workflow.
|
|
1061
|
-
function resolveAlertRuleUX(orderedRulesCollection, defaultValue) {
|
|
1062
|
-
if (defaultValue === true || defaultValue === null || defaultValue === undefined) {
|
|
1063
|
-
defaultValue = {
|
|
1064
|
-
action: 'error'
|
|
1065
|
-
};
|
|
1066
|
-
} else if (defaultValue === false) {
|
|
1067
|
-
defaultValue = {
|
|
1068
|
-
action: 'ignore'
|
|
1069
|
-
};
|
|
1070
|
-
}
|
|
1071
|
-
let block = false;
|
|
1072
|
-
let display = false;
|
|
1073
|
-
let needDefault = true;
|
|
1074
|
-
iterate_entries: for (const rules of orderedRulesCollection) {
|
|
1075
|
-
for (const rule of rules) {
|
|
1076
|
-
if (ruleValueDoesNotDefer(rule)) {
|
|
1077
|
-
needDefault = false;
|
|
1078
|
-
const narrowingFilter = uxForDefinedNonDeferValue(rule);
|
|
1079
|
-
block = block || narrowingFilter.block;
|
|
1080
|
-
display = display || narrowingFilter.display;
|
|
1081
|
-
continue iterate_entries;
|
|
1082
|
-
}
|
|
1083
|
-
}
|
|
1084
|
-
const narrowingFilter = uxForDefinedNonDeferValue(defaultValue);
|
|
1085
|
-
block = block || narrowingFilter.block;
|
|
1086
|
-
display = display || narrowingFilter.display;
|
|
1087
|
-
}
|
|
1088
|
-
if (needDefault) {
|
|
1089
|
-
const narrowingFilter = uxForDefinedNonDeferValue(defaultValue);
|
|
1090
|
-
block = block || narrowingFilter.block;
|
|
1091
|
-
display = display || narrowingFilter.display;
|
|
1092
|
-
}
|
|
1093
|
-
return {
|
|
1094
|
-
block,
|
|
1095
|
-
display
|
|
1096
|
-
};
|
|
1097
|
-
}
|
|
1098
|
-
|
|
1099
|
-
// Negative form because it is narrowing the type.
|
|
1100
|
-
function ruleValueDoesNotDefer(rule) {
|
|
1101
|
-
if (rule === undefined) {
|
|
1102
|
-
return false;
|
|
1103
|
-
}
|
|
1104
|
-
if (objects.isObject(rule)) {
|
|
1105
|
-
const {
|
|
1106
|
-
action
|
|
1107
|
-
} = rule;
|
|
1108
|
-
if (action === undefined || action === 'defer') {
|
|
1109
|
-
return false;
|
|
1110
|
-
}
|
|
1111
|
-
}
|
|
1112
|
-
return true;
|
|
1122
|
+
const { type } = alert
|
|
1123
|
+
return (
|
|
1124
|
+
type === ALERT_TYPE_CVE ||
|
|
1125
|
+
type === ALERT_TYPE_MEDIUM_CVE ||
|
|
1126
|
+
type === ALERT_TYPE_MILD_CVE ||
|
|
1127
|
+
type === ALERT_TYPE_CRITICAL_CVE
|
|
1128
|
+
)
|
|
1113
1129
|
}
|
|
1114
1130
|
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
const {
|
|
1121
|
-
action
|
|
1122
|
-
} = ruleValue;
|
|
1123
|
-
if (action === 'warn') {
|
|
1124
|
-
return WARN_UX;
|
|
1125
|
-
} else if (action === 'ignore') {
|
|
1126
|
-
return IGNORE_UX;
|
|
1127
|
-
}
|
|
1128
|
-
return ERROR_UX;
|
|
1129
|
-
}
|
|
1130
|
-
function createAlertUXLookup(settings) {
|
|
1131
|
-
const cachedUX = new Map();
|
|
1132
|
-
return context => {
|
|
1133
|
-
const {
|
|
1134
|
-
type
|
|
1135
|
-
} = context.alert;
|
|
1136
|
-
let ux = cachedUX.get(type);
|
|
1137
|
-
if (ux) {
|
|
1138
|
-
return ux;
|
|
1139
|
-
}
|
|
1140
|
-
const orderedRulesCollection = [];
|
|
1141
|
-
for (const settingsEntry of settings.entries) {
|
|
1142
|
-
const orderedRules = [];
|
|
1143
|
-
let target = settingsEntry.start;
|
|
1144
|
-
while (target !== null) {
|
|
1145
|
-
const resolvedTarget = settingsEntry.settings[target];
|
|
1146
|
-
if (!resolvedTarget) {
|
|
1147
|
-
break;
|
|
1148
|
-
}
|
|
1149
|
-
const issueRuleValue = resolvedTarget.issueRules?.[type];
|
|
1150
|
-
if (typeof issueRuleValue !== 'undefined') {
|
|
1151
|
-
orderedRules.push(issueRuleValue);
|
|
1152
|
-
}
|
|
1153
|
-
target = resolvedTarget.deferTo ?? null;
|
|
1154
|
-
}
|
|
1155
|
-
orderedRulesCollection.push(orderedRules);
|
|
1156
|
-
}
|
|
1157
|
-
const defaultValue = settings.defaults.issueRules[type];
|
|
1158
|
-
let resolvedDefaultValue = {
|
|
1159
|
-
action: 'error'
|
|
1160
|
-
};
|
|
1161
|
-
if (defaultValue === false) {
|
|
1162
|
-
resolvedDefaultValue = {
|
|
1163
|
-
action: 'ignore'
|
|
1164
|
-
};
|
|
1165
|
-
} else if (defaultValue && defaultValue !== true) {
|
|
1166
|
-
resolvedDefaultValue = {
|
|
1167
|
-
action: defaultValue.action ?? 'error'
|
|
1168
|
-
};
|
|
1169
|
-
}
|
|
1170
|
-
ux = resolveAlertRuleUX(orderedRulesCollection, resolvedDefaultValue);
|
|
1171
|
-
cachedUX.set(type, ux);
|
|
1172
|
-
return ux;
|
|
1173
|
-
};
|
|
1174
|
-
}
|
|
1175
|
-
let _uxLookup;
|
|
1176
|
-
async function uxLookup(settings) {
|
|
1177
|
-
if (_uxLookup === undefined) {
|
|
1178
|
-
const {
|
|
1179
|
-
orgs,
|
|
1180
|
-
settings
|
|
1181
|
-
} = await (async () => {
|
|
1182
|
-
try {
|
|
1183
|
-
const sockSdk = await setupSdk(getPublicToken());
|
|
1184
|
-
const orgResult = await sockSdk.getOrganizations();
|
|
1185
|
-
if (!orgResult.success) {
|
|
1186
|
-
if (orgResult.status === 429) {
|
|
1187
|
-
throw new Error(`API token quota exceeded: ${orgResult.error}`);
|
|
1188
|
-
}
|
|
1189
|
-
throw new Error(`Failed to fetch Socket organization info: ${orgResult.error}`);
|
|
1190
|
-
}
|
|
1191
|
-
const {
|
|
1192
|
-
organizations
|
|
1193
|
-
} = orgResult.data;
|
|
1194
|
-
const orgs = [];
|
|
1195
|
-
for (const org of Object.values(organizations)) {
|
|
1196
|
-
if (org) {
|
|
1197
|
-
orgs.push(org);
|
|
1198
|
-
}
|
|
1199
|
-
}
|
|
1200
|
-
const settingsResult = await sockSdk.postSettings(orgs.map(org => ({
|
|
1201
|
-
organization: org.id
|
|
1202
|
-
})));
|
|
1203
|
-
if (!settingsResult.success) {
|
|
1204
|
-
throw new Error(`Failed to fetch API key settings: ${settingsResult.error}`);
|
|
1205
|
-
}
|
|
1206
|
-
return {
|
|
1207
|
-
orgs,
|
|
1208
|
-
settings: settingsResult.data
|
|
1209
|
-
};
|
|
1210
|
-
} catch (e) {
|
|
1211
|
-
const cause = objects.isObject(e) && 'cause' in e ? e['cause'] : undefined;
|
|
1212
|
-
if (isErrnoException(cause) && (cause.code === 'ENOTFOUND' || cause.code === 'ECONNREFUSED')) {
|
|
1213
|
-
throw new Error('Unable to connect to socket.dev, ensure internet connectivity before retrying', {
|
|
1214
|
-
cause: e
|
|
1215
|
-
});
|
|
1216
|
-
}
|
|
1217
|
-
throw e;
|
|
1218
|
-
}
|
|
1219
|
-
})();
|
|
1220
|
-
// Remove any organizations not being enforced.
|
|
1221
|
-
const enforcedOrgs = getConfigValue('enforcedOrgs') ?? [];
|
|
1222
|
-
for (const {
|
|
1223
|
-
0: i,
|
|
1224
|
-
1: org
|
|
1225
|
-
} of orgs.entries()) {
|
|
1226
|
-
if (!enforcedOrgs.includes(org.id)) {
|
|
1227
|
-
settings.entries.splice(i, 1);
|
|
1228
|
-
}
|
|
1229
|
-
}
|
|
1230
|
-
const socketYml = findSocketYmlSync();
|
|
1231
|
-
if (socketYml) {
|
|
1232
|
-
settings.entries.push({
|
|
1233
|
-
start: socketYml.path,
|
|
1234
|
-
settings: {
|
|
1235
|
-
[socketYml.path]: {
|
|
1236
|
-
deferTo: null,
|
|
1237
|
-
// TODO: TypeScript complains about the type not matching. We should
|
|
1238
|
-
// figure out why are providing
|
|
1239
|
-
// issueRules: { [issueName: string]: boolean }
|
|
1240
|
-
// but expecting
|
|
1241
|
-
// issueRules: { [issueName: string]: { action: 'defer' | 'error' | 'ignore' | 'monitor' | 'warn' } }
|
|
1242
|
-
issueRules: socketYml.parsed.issueRules
|
|
1243
|
-
}
|
|
1244
|
-
}
|
|
1245
|
-
});
|
|
1246
|
-
}
|
|
1247
|
-
_uxLookup = createAlertUXLookup(settings);
|
|
1248
|
-
}
|
|
1249
|
-
return _uxLookup(settings);
|
|
1250
|
-
}
|
|
1131
|
+
const ALERT_FIX_TYPE = /*#__PURE__*/ (function (ALERT_FIX_TYPE) {
|
|
1132
|
+
ALERT_FIX_TYPE['cve'] = 'cve'
|
|
1133
|
+
ALERT_FIX_TYPE['upgrade'] = 'upgrade'
|
|
1134
|
+
return ALERT_FIX_TYPE
|
|
1135
|
+
})({})
|
|
1251
1136
|
|
|
1252
1137
|
function pick(input, keys) {
|
|
1253
|
-
const result = {}
|
|
1138
|
+
const result = {}
|
|
1254
1139
|
for (const key of keys) {
|
|
1255
|
-
result[key] = input[key]
|
|
1140
|
+
result[key] = input[key]
|
|
1256
1141
|
}
|
|
1257
|
-
return result
|
|
1142
|
+
return result
|
|
1258
1143
|
}
|
|
1259
1144
|
|
|
1260
1145
|
function stringJoinWithSeparateFinalSeparator(list, separator = ' and ') {
|
|
1261
|
-
const values = list.filter(Boolean)
|
|
1262
|
-
const {
|
|
1263
|
-
length
|
|
1264
|
-
} = values;
|
|
1146
|
+
const values = list.filter(Boolean)
|
|
1147
|
+
const { length } = values
|
|
1265
1148
|
if (!length) {
|
|
1266
|
-
return ''
|
|
1149
|
+
return ''
|
|
1267
1150
|
}
|
|
1268
1151
|
if (length === 1) {
|
|
1269
|
-
return values[0]
|
|
1152
|
+
return values[0]
|
|
1270
1153
|
}
|
|
1271
|
-
const finalValue = values.pop()
|
|
1272
|
-
return `${values.join(', ')}${separator}${finalValue}
|
|
1154
|
+
const finalValue = values.pop()
|
|
1155
|
+
return `${values.join(', ')}${separator}${finalValue}`
|
|
1273
1156
|
}
|
|
1274
1157
|
|
|
1275
|
-
|
|
1276
|
-
ALERT_SEVERITY[
|
|
1277
|
-
ALERT_SEVERITY[
|
|
1278
|
-
ALERT_SEVERITY[
|
|
1279
|
-
ALERT_SEVERITY[
|
|
1280
|
-
return ALERT_SEVERITY
|
|
1281
|
-
}({})
|
|
1158
|
+
const ALERT_SEVERITY = /*#__PURE__*/ (function (ALERT_SEVERITY) {
|
|
1159
|
+
ALERT_SEVERITY['critical'] = 'critical'
|
|
1160
|
+
ALERT_SEVERITY['high'] = 'high'
|
|
1161
|
+
ALERT_SEVERITY['middle'] = 'middle'
|
|
1162
|
+
ALERT_SEVERITY['low'] = 'low'
|
|
1163
|
+
return ALERT_SEVERITY
|
|
1164
|
+
})({})
|
|
1282
1165
|
// Ordered from most severe to least.
|
|
1283
|
-
const
|
|
1166
|
+
const ALERT_SEVERITIES_SORTED = Object.freeze([
|
|
1167
|
+
'critical',
|
|
1168
|
+
'high',
|
|
1169
|
+
'middle',
|
|
1170
|
+
'low'
|
|
1171
|
+
])
|
|
1284
1172
|
function getDesiredSeverities(lowestToInclude) {
|
|
1285
|
-
const result = []
|
|
1286
|
-
for (const severity of
|
|
1287
|
-
result.push(severity)
|
|
1173
|
+
const result = []
|
|
1174
|
+
for (const severity of ALERT_SEVERITIES_SORTED) {
|
|
1175
|
+
result.push(severity)
|
|
1288
1176
|
if (severity === lowestToInclude) {
|
|
1289
|
-
break
|
|
1177
|
+
break
|
|
1290
1178
|
}
|
|
1291
1179
|
}
|
|
1292
|
-
return result
|
|
1180
|
+
return result
|
|
1293
1181
|
}
|
|
1294
1182
|
function formatSeverityCount(severityCount) {
|
|
1295
|
-
const summary = []
|
|
1296
|
-
for (const severity of
|
|
1183
|
+
const summary = []
|
|
1184
|
+
for (const severity of ALERT_SEVERITIES_SORTED) {
|
|
1297
1185
|
if (severityCount[severity]) {
|
|
1298
|
-
summary.push(`${severityCount[severity]} ${severity}`)
|
|
1186
|
+
summary.push(`${severityCount[severity]} ${severity}`)
|
|
1299
1187
|
}
|
|
1300
1188
|
}
|
|
1301
|
-
return stringJoinWithSeparateFinalSeparator(summary)
|
|
1189
|
+
return stringJoinWithSeparateFinalSeparator(summary)
|
|
1302
1190
|
}
|
|
1303
1191
|
function getSeverityCount(issues, lowestToInclude) {
|
|
1304
|
-
const severityCount = pick(
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1192
|
+
const severityCount = pick(
|
|
1193
|
+
{
|
|
1194
|
+
low: 0,
|
|
1195
|
+
middle: 0,
|
|
1196
|
+
high: 0,
|
|
1197
|
+
critical: 0
|
|
1198
|
+
},
|
|
1199
|
+
getDesiredSeverities(lowestToInclude)
|
|
1200
|
+
)
|
|
1310
1201
|
for (const issue of issues) {
|
|
1311
|
-
const {
|
|
1312
|
-
value
|
|
1313
|
-
} = issue;
|
|
1202
|
+
const { value } = issue
|
|
1314
1203
|
if (!value) {
|
|
1315
|
-
continue
|
|
1204
|
+
continue
|
|
1316
1205
|
}
|
|
1317
|
-
const {
|
|
1318
|
-
severity
|
|
1319
|
-
} = value;
|
|
1206
|
+
const { severity } = value
|
|
1320
1207
|
if (severityCount[severity] !== undefined) {
|
|
1321
|
-
severityCount[severity] += 1
|
|
1208
|
+
severityCount[severity] += 1
|
|
1322
1209
|
}
|
|
1323
1210
|
}
|
|
1324
|
-
return severityCount
|
|
1211
|
+
return severityCount
|
|
1325
1212
|
}
|
|
1326
1213
|
|
|
1327
1214
|
class ColorOrMarkdown {
|
|
1328
1215
|
constructor(useMarkdown) {
|
|
1329
|
-
this.useMarkdown = !!useMarkdown
|
|
1216
|
+
this.useMarkdown = !!useMarkdown
|
|
1330
1217
|
}
|
|
1331
1218
|
bold(text) {
|
|
1332
|
-
return this.useMarkdown ? `**${text}**` : colors.bold(`${text}`)
|
|
1219
|
+
return this.useMarkdown ? `**${text}**` : colors.bold(`${text}`)
|
|
1333
1220
|
}
|
|
1334
1221
|
header(text, level = 1) {
|
|
1335
|
-
return this.useMarkdown
|
|
1222
|
+
return this.useMarkdown
|
|
1223
|
+
? `\n${''.padStart(level, '#')} ${text}\n`
|
|
1224
|
+
: colors.underline(`\n${level === 1 ? colors.bold(text) : text}\n`)
|
|
1336
1225
|
}
|
|
1337
|
-
hyperlink(text, url, {
|
|
1338
|
-
fallback = true,
|
|
1339
|
-
fallbackToUrl
|
|
1340
|
-
} = {}) {
|
|
1226
|
+
hyperlink(text, url, { fallback = true, fallbackToUrl } = {}) {
|
|
1341
1227
|
if (url) {
|
|
1342
|
-
return this.useMarkdown
|
|
1343
|
-
|
|
1344
|
-
|
|
1228
|
+
return this.useMarkdown
|
|
1229
|
+
? `[${text}](${url})`
|
|
1230
|
+
: terminalLink(text, url, {
|
|
1231
|
+
fallback: fallbackToUrl ? (_text, url) => url : fallback
|
|
1232
|
+
})
|
|
1345
1233
|
}
|
|
1346
|
-
return text
|
|
1234
|
+
return text
|
|
1347
1235
|
}
|
|
1348
1236
|
indent(...args) {
|
|
1349
|
-
return indentString(...args)
|
|
1237
|
+
return indentString(...args)
|
|
1350
1238
|
}
|
|
1351
1239
|
italic(text) {
|
|
1352
|
-
return this.useMarkdown ? `_${text}_` : colors.italic(`${text}`)
|
|
1240
|
+
return this.useMarkdown ? `_${text}_` : colors.italic(`${text}`)
|
|
1353
1241
|
}
|
|
1354
1242
|
json(value) {
|
|
1355
|
-
return this.useMarkdown
|
|
1243
|
+
return this.useMarkdown
|
|
1244
|
+
? '```json\n' + JSON.stringify(value) + '\n```'
|
|
1245
|
+
: JSON.stringify(value)
|
|
1356
1246
|
}
|
|
1357
1247
|
list(items) {
|
|
1358
|
-
const indentedContent = items.map(item => this.indent(item).trimStart())
|
|
1359
|
-
return this.useMarkdown
|
|
1248
|
+
const indentedContent = items.map(item => this.indent(item).trimStart())
|
|
1249
|
+
return this.useMarkdown
|
|
1250
|
+
? `* ${indentedContent.join('\n* ')}\n`
|
|
1251
|
+
: `${indentedContent.join('\n')}\n`
|
|
1360
1252
|
}
|
|
1361
1253
|
}
|
|
1362
1254
|
|
|
1363
1255
|
function getSocketDevAlertUrl(alertType) {
|
|
1364
|
-
return `https://socket.dev/alerts/${alertType}
|
|
1256
|
+
return `https://socket.dev/alerts/${alertType}`
|
|
1365
1257
|
}
|
|
1366
1258
|
function getSocketDevPackageOverviewUrl(eco, name, version) {
|
|
1367
|
-
return `https://socket.dev/${eco}/package/${name}${version ? `/overview/${version}` : ''}
|
|
1259
|
+
return `https://socket.dev/${eco}/package/${name}${version ? `/overview/${version}` : ''}`
|
|
1368
1260
|
}
|
|
1369
1261
|
|
|
1370
|
-
let _translations
|
|
1262
|
+
let _translations
|
|
1371
1263
|
function getTranslations() {
|
|
1372
1264
|
if (_translations === undefined) {
|
|
1373
1265
|
_translations = require(
|
|
1374
|
-
|
|
1375
|
-
|
|
1266
|
+
// Lazily access constants.rootPath.
|
|
1267
|
+
path.join(constants.rootPath, 'translations.json')
|
|
1268
|
+
)
|
|
1376
1269
|
}
|
|
1377
|
-
return _translations
|
|
1270
|
+
return _translations
|
|
1378
1271
|
}
|
|
1379
1272
|
|
|
1380
|
-
const {
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1273
|
+
const ALERT_SEVERITY_COLOR = /*#__PURE__*/ (function (ALERT_SEVERITY_COLOR) {
|
|
1274
|
+
ALERT_SEVERITY_COLOR['critical'] = 'magenta'
|
|
1275
|
+
ALERT_SEVERITY_COLOR['high'] = 'red'
|
|
1276
|
+
ALERT_SEVERITY_COLOR['middle'] = 'yellow'
|
|
1277
|
+
ALERT_SEVERITY_COLOR['low'] = 'white'
|
|
1278
|
+
return ALERT_SEVERITY_COLOR
|
|
1279
|
+
})({})
|
|
1280
|
+
const ALERT_SEVERITY_ORDER = /*#__PURE__*/ (function (ALERT_SEVERITY_ORDER) {
|
|
1281
|
+
ALERT_SEVERITY_ORDER[(ALERT_SEVERITY_ORDER['critical'] = 0)] = 'critical'
|
|
1282
|
+
ALERT_SEVERITY_ORDER[(ALERT_SEVERITY_ORDER['high'] = 1)] = 'high'
|
|
1283
|
+
ALERT_SEVERITY_ORDER[(ALERT_SEVERITY_ORDER['middle'] = 2)] = 'middle'
|
|
1284
|
+
ALERT_SEVERITY_ORDER[(ALERT_SEVERITY_ORDER['low'] = 3)] = 'low'
|
|
1285
|
+
ALERT_SEVERITY_ORDER[(ALERT_SEVERITY_ORDER['none'] = 4)] = 'none'
|
|
1286
|
+
return ALERT_SEVERITY_ORDER
|
|
1287
|
+
})({})
|
|
1288
|
+
const { CVE_ALERT_PROPS_FIRST_PATCHED_VERSION_IDENTIFIER, NPM: NPM$2 } =
|
|
1289
|
+
constants
|
|
1290
|
+
const MIN_ABOVE_THE_FOLD_COUNT = 3
|
|
1291
|
+
const MIN_ABOVE_THE_FOLD_ALERT_COUNT = 1
|
|
1292
|
+
const format = new ColorOrMarkdown(false)
|
|
1293
|
+
function alertsHaveBlocked(alerts) {
|
|
1294
|
+
return alerts.find(a => a.blocked) !== undefined
|
|
1295
|
+
}
|
|
1296
|
+
function alertsHaveSeverity(alerts, severity) {
|
|
1297
|
+
return alerts.find(a => a.raw.severity === severity) !== undefined
|
|
1298
|
+
}
|
|
1299
|
+
function alertSeverityComparator(a, b) {
|
|
1300
|
+
return getAlertSeverityOrder(a) - getAlertSeverityOrder(b)
|
|
1301
|
+
}
|
|
1302
|
+
function getAlertSeverityOrder(alert) {
|
|
1303
|
+
const { severity } = alert.raw
|
|
1304
|
+
return severity === ALERT_SEVERITY.critical
|
|
1305
|
+
? 0
|
|
1306
|
+
: severity === ALERT_SEVERITY.high
|
|
1307
|
+
? 1
|
|
1308
|
+
: severity === ALERT_SEVERITY.middle
|
|
1309
|
+
? 2
|
|
1310
|
+
: severity === ALERT_SEVERITY.low
|
|
1311
|
+
? 3
|
|
1312
|
+
: 4
|
|
1313
|
+
}
|
|
1314
|
+
function getAlertsSeverityOrder(alerts) {
|
|
1315
|
+
return alertsHaveBlocked(alerts) ||
|
|
1316
|
+
alertsHaveSeverity(alerts, ALERT_SEVERITY.critical)
|
|
1317
|
+
? 0
|
|
1318
|
+
: alertsHaveSeverity(alerts, ALERT_SEVERITY.high)
|
|
1319
|
+
? 1
|
|
1320
|
+
: alertsHaveSeverity(alerts, ALERT_SEVERITY.middle)
|
|
1321
|
+
? 2
|
|
1322
|
+
: alertsHaveSeverity(alerts, ALERT_SEVERITY.low)
|
|
1323
|
+
? 3
|
|
1324
|
+
: 4
|
|
1325
|
+
}
|
|
1326
|
+
function getHiddenRiskCounts(hiddenAlerts) {
|
|
1327
|
+
const riskCounts = {
|
|
1328
|
+
critical: 0,
|
|
1329
|
+
high: 0,
|
|
1330
|
+
middle: 0,
|
|
1331
|
+
low: 0
|
|
1332
|
+
}
|
|
1333
|
+
for (const alert of hiddenAlerts) {
|
|
1334
|
+
switch (getAlertSeverityOrder(alert)) {
|
|
1335
|
+
case ALERT_SEVERITY_ORDER.critical:
|
|
1336
|
+
riskCounts.critical += 1
|
|
1337
|
+
break
|
|
1338
|
+
case ALERT_SEVERITY_ORDER.high:
|
|
1339
|
+
riskCounts.high += 1
|
|
1340
|
+
break
|
|
1341
|
+
case ALERT_SEVERITY_ORDER.middle:
|
|
1342
|
+
riskCounts.middle += 1
|
|
1343
|
+
break
|
|
1344
|
+
case ALERT_SEVERITY_ORDER.low:
|
|
1345
|
+
riskCounts.low += 1
|
|
1346
|
+
break
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
return riskCounts
|
|
1350
|
+
}
|
|
1351
|
+
function getHiddenRisksDescription(riskCounts) {
|
|
1352
|
+
const descriptions = []
|
|
1353
|
+
if (riskCounts.critical) {
|
|
1354
|
+
descriptions.push(`${riskCounts.critical} ${getSeverityLabel('critical')}`)
|
|
1355
|
+
}
|
|
1356
|
+
if (riskCounts.high) {
|
|
1357
|
+
descriptions.push(`${riskCounts.high} ${getSeverityLabel('high')}`)
|
|
1358
|
+
}
|
|
1359
|
+
if (riskCounts.middle) {
|
|
1360
|
+
descriptions.push(`${riskCounts.middle} ${getSeverityLabel('middle')}`)
|
|
1361
|
+
}
|
|
1362
|
+
if (riskCounts.low) {
|
|
1363
|
+
descriptions.push(`${riskCounts.low} ${getSeverityLabel('low')}`)
|
|
1364
|
+
}
|
|
1365
|
+
return `(${descriptions.join('; ')})`
|
|
1366
|
+
}
|
|
1367
|
+
function getSeverityLabel(severity) {
|
|
1368
|
+
return severity === 'middle' ? 'moderate' : severity
|
|
1369
|
+
}
|
|
1385
1370
|
async function addArtifactToAlertsMap(artifact, alertsByPkgId, options) {
|
|
1386
1371
|
// Make TypeScript happy.
|
|
1387
1372
|
if (!artifact.name || !artifact.version || !artifact.alerts?.length) {
|
|
1388
|
-
return alertsByPkgId
|
|
1373
|
+
return alertsByPkgId
|
|
1389
1374
|
}
|
|
1390
1375
|
const {
|
|
1391
1376
|
consolidate = false,
|
|
@@ -1394,176 +1379,322 @@ async function addArtifactToAlertsMap(artifact, alertsByPkgId, options) {
|
|
|
1394
1379
|
} = {
|
|
1395
1380
|
__proto__: null,
|
|
1396
1381
|
...options
|
|
1397
|
-
}
|
|
1382
|
+
}
|
|
1398
1383
|
const include = {
|
|
1399
1384
|
__proto__: null,
|
|
1385
|
+
blocked: true,
|
|
1400
1386
|
critical: true,
|
|
1401
1387
|
cve: true,
|
|
1402
1388
|
unfixable: true,
|
|
1403
|
-
|
|
1389
|
+
upgradable: false,
|
|
1404
1390
|
..._include
|
|
1405
|
-
}
|
|
1406
|
-
const name = packages.resolvePackageName(artifact)
|
|
1407
|
-
const {
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
const
|
|
1411
|
-
const
|
|
1412
|
-
|
|
1391
|
+
}
|
|
1392
|
+
const name = packages.resolvePackageName(artifact)
|
|
1393
|
+
const { version } = artifact
|
|
1394
|
+
const pkgId = `${name}@${version}`
|
|
1395
|
+
const major = semver.major(version)
|
|
1396
|
+
const socketYml = findSocketYmlSync()
|
|
1397
|
+
const enabledState = {
|
|
1398
|
+
__proto__: null,
|
|
1399
|
+
...socketYml?.parsed.issueRules
|
|
1400
|
+
}
|
|
1401
|
+
let sockPkgAlerts = []
|
|
1413
1402
|
for (const alert of artifact.alerts) {
|
|
1414
|
-
|
|
1415
|
-
const
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
const
|
|
1425
|
-
const
|
|
1426
|
-
const
|
|
1427
|
-
const
|
|
1428
|
-
const
|
|
1429
|
-
const
|
|
1430
|
-
|
|
1431
|
-
|
|
1403
|
+
const action = alert.action ?? ''
|
|
1404
|
+
const enabledFlag = enabledState[alert.type]
|
|
1405
|
+
if (
|
|
1406
|
+
(action === 'ignore' && enabledFlag !== true) ||
|
|
1407
|
+
enabledFlag === false
|
|
1408
|
+
) {
|
|
1409
|
+
continue
|
|
1410
|
+
}
|
|
1411
|
+
const blocked = action === 'error'
|
|
1412
|
+
const critical = alert.severity === ALERT_SEVERITY.critical
|
|
1413
|
+
const cve = isArtifactAlertCve(alert)
|
|
1414
|
+
const fixType = alert.fix?.type ?? ''
|
|
1415
|
+
const fixableCve = fixType === ALERT_FIX_TYPE.cve
|
|
1416
|
+
const fixableUpgrade = fixType === ALERT_FIX_TYPE.upgrade
|
|
1417
|
+
const fixable = fixableCve || fixableUpgrade
|
|
1418
|
+
const upgradable = fixableUpgrade && !objects.hasOwn(overrides, name)
|
|
1419
|
+
if (
|
|
1420
|
+
(include.blocked && blocked) ||
|
|
1421
|
+
(include.critical && critical) ||
|
|
1422
|
+
(include.cve && cve) ||
|
|
1423
|
+
(include.unfixable && !fixable) ||
|
|
1424
|
+
(include.upgradable && upgradable)
|
|
1425
|
+
) {
|
|
1432
1426
|
sockPkgAlerts.push({
|
|
1433
1427
|
name,
|
|
1434
1428
|
version,
|
|
1435
1429
|
key: alert.key,
|
|
1436
1430
|
type: alert.type,
|
|
1437
|
-
|
|
1431
|
+
blocked,
|
|
1438
1432
|
critical,
|
|
1439
|
-
display: ux.display,
|
|
1440
1433
|
fixable,
|
|
1441
1434
|
raw: alert,
|
|
1442
|
-
|
|
1443
|
-
})
|
|
1435
|
+
upgradable
|
|
1436
|
+
})
|
|
1444
1437
|
}
|
|
1445
1438
|
}
|
|
1446
1439
|
if (!sockPkgAlerts.length) {
|
|
1447
|
-
return alertsByPkgId
|
|
1440
|
+
return alertsByPkgId
|
|
1448
1441
|
}
|
|
1449
1442
|
if (consolidate) {
|
|
1450
|
-
const highestForCve = new Map()
|
|
1451
|
-
const highestForUpgrade = new Map()
|
|
1452
|
-
const unfixableAlerts = []
|
|
1443
|
+
const highestForCve = new Map()
|
|
1444
|
+
const highestForUpgrade = new Map()
|
|
1445
|
+
const unfixableAlerts = []
|
|
1453
1446
|
for (const sockPkgAlert of sockPkgAlerts) {
|
|
1454
|
-
const alert = sockPkgAlert.raw
|
|
1455
|
-
const fixType = alert.fix?.type ?? ''
|
|
1447
|
+
const alert = sockPkgAlert.raw
|
|
1448
|
+
const fixType = alert.fix?.type ?? ''
|
|
1456
1449
|
if (fixType === ALERT_FIX_TYPE.cve) {
|
|
1457
|
-
const patchedVersion =
|
|
1458
|
-
|
|
1459
|
-
const
|
|
1460
|
-
const
|
|
1450
|
+
const patchedVersion =
|
|
1451
|
+
alert.props[CVE_ALERT_PROPS_FIRST_PATCHED_VERSION_IDENTIFIER]
|
|
1452
|
+
const patchedMajor = semver.major(patchedVersion)
|
|
1453
|
+
const oldHighest = highestForCve.get(patchedMajor)
|
|
1454
|
+
const highest = oldHighest?.version ?? '0.0.0'
|
|
1461
1455
|
if (semver.gt(patchedVersion, highest)) {
|
|
1462
1456
|
highestForCve.set(patchedMajor, {
|
|
1463
1457
|
alert: sockPkgAlert,
|
|
1464
1458
|
version: patchedVersion
|
|
1465
|
-
})
|
|
1459
|
+
})
|
|
1466
1460
|
}
|
|
1467
1461
|
} else if (fixType === ALERT_FIX_TYPE.upgrade) {
|
|
1468
|
-
const oldHighest = highestForUpgrade.get(major)
|
|
1469
|
-
const highest = oldHighest?.version ?? '0.0.0'
|
|
1462
|
+
const oldHighest = highestForUpgrade.get(major)
|
|
1463
|
+
const highest = oldHighest?.version ?? '0.0.0'
|
|
1470
1464
|
if (semver.gt(version, highest)) {
|
|
1471
1465
|
highestForUpgrade.set(major, {
|
|
1472
1466
|
alert: sockPkgAlert,
|
|
1473
1467
|
version
|
|
1474
|
-
})
|
|
1468
|
+
})
|
|
1475
1469
|
}
|
|
1476
1470
|
} else {
|
|
1477
|
-
unfixableAlerts.push(sockPkgAlert)
|
|
1471
|
+
unfixableAlerts.push(sockPkgAlert)
|
|
1478
1472
|
}
|
|
1479
1473
|
}
|
|
1480
|
-
sockPkgAlerts = [
|
|
1474
|
+
sockPkgAlerts = [
|
|
1475
|
+
...unfixableAlerts,
|
|
1476
|
+
...[...highestForCve.values()].map(d => d.alert),
|
|
1477
|
+
...[...highestForUpgrade.values()].map(d => d.alert)
|
|
1478
|
+
]
|
|
1481
1479
|
}
|
|
1482
1480
|
if (sockPkgAlerts.length) {
|
|
1483
|
-
sockPkgAlerts.sort((a, b) => sorts.naturalCompare(a.type, b.type))
|
|
1484
|
-
alertsByPkgId.set(pkgId, sockPkgAlerts)
|
|
1481
|
+
sockPkgAlerts.sort((a, b) => sorts.naturalCompare(a.type, b.type))
|
|
1482
|
+
alertsByPkgId.set(pkgId, sockPkgAlerts)
|
|
1485
1483
|
}
|
|
1486
|
-
return alertsByPkgId
|
|
1484
|
+
return alertsByPkgId
|
|
1487
1485
|
}
|
|
1488
1486
|
function getCveInfoByAlertsMap(alertsMap, options) {
|
|
1489
1487
|
const exclude = {
|
|
1490
|
-
|
|
1488
|
+
upgradable: true,
|
|
1491
1489
|
...{
|
|
1492
1490
|
__proto__: null,
|
|
1493
1491
|
...options
|
|
1494
1492
|
}.exclude
|
|
1495
|
-
}
|
|
1496
|
-
let infoByPkg = null
|
|
1493
|
+
}
|
|
1494
|
+
let infoByPkg = null
|
|
1497
1495
|
for (const [pkgId, sockPkgAlerts] of alertsMap) {
|
|
1498
|
-
const purlObj = packageurlJs.PackageURL.fromString(`pkg:npm/${pkgId}`)
|
|
1499
|
-
const name = packages.resolvePackageName(purlObj)
|
|
1496
|
+
const purlObj = packageurlJs.PackageURL.fromString(`pkg:npm/${pkgId}`)
|
|
1497
|
+
const name = packages.resolvePackageName(purlObj)
|
|
1500
1498
|
for (const sockPkgAlert of sockPkgAlerts) {
|
|
1501
|
-
const alert = sockPkgAlert.raw
|
|
1502
|
-
if (
|
|
1503
|
-
|
|
1499
|
+
const alert = sockPkgAlert.raw
|
|
1500
|
+
if (
|
|
1501
|
+
alert.fix?.type !== ALERT_FIX_TYPE.cve ||
|
|
1502
|
+
(exclude.upgradable && registry.getManifestData(NPM$2, name))
|
|
1503
|
+
) {
|
|
1504
|
+
continue
|
|
1504
1505
|
}
|
|
1505
1506
|
if (!infoByPkg) {
|
|
1506
|
-
infoByPkg = new Map()
|
|
1507
|
+
infoByPkg = new Map()
|
|
1507
1508
|
}
|
|
1508
|
-
let infos = infoByPkg.get(name)
|
|
1509
|
+
let infos = infoByPkg.get(name)
|
|
1509
1510
|
if (!infos) {
|
|
1510
|
-
infos = []
|
|
1511
|
-
infoByPkg.set(name, infos)
|
|
1511
|
+
infos = []
|
|
1512
|
+
infoByPkg.set(name, infos)
|
|
1512
1513
|
}
|
|
1513
|
-
const {
|
|
1514
|
-
|
|
1515
|
-
vulnerableVersionRange
|
|
1516
|
-
} = alert.props;
|
|
1514
|
+
const { firstPatchedVersionIdentifier, vulnerableVersionRange } =
|
|
1515
|
+
alert.props
|
|
1517
1516
|
infos.push({
|
|
1518
1517
|
firstPatchedVersionIdentifier,
|
|
1519
|
-
vulnerableVersionRange: new semver.Range(
|
|
1520
|
-
|
|
1518
|
+
vulnerableVersionRange: new semver.Range(
|
|
1519
|
+
vulnerableVersionRange
|
|
1520
|
+
).format()
|
|
1521
|
+
})
|
|
1521
1522
|
}
|
|
1522
1523
|
}
|
|
1523
|
-
return infoByPkg
|
|
1524
|
+
return infoByPkg
|
|
1524
1525
|
}
|
|
1525
1526
|
function logAlertsMap(alertsMap, options) {
|
|
1526
|
-
const {
|
|
1527
|
-
output = process.stderr
|
|
1528
|
-
} = {
|
|
1527
|
+
const { hideAt = 'middle', output = process.stderr } = {
|
|
1529
1528
|
__proto__: null,
|
|
1530
1529
|
...options
|
|
1531
|
-
}
|
|
1532
|
-
const translations = getTranslations()
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1530
|
+
}
|
|
1531
|
+
const translations = getTranslations()
|
|
1532
|
+
const sortedEntries = [...alertsMap.entries()].sort(
|
|
1533
|
+
(a, b) => getAlertsSeverityOrder(a[1]) - getAlertsSeverityOrder(b[1])
|
|
1534
|
+
)
|
|
1535
|
+
const aboveTheFoldPkgIds = new Set()
|
|
1536
|
+
const viewableAlertsByPkgId = new Map()
|
|
1537
|
+
const hiddenAlertsByPkgId = new Map()
|
|
1538
|
+
for (let i = 0, { length } = sortedEntries; i < length; i += 1) {
|
|
1539
|
+
const { 0: pkgId, 1: alerts } = sortedEntries[i]
|
|
1540
|
+
const hiddenAlerts = []
|
|
1541
|
+
const viewableAlerts = alerts.filter(a => {
|
|
1542
|
+
const keep =
|
|
1543
|
+
a.blocked || getAlertSeverityOrder(a) < ALERT_SEVERITY_ORDER[hideAt]
|
|
1544
|
+
if (!keep) {
|
|
1545
|
+
hiddenAlerts.push(a)
|
|
1546
|
+
}
|
|
1547
|
+
return keep
|
|
1548
|
+
})
|
|
1549
|
+
if (hiddenAlerts.length) {
|
|
1550
|
+
hiddenAlertsByPkgId.set(pkgId, hiddenAlerts.sort(alertSeverityComparator))
|
|
1551
|
+
}
|
|
1552
|
+
if (!viewableAlerts.length) {
|
|
1553
|
+
continue
|
|
1554
|
+
}
|
|
1555
|
+
viewableAlerts.sort(alertSeverityComparator)
|
|
1556
|
+
viewableAlertsByPkgId.set(pkgId, viewableAlerts)
|
|
1557
|
+
if (
|
|
1558
|
+
viewableAlerts.find(
|
|
1559
|
+
a => a.blocked || getAlertSeverityOrder(a) < ALERT_SEVERITY_ORDER.middle
|
|
1560
|
+
)
|
|
1561
|
+
) {
|
|
1562
|
+
aboveTheFoldPkgIds.add(pkgId)
|
|
1563
|
+
}
|
|
1564
|
+
}
|
|
1565
|
+
|
|
1566
|
+
// If MIN_ABOVE_THE_FOLD_COUNT is NOT met add more from viewable pkg ids.
|
|
1567
|
+
for (const { 0: pkgId } of viewableAlertsByPkgId.entries()) {
|
|
1568
|
+
if (aboveTheFoldPkgIds.size >= MIN_ABOVE_THE_FOLD_COUNT) {
|
|
1569
|
+
break
|
|
1570
|
+
}
|
|
1571
|
+
aboveTheFoldPkgIds.add(pkgId)
|
|
1572
|
+
}
|
|
1573
|
+
// If MIN_ABOVE_THE_FOLD_COUNT is STILL NOT met add more from hidden pkg ids.
|
|
1574
|
+
for (const { 0: pkgId, 1: hiddenAlerts } of hiddenAlertsByPkgId.entries()) {
|
|
1575
|
+
if (aboveTheFoldPkgIds.size >= MIN_ABOVE_THE_FOLD_COUNT) {
|
|
1576
|
+
break
|
|
1577
|
+
}
|
|
1578
|
+
aboveTheFoldPkgIds.add(pkgId)
|
|
1579
|
+
const viewableAlerts = viewableAlertsByPkgId.get(pkgId) ?? []
|
|
1580
|
+
if (viewableAlerts.length < MIN_ABOVE_THE_FOLD_ALERT_COUNT) {
|
|
1581
|
+
const neededCount = MIN_ABOVE_THE_FOLD_ALERT_COUNT - viewableAlerts.length
|
|
1582
|
+
let removedHiddenAlerts
|
|
1583
|
+
if (hiddenAlerts.length - neededCount > 0) {
|
|
1584
|
+
removedHiddenAlerts = hiddenAlerts.splice(
|
|
1585
|
+
0,
|
|
1586
|
+
MIN_ABOVE_THE_FOLD_ALERT_COUNT
|
|
1587
|
+
)
|
|
1588
|
+
} else {
|
|
1589
|
+
removedHiddenAlerts = hiddenAlerts
|
|
1590
|
+
hiddenAlertsByPkgId.delete(pkgId)
|
|
1591
|
+
}
|
|
1592
|
+
viewableAlertsByPkgId.set(pkgId, [
|
|
1593
|
+
...viewableAlerts,
|
|
1594
|
+
...removedHiddenAlerts
|
|
1595
|
+
])
|
|
1596
|
+
}
|
|
1597
|
+
}
|
|
1598
|
+
const mentionedPkgIdsWithHiddenAlerts = new Set()
|
|
1599
|
+
for (
|
|
1600
|
+
let i = 0,
|
|
1601
|
+
prevAboveTheFold = true,
|
|
1602
|
+
entries = [...viewableAlertsByPkgId.entries()],
|
|
1603
|
+
{ length } = entries;
|
|
1604
|
+
i < length;
|
|
1605
|
+
i += 1
|
|
1606
|
+
) {
|
|
1607
|
+
const { 0: pkgId, 1: alerts } = entries[i]
|
|
1608
|
+
const lines = new Set()
|
|
1536
1609
|
for (const alert of alerts) {
|
|
1537
|
-
const {
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1610
|
+
const { type } = alert
|
|
1611
|
+
const severity = alert.raw.severity ?? ''
|
|
1612
|
+
const attributes = [
|
|
1613
|
+
...(severity
|
|
1614
|
+
? [colors[ALERT_SEVERITY_COLOR[severity]](getSeverityLabel(severity))]
|
|
1615
|
+
: []),
|
|
1616
|
+
...(alert.blocked ? [colors.bold(colors.red('blocked'))] : []),
|
|
1617
|
+
...(alert.fixable ? ['fixable'] : [])
|
|
1618
|
+
]
|
|
1619
|
+
const maybeAttributes = attributes.length
|
|
1620
|
+
? ` ${colors.italic(`(${attributes.join('; ')})`)}`
|
|
1621
|
+
: ''
|
|
1542
1622
|
// Based data from { pageProps: { alertTypes } } of:
|
|
1543
1623
|
// https://socket.dev/_next/data/94666139314b6437ee4491a0864e72b264547585/en-US.json
|
|
1544
|
-
const info = translations.alerts[type]
|
|
1545
|
-
const title = info?.title ?? type
|
|
1546
|
-
const maybeDesc = info?.description ? ` - ${info.description}` : ''
|
|
1624
|
+
const info = translations.alerts[type]
|
|
1625
|
+
const title = info?.title ?? type
|
|
1626
|
+
const maybeDesc = info?.description ? ` - ${info.description}` : ''
|
|
1627
|
+
const content = `${title}${maybeAttributes}${maybeDesc}`
|
|
1547
1628
|
// TODO: emoji seems to mis-align terminals sometimes
|
|
1548
|
-
lines.add(` ${
|
|
1629
|
+
lines.add(` ${content}`)
|
|
1630
|
+
}
|
|
1631
|
+
const purlObj = packageurlJs.PackageURL.fromString(`pkg:npm/${pkgId}`)
|
|
1632
|
+
const hyperlink = format.hyperlink(
|
|
1633
|
+
pkgId,
|
|
1634
|
+
getSocketDevPackageOverviewUrl(
|
|
1635
|
+
NPM$2,
|
|
1636
|
+
packages.resolvePackageName(purlObj),
|
|
1637
|
+
purlObj.version
|
|
1638
|
+
)
|
|
1639
|
+
)
|
|
1640
|
+
const isAboveTheFold = aboveTheFoldPkgIds.has(pkgId)
|
|
1641
|
+
if (isAboveTheFold) {
|
|
1642
|
+
aboveTheFoldPkgIds.add(pkgId)
|
|
1643
|
+
output.write(`${i ? '\n' : ''}${hyperlink}:\n`)
|
|
1644
|
+
} else {
|
|
1645
|
+
output.write(`${prevAboveTheFold ? '\n' : ''}${hyperlink}:\n`)
|
|
1549
1646
|
}
|
|
1550
|
-
output.write(`(socket) ${format.hyperlink(pkgId, getSocketDevPackageOverviewUrl(NPM$2, packages.resolvePackageName(purlObj), purlObj.version))} contains risks:\n`);
|
|
1551
1647
|
for (const line of lines) {
|
|
1552
|
-
output.write(`${line}\n`)
|
|
1648
|
+
output.write(`${line}\n`)
|
|
1649
|
+
}
|
|
1650
|
+
const hiddenAlerts = hiddenAlertsByPkgId.get(pkgId) ?? []
|
|
1651
|
+
const { length: hiddenAlertsCount } = hiddenAlerts
|
|
1652
|
+
if (hiddenAlertsCount) {
|
|
1653
|
+
mentionedPkgIdsWithHiddenAlerts.add(pkgId)
|
|
1654
|
+
if (hiddenAlertsCount === 1) {
|
|
1655
|
+
output.write(
|
|
1656
|
+
` ${colors.dim(`+1 Hidden ${getSeverityLabel(hiddenAlerts[0].raw.severity ?? 'low')} risk alert`)}\n`
|
|
1657
|
+
)
|
|
1658
|
+
} else {
|
|
1659
|
+
output.write(
|
|
1660
|
+
` ${colors.dim(`+${hiddenAlertsCount} Hidden alerts ${colors.italic(getHiddenRisksDescription(getHiddenRiskCounts(hiddenAlerts)))}`)}\n`
|
|
1661
|
+
)
|
|
1662
|
+
}
|
|
1553
1663
|
}
|
|
1664
|
+
prevAboveTheFold = isAboveTheFold
|
|
1554
1665
|
}
|
|
1666
|
+
const additionalHiddenCount =
|
|
1667
|
+
hiddenAlertsByPkgId.size - mentionedPkgIdsWithHiddenAlerts.size
|
|
1668
|
+
if (additionalHiddenCount) {
|
|
1669
|
+
const totalRiskCounts = {
|
|
1670
|
+
critical: 0,
|
|
1671
|
+
high: 0,
|
|
1672
|
+
middle: 0,
|
|
1673
|
+
low: 0
|
|
1674
|
+
}
|
|
1675
|
+
for (const { 0: pkgId, 1: alerts } of hiddenAlertsByPkgId.entries()) {
|
|
1676
|
+
if (mentionedPkgIdsWithHiddenAlerts.has(pkgId)) {
|
|
1677
|
+
continue
|
|
1678
|
+
}
|
|
1679
|
+
const riskCounts = getHiddenRiskCounts(alerts)
|
|
1680
|
+
totalRiskCounts.critical += riskCounts.critical
|
|
1681
|
+
totalRiskCounts.high += riskCounts.high
|
|
1682
|
+
totalRiskCounts.middle += riskCounts.middle
|
|
1683
|
+
totalRiskCounts.low += riskCounts.low
|
|
1684
|
+
}
|
|
1685
|
+
output.write(
|
|
1686
|
+
`${aboveTheFoldPkgIds.size ? '\n' : ''}${colors.dim(`${aboveTheFoldPkgIds.size ? '+' : ''}${additionalHiddenCount} Packages with hidden alerts ${colors.italic(getHiddenRisksDescription(totalRiskCounts))}`)}\n`
|
|
1687
|
+
)
|
|
1688
|
+
}
|
|
1689
|
+
output.write('\n')
|
|
1555
1690
|
}
|
|
1556
1691
|
|
|
1557
|
-
const {
|
|
1558
|
-
LOOP_SENTINEL,
|
|
1559
|
-
NPM: NPM$1,
|
|
1560
|
-
NPM_REGISTRY_URL
|
|
1561
|
-
} = constants;
|
|
1692
|
+
const { LOOP_SENTINEL, NPM: NPM$1, NPM_REGISTRY_URL } = constants
|
|
1562
1693
|
function getDetailsFromDiff(diff_, options) {
|
|
1563
|
-
const details = []
|
|
1694
|
+
const details = []
|
|
1564
1695
|
// `diff_` is `null` when `npm install --package-lock-only` is passed.
|
|
1565
1696
|
if (!diff_) {
|
|
1566
|
-
return details
|
|
1697
|
+
return details
|
|
1567
1698
|
}
|
|
1568
1699
|
const include = {
|
|
1569
1700
|
__proto__: null,
|
|
@@ -1573,255 +1704,285 @@ function getDetailsFromDiff(diff_, options) {
|
|
|
1573
1704
|
__proto__: null,
|
|
1574
1705
|
...options
|
|
1575
1706
|
}.include
|
|
1576
|
-
}
|
|
1577
|
-
const queue = [...diff_.children]
|
|
1578
|
-
let pos = 0
|
|
1579
|
-
let {
|
|
1580
|
-
length: queueLength
|
|
1581
|
-
} = queue;
|
|
1707
|
+
}
|
|
1708
|
+
const queue = [...diff_.children]
|
|
1709
|
+
let pos = 0
|
|
1710
|
+
let { length: queueLength } = queue
|
|
1582
1711
|
while (pos < queueLength) {
|
|
1583
1712
|
if (pos === LOOP_SENTINEL) {
|
|
1584
|
-
throw new Error('Detected infinite loop while walking Arborist diff')
|
|
1713
|
+
throw new Error('Detected infinite loop while walking Arborist diff')
|
|
1585
1714
|
}
|
|
1586
|
-
const diff = queue[pos++]
|
|
1587
|
-
const {
|
|
1588
|
-
action
|
|
1589
|
-
} = diff;
|
|
1715
|
+
const diff = queue[pos++]
|
|
1716
|
+
const { action } = diff
|
|
1590
1717
|
if (action) {
|
|
1591
1718
|
// The `pkgNode`, i.e. the `ideal` node, will be `undefined` if the diff
|
|
1592
1719
|
// action is 'REMOVE'
|
|
1593
1720
|
// The `oldNode`, i.e. the `actual` node, will be `undefined` if the diff
|
|
1594
1721
|
// action is 'ADD'.
|
|
1595
|
-
const {
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
} = diff;
|
|
1599
|
-
let existing;
|
|
1600
|
-
let keep = false;
|
|
1722
|
+
const { actual: oldNode, ideal: pkgNode } = diff
|
|
1723
|
+
let existing
|
|
1724
|
+
let keep = false
|
|
1601
1725
|
if (action === DiffAction.change) {
|
|
1602
1726
|
if (pkgNode?.package.version !== oldNode?.package.version) {
|
|
1603
|
-
keep = true
|
|
1604
|
-
if (
|
|
1605
|
-
|
|
1727
|
+
keep = true
|
|
1728
|
+
if (
|
|
1729
|
+
oldNode?.package.name &&
|
|
1730
|
+
oldNode.package.name === pkgNode?.package.name
|
|
1731
|
+
) {
|
|
1732
|
+
existing = oldNode
|
|
1606
1733
|
}
|
|
1607
1734
|
} else {
|
|
1608
|
-
debug.debugLog('SKIPPING META CHANGE ON', diff)
|
|
1735
|
+
debug.debugLog('SKIPPING META CHANGE ON', diff)
|
|
1609
1736
|
}
|
|
1610
1737
|
} else {
|
|
1611
|
-
keep = action !== DiffAction.remove
|
|
1738
|
+
keep = action !== DiffAction.remove
|
|
1612
1739
|
}
|
|
1613
1740
|
if (keep && pkgNode?.resolved && (!oldNode || oldNode.resolved)) {
|
|
1614
|
-
if (
|
|
1741
|
+
if (
|
|
1742
|
+
include.unknownOrigin ||
|
|
1743
|
+
getUrlOrigin(pkgNode.resolved) === NPM_REGISTRY_URL
|
|
1744
|
+
) {
|
|
1615
1745
|
details.push({
|
|
1616
1746
|
node: pkgNode,
|
|
1617
1747
|
existing
|
|
1618
|
-
})
|
|
1748
|
+
})
|
|
1619
1749
|
}
|
|
1620
1750
|
}
|
|
1621
1751
|
}
|
|
1622
1752
|
for (const child of diff.children) {
|
|
1623
|
-
queue[queueLength++] = child
|
|
1753
|
+
queue[queueLength++] = child
|
|
1624
1754
|
}
|
|
1625
1755
|
}
|
|
1626
1756
|
if (include.unchanged) {
|
|
1627
|
-
const {
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
if (include.unknownOrigin || getUrlOrigin(pkgNode.resolved) === NPM_REGISTRY_URL) {
|
|
1757
|
+
const { unchanged } = diff_
|
|
1758
|
+
for (let i = 0, { length } = unchanged; i < length; i += 1) {
|
|
1759
|
+
const pkgNode = unchanged[i]
|
|
1760
|
+
if (
|
|
1761
|
+
include.unknownOrigin ||
|
|
1762
|
+
getUrlOrigin(pkgNode.resolved) === NPM_REGISTRY_URL
|
|
1763
|
+
) {
|
|
1635
1764
|
details.push({
|
|
1636
1765
|
node: pkgNode,
|
|
1637
1766
|
existing: pkgNode
|
|
1638
|
-
})
|
|
1767
|
+
})
|
|
1639
1768
|
}
|
|
1640
1769
|
}
|
|
1641
1770
|
}
|
|
1642
|
-
return details
|
|
1771
|
+
return details
|
|
1643
1772
|
}
|
|
1644
1773
|
function getUrlOrigin(input) {
|
|
1645
1774
|
try {
|
|
1646
1775
|
// TODO: URL.parse is available in Node 22.1.0. We can use it when we drop Node 18.
|
|
1647
1776
|
// https://nodejs.org/docs/latest-v22.x/api/url.html#urlparseinput-base
|
|
1648
1777
|
// return URL.parse(input)?.origin ?? ''
|
|
1649
|
-
return new URL(input).origin ?? ''
|
|
1778
|
+
return new URL(input).origin ?? ''
|
|
1650
1779
|
} catch {}
|
|
1651
|
-
return ''
|
|
1780
|
+
return ''
|
|
1652
1781
|
}
|
|
1653
|
-
function findBestPatchVersion(
|
|
1654
|
-
|
|
1655
|
-
|
|
1782
|
+
function findBestPatchVersion(
|
|
1783
|
+
node,
|
|
1784
|
+
availableVersions,
|
|
1785
|
+
vulnerableVersionRange,
|
|
1786
|
+
_firstPatchedVersionIdentifier
|
|
1787
|
+
) {
|
|
1788
|
+
const manifestData = registry.getManifestData(NPM$1, node.name)
|
|
1789
|
+
let eligibleVersions
|
|
1656
1790
|
if (manifestData && manifestData.name === manifestData.package) {
|
|
1657
|
-
const major = semver.major(manifestData.version)
|
|
1658
|
-
eligibleVersions = availableVersions.filter(v => semver.major(v) === major)
|
|
1791
|
+
const major = semver.major(manifestData.version)
|
|
1792
|
+
eligibleVersions = availableVersions.filter(v => semver.major(v) === major)
|
|
1659
1793
|
} else {
|
|
1660
|
-
const major = semver.major(node.version)
|
|
1661
|
-
eligibleVersions = availableVersions.filter(
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1794
|
+
const major = semver.major(node.version)
|
|
1795
|
+
eligibleVersions = availableVersions.filter(
|
|
1796
|
+
v =>
|
|
1797
|
+
// Filter for versions that are within the current major version and
|
|
1798
|
+
// are NOT in the vulnerable range.
|
|
1799
|
+
semver.major(v) === major &&
|
|
1800
|
+
(!vulnerableVersionRange ||
|
|
1801
|
+
!semver.satisfies(v, vulnerableVersionRange))
|
|
1802
|
+
)
|
|
1803
|
+
}
|
|
1804
|
+
return semver.maxSatisfying(eligibleVersions, '*')
|
|
1667
1805
|
}
|
|
1668
1806
|
function findPackageNodes(tree, packageName) {
|
|
1669
|
-
const queue = [
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1807
|
+
const queue = [
|
|
1808
|
+
{
|
|
1809
|
+
node: tree
|
|
1810
|
+
}
|
|
1811
|
+
]
|
|
1812
|
+
const matches = []
|
|
1813
|
+
let sentinel = 0
|
|
1674
1814
|
while (queue.length) {
|
|
1675
1815
|
if (sentinel++ === LOOP_SENTINEL) {
|
|
1676
|
-
throw new Error('Detected infinite loop in findPackageNodes')
|
|
1816
|
+
throw new Error('Detected infinite loop in findPackageNodes')
|
|
1677
1817
|
}
|
|
1678
|
-
const {
|
|
1679
|
-
|
|
1680
|
-
} = queue.pop();
|
|
1681
|
-
const node = currentNode.children.get(packageName);
|
|
1818
|
+
const { node: currentNode } = queue.pop()
|
|
1819
|
+
const node = currentNode.children.get(packageName)
|
|
1682
1820
|
if (node) {
|
|
1683
|
-
matches.push(node)
|
|
1821
|
+
matches.push(node)
|
|
1684
1822
|
}
|
|
1685
|
-
const children = [...currentNode.children.values()]
|
|
1823
|
+
const children = [...currentNode.children.values()]
|
|
1686
1824
|
for (let i = children.length - 1; i >= 0; i -= 1) {
|
|
1687
1825
|
queue.push({
|
|
1688
1826
|
node: children[i]
|
|
1689
|
-
})
|
|
1827
|
+
})
|
|
1690
1828
|
}
|
|
1691
1829
|
}
|
|
1692
|
-
return matches
|
|
1830
|
+
return matches
|
|
1693
1831
|
}
|
|
1694
1832
|
async function getAlertsMapFromArborist(arb, options) {
|
|
1695
|
-
const {
|
|
1696
|
-
include: _include,
|
|
1697
|
-
spinner
|
|
1698
|
-
} = {
|
|
1833
|
+
const { include: _include, spinner } = {
|
|
1699
1834
|
__proto__: null,
|
|
1700
1835
|
...options
|
|
1701
|
-
}
|
|
1836
|
+
}
|
|
1702
1837
|
const include = {
|
|
1703
1838
|
__proto__: null,
|
|
1839
|
+
blocked: true,
|
|
1840
|
+
critical: true,
|
|
1841
|
+
cve: true,
|
|
1704
1842
|
existing: false,
|
|
1705
1843
|
unfixable: true,
|
|
1844
|
+
upgradable: false,
|
|
1706
1845
|
..._include
|
|
1707
|
-
}
|
|
1846
|
+
}
|
|
1708
1847
|
const needInfoOn = getDetailsFromDiff(arb.diff, {
|
|
1709
1848
|
include: {
|
|
1710
1849
|
unchanged: include.existing
|
|
1711
1850
|
}
|
|
1712
|
-
})
|
|
1713
|
-
const pkgIds = arrays.arrayUnique(needInfoOn.map(d => d.node.pkgid))
|
|
1714
|
-
let {
|
|
1715
|
-
|
|
1716
|
-
} = pkgIds;
|
|
1717
|
-
const alertsByPkgId = new Map();
|
|
1851
|
+
})
|
|
1852
|
+
const pkgIds = arrays.arrayUnique(needInfoOn.map(d => d.node.pkgid))
|
|
1853
|
+
let { length: remaining } = pkgIds
|
|
1854
|
+
const alertsByPkgId = new Map()
|
|
1718
1855
|
if (!remaining) {
|
|
1719
|
-
return alertsByPkgId
|
|
1720
|
-
}
|
|
1721
|
-
const getText = () => `Looking up data for ${remaining} packages
|
|
1722
|
-
spinner?.start(getText())
|
|
1723
|
-
let overrides
|
|
1724
|
-
const overridesMap = (
|
|
1856
|
+
return alertsByPkgId
|
|
1857
|
+
}
|
|
1858
|
+
const getText = () => `Looking up data for ${remaining} packages`
|
|
1859
|
+
spinner?.start(getText())
|
|
1860
|
+
let overrides
|
|
1861
|
+
const overridesMap = (
|
|
1862
|
+
arb.actualTree ??
|
|
1863
|
+
arb.idealTree ??
|
|
1864
|
+
(await arb.loadActual())
|
|
1865
|
+
)?.overrides?.children
|
|
1725
1866
|
if (overridesMap) {
|
|
1726
|
-
overrides = Object.fromEntries(
|
|
1727
|
-
|
|
1728
|
-
|
|
1867
|
+
overrides = Object.fromEntries(
|
|
1868
|
+
[...overridesMap.entries()].map(([key, overrideSet]) => {
|
|
1869
|
+
return [key, overrideSet.value]
|
|
1870
|
+
})
|
|
1871
|
+
)
|
|
1729
1872
|
}
|
|
1730
|
-
const sockSdk = await setupSdk(getPublicToken())
|
|
1873
|
+
const sockSdk = await setupSdk(getPublicToken())
|
|
1731
1874
|
const toAlertsMapOptions = {
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1875
|
+
...options,
|
|
1876
|
+
include,
|
|
1877
|
+
overrides
|
|
1878
|
+
}
|
|
1879
|
+
for await (const batchPackageFetchResult of sockSdk.batchPackageStream(
|
|
1880
|
+
{
|
|
1881
|
+
alerts: 'true',
|
|
1882
|
+
compact: 'true',
|
|
1883
|
+
fixable: include.unfixable ? 'false' : 'true'
|
|
1884
|
+
},
|
|
1885
|
+
{
|
|
1886
|
+
components: pkgIds.map(id => ({
|
|
1887
|
+
purl: `pkg:npm/${id}`
|
|
1888
|
+
}))
|
|
1889
|
+
}
|
|
1890
|
+
)) {
|
|
1744
1891
|
if (batchPackageFetchResult.success) {
|
|
1745
|
-
await addArtifactToAlertsMap(
|
|
1892
|
+
await addArtifactToAlertsMap(
|
|
1893
|
+
batchPackageFetchResult.data,
|
|
1894
|
+
alertsByPkgId,
|
|
1895
|
+
toAlertsMapOptions
|
|
1896
|
+
)
|
|
1746
1897
|
}
|
|
1747
|
-
remaining -= 1
|
|
1898
|
+
remaining -= 1
|
|
1748
1899
|
if (spinner && remaining > 0) {
|
|
1749
|
-
spinner.start()
|
|
1750
|
-
spinner.setText(getText())
|
|
1900
|
+
spinner.start()
|
|
1901
|
+
spinner.setText(getText())
|
|
1751
1902
|
}
|
|
1752
1903
|
}
|
|
1753
|
-
spinner?.stop()
|
|
1754
|
-
return alertsByPkgId
|
|
1904
|
+
spinner?.stop()
|
|
1905
|
+
return alertsByPkgId
|
|
1755
1906
|
}
|
|
1756
|
-
function updateNode(
|
|
1757
|
-
|
|
1907
|
+
function updateNode(
|
|
1908
|
+
node,
|
|
1909
|
+
packument,
|
|
1910
|
+
vulnerableVersionRange,
|
|
1911
|
+
firstPatchedVersionIdentifier
|
|
1912
|
+
) {
|
|
1913
|
+
const availableVersions = Object.keys(packument.versions)
|
|
1758
1914
|
// Find the highest non-vulnerable version within the same major range
|
|
1759
|
-
const targetVersion = findBestPatchVersion(
|
|
1760
|
-
|
|
1915
|
+
const targetVersion = findBestPatchVersion(
|
|
1916
|
+
node,
|
|
1917
|
+
availableVersions,
|
|
1918
|
+
vulnerableVersionRange
|
|
1919
|
+
)
|
|
1920
|
+
const targetPackument = targetVersion
|
|
1921
|
+
? packument.versions[targetVersion]
|
|
1922
|
+
: undefined
|
|
1761
1923
|
// Check !targetVersion to make TypeScript happy.
|
|
1762
1924
|
if (!targetVersion || !targetPackument) {
|
|
1763
1925
|
// No suitable patch version found.
|
|
1764
|
-
return false
|
|
1926
|
+
return false
|
|
1765
1927
|
}
|
|
1766
1928
|
// Use Object.defineProperty to override the version.
|
|
1767
1929
|
Object.defineProperty(node, 'version', {
|
|
1768
1930
|
configurable: true,
|
|
1769
1931
|
enumerable: true,
|
|
1770
1932
|
get: () => targetVersion
|
|
1771
|
-
})
|
|
1772
|
-
node.package.version = targetVersion
|
|
1933
|
+
})
|
|
1934
|
+
node.package.version = targetVersion
|
|
1773
1935
|
// Update resolved and clear integrity for the new version.
|
|
1774
|
-
const purlObj = packageurlJs.PackageURL.fromString(`pkg:npm/${node.name}`)
|
|
1775
|
-
node.resolved = `${NPM_REGISTRY_URL}/${node.name}/-/${purlObj.name}-${targetVersion}.tgz
|
|
1776
|
-
const {
|
|
1777
|
-
integrity
|
|
1778
|
-
} = targetPackument.dist;
|
|
1936
|
+
const purlObj = packageurlJs.PackageURL.fromString(`pkg:npm/${node.name}`)
|
|
1937
|
+
node.resolved = `${NPM_REGISTRY_URL}/${node.name}/-/${purlObj.name}-${targetVersion}.tgz`
|
|
1938
|
+
const { integrity } = targetPackument.dist
|
|
1779
1939
|
if (integrity) {
|
|
1780
|
-
node.integrity = integrity
|
|
1940
|
+
node.integrity = integrity
|
|
1781
1941
|
} else {
|
|
1782
|
-
delete node.integrity
|
|
1942
|
+
delete node.integrity
|
|
1783
1943
|
}
|
|
1784
1944
|
if ('deprecated' in targetPackument) {
|
|
1785
|
-
node.package['deprecated'] = targetPackument.deprecated
|
|
1945
|
+
node.package['deprecated'] = targetPackument.deprecated
|
|
1786
1946
|
} else {
|
|
1787
|
-
delete node.package['deprecated']
|
|
1947
|
+
delete node.package['deprecated']
|
|
1788
1948
|
}
|
|
1789
1949
|
const newDeps = {
|
|
1790
1950
|
...targetPackument.dependencies
|
|
1791
|
-
}
|
|
1792
|
-
const {
|
|
1793
|
-
|
|
1794
|
-
} = node.package;
|
|
1795
|
-
node.package.dependencies = newDeps;
|
|
1951
|
+
}
|
|
1952
|
+
const { dependencies: oldDeps } = node.package
|
|
1953
|
+
node.package.dependencies = newDeps
|
|
1796
1954
|
if (oldDeps) {
|
|
1797
1955
|
for (const oldDepName of Object.keys(oldDeps)) {
|
|
1798
1956
|
if (!objects.hasOwn(newDeps, oldDepName)) {
|
|
1799
|
-
node.edgesOut.get(oldDepName)?.detach()
|
|
1957
|
+
node.edgesOut.get(oldDepName)?.detach()
|
|
1800
1958
|
}
|
|
1801
1959
|
}
|
|
1802
1960
|
}
|
|
1803
1961
|
for (const newDepName of Object.keys(newDeps)) {
|
|
1804
1962
|
if (!objects.hasOwn(oldDeps, newDepName)) {
|
|
1805
|
-
node.addEdgeOut(
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1963
|
+
node.addEdgeOut(
|
|
1964
|
+
new Edge({
|
|
1965
|
+
from: node,
|
|
1966
|
+
name: newDepName,
|
|
1967
|
+
spec: newDeps[newDepName],
|
|
1968
|
+
type: 'prod'
|
|
1969
|
+
})
|
|
1970
|
+
)
|
|
1811
1971
|
}
|
|
1812
1972
|
}
|
|
1813
|
-
return true
|
|
1973
|
+
return true
|
|
1814
1974
|
}
|
|
1815
1975
|
|
|
1816
1976
|
const {
|
|
1817
1977
|
NPM,
|
|
1818
1978
|
NPX,
|
|
1819
|
-
|
|
1979
|
+
SOCKET_CLI_ACCEPT_RISKS,
|
|
1980
|
+
SOCKET_CLI_SAFE_BIN,
|
|
1981
|
+
SOCKET_CLI_SAFE_PROGRESS,
|
|
1982
|
+
SOCKET_CLI_VIEW_ALL_RISKS,
|
|
1820
1983
|
kInternalsSymbol,
|
|
1821
|
-
[kInternalsSymbol]: {
|
|
1822
|
-
|
|
1823
|
-
}
|
|
1824
|
-
} = constants;
|
|
1984
|
+
[kInternalsSymbol]: { getIpc }
|
|
1985
|
+
} = constants
|
|
1825
1986
|
const SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES = {
|
|
1826
1987
|
__proto__: null,
|
|
1827
1988
|
audit: false,
|
|
@@ -1832,34 +1993,44 @@ const SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES = {
|
|
|
1832
1993
|
save: false,
|
|
1833
1994
|
saveBundle: false,
|
|
1834
1995
|
silent: true
|
|
1835
|
-
}
|
|
1836
|
-
const kCtorArgs = Symbol('ctorArgs')
|
|
1837
|
-
const kRiskyReify = Symbol('riskyReify')
|
|
1838
|
-
const Arborist = require(shadowNpmPaths.getArboristClassPath())
|
|
1996
|
+
}
|
|
1997
|
+
const kCtorArgs = Symbol('ctorArgs')
|
|
1998
|
+
const kRiskyReify = Symbol('riskyReify')
|
|
1999
|
+
const Arborist = require(shadowNpmPaths.getArboristClassPath())
|
|
1839
2000
|
|
|
1840
2001
|
// Implementation code not related to our custom behavior is based on
|
|
1841
2002
|
// https://github.com/npm/cli/blob/v11.0.0/workspaces/arborist/lib/arborist/index.js:
|
|
1842
2003
|
class SafeArborist extends Arborist {
|
|
1843
2004
|
constructor(...ctorArgs) {
|
|
1844
|
-
super(
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
2005
|
+
super(
|
|
2006
|
+
{
|
|
2007
|
+
path:
|
|
2008
|
+
(ctorArgs.length ? ctorArgs[0]?.path : undefined) ?? process$1.cwd(),
|
|
2009
|
+
...(ctorArgs.length ? ctorArgs[0] : undefined),
|
|
2010
|
+
...SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES
|
|
2011
|
+
},
|
|
2012
|
+
...ctorArgs.slice(1)
|
|
2013
|
+
)
|
|
2014
|
+
this[kCtorArgs] = ctorArgs
|
|
1850
2015
|
}
|
|
1851
2016
|
async [kRiskyReify](...args) {
|
|
1852
|
-
const ctorArgs = this[kCtorArgs]
|
|
1853
|
-
const arb = new Arborist(
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
...(
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
2017
|
+
const ctorArgs = this[kCtorArgs]
|
|
2018
|
+
const arb = new Arborist(
|
|
2019
|
+
{
|
|
2020
|
+
...(ctorArgs.length ? ctorArgs[0] : undefined),
|
|
2021
|
+
progress: false
|
|
2022
|
+
},
|
|
2023
|
+
...ctorArgs.slice(1)
|
|
2024
|
+
)
|
|
2025
|
+
const ret = await arb.reify(
|
|
2026
|
+
{
|
|
2027
|
+
...(args.length ? args[0] : undefined),
|
|
2028
|
+
progress: false
|
|
2029
|
+
},
|
|
2030
|
+
...args.slice(1)
|
|
2031
|
+
)
|
|
2032
|
+
Object.assign(this, arb)
|
|
2033
|
+
return ret
|
|
1863
2034
|
}
|
|
1864
2035
|
|
|
1865
2036
|
// @ts-ignore Incorrectly typed.
|
|
@@ -1867,97 +2038,119 @@ class SafeArborist extends Arborist {
|
|
|
1867
2038
|
const options = {
|
|
1868
2039
|
__proto__: null,
|
|
1869
2040
|
...(args.length ? args[0] : undefined)
|
|
1870
|
-
};
|
|
1871
|
-
const safeWrapperName = options.dryRun ? undefined : await getIpc(SOCKET_CLI_SAFE_WRAPPER);
|
|
1872
|
-
const isSafeNpm = safeWrapperName === NPM;
|
|
1873
|
-
const isSafeNpx = safeWrapperName === NPX;
|
|
1874
|
-
if (!safeWrapperName || isSafeNpx && options['yes']) {
|
|
1875
|
-
return await this[kRiskyReify](...args);
|
|
1876
2041
|
}
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
}
|
|
1882
|
-
await super.reify(
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
2042
|
+
const ipc = await getIpc()
|
|
2043
|
+
const binName = ipc[SOCKET_CLI_SAFE_BIN]
|
|
2044
|
+
if (!binName) {
|
|
2045
|
+
return await this[kRiskyReify](...args)
|
|
2046
|
+
}
|
|
2047
|
+
await super.reify(
|
|
2048
|
+
{
|
|
2049
|
+
...options,
|
|
2050
|
+
...SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES,
|
|
2051
|
+
progress: false
|
|
2052
|
+
},
|
|
2053
|
+
// @ts-ignore: TS gets grumpy about rest parameters.
|
|
2054
|
+
...args.slice(1)
|
|
2055
|
+
)
|
|
2056
|
+
const progress = ipc[SOCKET_CLI_SAFE_PROGRESS]
|
|
2057
|
+
const spinner =
|
|
2058
|
+
options['silent'] || !progress
|
|
2059
|
+
? undefined
|
|
2060
|
+
: // Lazily access constants.spinner.
|
|
2061
|
+
constants.spinner
|
|
2062
|
+
const isSafeNpm = binName === NPM
|
|
2063
|
+
const isSafeNpx = binName === NPX
|
|
1889
2064
|
const alertsMap = await getAlertsMapFromArborist(this, {
|
|
1890
2065
|
spinner,
|
|
1891
|
-
include:
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
2066
|
+
include:
|
|
2067
|
+
options.dryRun ||
|
|
2068
|
+
options['yes'] ||
|
|
2069
|
+
// Lazily access constants.ENV[SOCKET_CLI_ACCEPT_RISKS].
|
|
2070
|
+
constants.ENV[SOCKET_CLI_ACCEPT_RISKS]
|
|
2071
|
+
? {
|
|
2072
|
+
blocked: true,
|
|
2073
|
+
critical: false,
|
|
2074
|
+
cve: false,
|
|
2075
|
+
unfixable: false
|
|
2076
|
+
}
|
|
2077
|
+
: {
|
|
2078
|
+
existing: isSafeNpx,
|
|
2079
|
+
unfixable: isSafeNpm
|
|
2080
|
+
}
|
|
2081
|
+
})
|
|
1896
2082
|
if (alertsMap.size) {
|
|
2083
|
+
process$1.exitCode = 1
|
|
1897
2084
|
logAlertsMap(alertsMap, {
|
|
2085
|
+
// Lazily access constants.ENV[SOCKET_CLI_VIEW_ALL_RISKS].
|
|
2086
|
+
hideAt: constants.ENV[SOCKET_CLI_VIEW_ALL_RISKS] ? 'none' : 'middle',
|
|
1898
2087
|
output: process$1.stderr
|
|
1899
|
-
})
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
2088
|
+
})
|
|
2089
|
+
throw new Error(commonTags.stripIndents`
|
|
2090
|
+
Socket ${binName} exiting due to risks.
|
|
2091
|
+
View all risks - Rerun with environment variable ${SOCKET_CLI_VIEW_ALL_RISKS}=1.
|
|
2092
|
+
Accept risks - Rerun with environment variable ${SOCKET_CLI_ACCEPT_RISKS}=1.
|
|
2093
|
+
`)
|
|
2094
|
+
} else if (!options['silent']) {
|
|
2095
|
+
logger.logger.success(`Socket ${binName} found no risks!`)
|
|
2096
|
+
if (binName === NPX) {
|
|
2097
|
+
logger.logger.log(`Running ${options.add[0]}`)
|
|
1905
2098
|
}
|
|
1906
|
-
} else {
|
|
1907
|
-
logger.logger.success('Socket npm found no risks!');
|
|
1908
2099
|
}
|
|
1909
|
-
return await this[kRiskyReify](...args)
|
|
2100
|
+
return await this[kRiskyReify](...args)
|
|
1910
2101
|
}
|
|
1911
2102
|
}
|
|
1912
2103
|
|
|
1913
2104
|
function installSafeArborist() {
|
|
1914
2105
|
// Override '@npmcli/arborist' module exports with patched variants based on
|
|
1915
2106
|
// https://github.com/npm/cli/pull/8089.
|
|
1916
|
-
const cache = require.cache
|
|
2107
|
+
const cache = require.cache
|
|
1917
2108
|
cache[shadowNpmPaths.getArboristClassPath()] = {
|
|
1918
2109
|
exports: SafeArborist
|
|
1919
|
-
}
|
|
2110
|
+
}
|
|
1920
2111
|
cache[shadowNpmPaths.getArboristEdgeClassPath()] = {
|
|
1921
2112
|
exports: SafeEdge
|
|
1922
|
-
}
|
|
2113
|
+
}
|
|
1923
2114
|
cache[shadowNpmPaths.getArboristNodeClassPath()] = {
|
|
1924
2115
|
exports: SafeNode
|
|
1925
|
-
}
|
|
2116
|
+
}
|
|
1926
2117
|
cache[shadowNpmPaths.getArboristOverrideSetClassPath()] = {
|
|
1927
2118
|
exports: SafeOverrideSet
|
|
1928
|
-
}
|
|
2119
|
+
}
|
|
1929
2120
|
}
|
|
1930
2121
|
|
|
1931
|
-
installSafeArborist()
|
|
2122
|
+
installSafeArborist()
|
|
1932
2123
|
|
|
1933
|
-
exports.ALERT_SEVERITY = ALERT_SEVERITY
|
|
1934
|
-
exports.Arborist = Arborist
|
|
1935
|
-
exports.AuthError = AuthError
|
|
1936
|
-
exports.ColorOrMarkdown = ColorOrMarkdown
|
|
1937
|
-
exports.InputError = InputError
|
|
1938
|
-
exports.SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES =
|
|
1939
|
-
|
|
1940
|
-
exports.
|
|
1941
|
-
exports.
|
|
1942
|
-
exports.
|
|
1943
|
-
exports.
|
|
1944
|
-
exports.
|
|
1945
|
-
exports.
|
|
1946
|
-
exports.
|
|
1947
|
-
exports.
|
|
1948
|
-
exports.
|
|
1949
|
-
exports.
|
|
1950
|
-
exports.
|
|
1951
|
-
exports.
|
|
1952
|
-
exports.
|
|
1953
|
-
exports.
|
|
1954
|
-
exports.
|
|
1955
|
-
exports.
|
|
1956
|
-
exports.
|
|
1957
|
-
exports.
|
|
1958
|
-
exports.
|
|
1959
|
-
exports.
|
|
1960
|
-
exports.
|
|
1961
|
-
exports.
|
|
1962
|
-
|
|
2124
|
+
exports.ALERT_SEVERITY = ALERT_SEVERITY
|
|
2125
|
+
exports.Arborist = Arborist
|
|
2126
|
+
exports.AuthError = AuthError
|
|
2127
|
+
exports.ColorOrMarkdown = ColorOrMarkdown
|
|
2128
|
+
exports.InputError = InputError
|
|
2129
|
+
exports.SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES =
|
|
2130
|
+
SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES
|
|
2131
|
+
exports.SafeArborist = SafeArborist
|
|
2132
|
+
exports.addArtifactToAlertsMap = addArtifactToAlertsMap
|
|
2133
|
+
exports.captureException = captureException
|
|
2134
|
+
exports.findBestPatchVersion = findBestPatchVersion
|
|
2135
|
+
exports.findPackageNodes = findPackageNodes
|
|
2136
|
+
exports.findUp = findUp
|
|
2137
|
+
exports.formatSeverityCount = formatSeverityCount
|
|
2138
|
+
exports.getAlertsMapFromArborist = getAlertsMapFromArborist
|
|
2139
|
+
exports.getConfigValue = getConfigValue
|
|
2140
|
+
exports.getCveInfoByAlertsMap = getCveInfoByAlertsMap
|
|
2141
|
+
exports.getDefaultToken = getDefaultToken
|
|
2142
|
+
exports.getPublicToken = getPublicToken
|
|
2143
|
+
exports.getSeverityCount = getSeverityCount
|
|
2144
|
+
exports.getSocketDevAlertUrl = getSocketDevAlertUrl
|
|
2145
|
+
exports.getSocketDevPackageOverviewUrl = getSocketDevPackageOverviewUrl
|
|
2146
|
+
exports.overrideCachedConfig = overrideCachedConfig
|
|
2147
|
+
exports.readFileBinary = readFileBinary
|
|
2148
|
+
exports.readFileUtf8 = readFileUtf8
|
|
2149
|
+
exports.safeReadFile = safeReadFile
|
|
2150
|
+
exports.sensitiveConfigKeys = sensitiveConfigKeys
|
|
2151
|
+
exports.setupSdk = setupSdk
|
|
2152
|
+
exports.supportedConfigKeys = supportedConfigKeys
|
|
2153
|
+
exports.updateConfigValue = updateConfigValue
|
|
2154
|
+
exports.updateNode = updateNode
|
|
2155
|
+
//# debugId=c4cc0383-a1f3-4096-bddd-173589820ed1
|
|
1963
2156
|
//# sourceMappingURL=shadow-npm-inject.js.map
|