Skip to content

Commit b5fa690

Browse files
authored
Merge branch 'main' into action-cmd
Signed-off-by: typicode <[email protected]>
2 parents 9dce0bd + 427d928 commit b5fa690

File tree

5 files changed

+107
-72
lines changed

5 files changed

+107
-72
lines changed

.dep-stats.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"@inquirer/prompts": "^7.1.0",
66
"@npmcli/promise-spawn": "^8.0.2",
77
"@socketsecurity/config": "^2.1.3",
8-
"@socketsecurity/registry": "^1.0.33",
8+
"@socketsecurity/registry": "^1.0.35",
99
"@socketsecurity/sdk": "^1.3.0",
1010
"blessed": "^0.1.81",
1111
"blessed-contrib": "^4.11.0",

eslint.config.js

Lines changed: 46 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ const sharedRules = {
4141
}
4242

4343
const sharedRulesForImportX = {
44+
...origImportXFlatConfigs.recommended.rules,
4445
'import-x/order': [
4546
'warn',
4647
{
@@ -66,35 +67,38 @@ const sharedRulesForImportX = {
6667
]
6768
}
6869

69-
const getImportXFlatConfigs = isEsm => ({
70-
recommended: {
71-
...origImportXFlatConfigs.recommended,
72-
languageOptions: {
73-
...origImportXFlatConfigs.recommended.languageOptions,
74-
ecmaVersion: LATEST,
75-
sourceType: isEsm ? 'module' : 'script'
70+
function getImportXFlatConfigs(isEsm) {
71+
return {
72+
recommended: {
73+
...origImportXFlatConfigs.recommended,
74+
languageOptions: {
75+
...origImportXFlatConfigs.recommended.languageOptions,
76+
ecmaVersion: LATEST,
77+
sourceType: isEsm ? 'module' : 'script'
78+
},
79+
rules: {
80+
...sharedRulesForImportX,
81+
'import-x/no-named-as-default-member': 'off'
82+
}
7683
},
77-
rules: {
78-
...origImportXFlatConfigs.recommended.rules,
79-
...sharedRulesForImportX,
80-
'import-x/no-named-as-default-member': 'off'
81-
}
82-
},
83-
typescript: {
84-
...origImportXFlatConfigs.typescript,
85-
settings: {
86-
...origImportXFlatConfigs.typescript.settings,
87-
'import-x/resolver-next': [
88-
createOxcImportResolver({
89-
tsConfig: {
90-
configFile: rootTsConfigPath,
91-
references: 'auto'
92-
}
93-
})
94-
]
84+
typescript: {
85+
...origImportXFlatConfigs.typescript,
86+
plugins: origImportXFlatConfigs.recommended.plugins,
87+
settings: {
88+
...origImportXFlatConfigs.typescript.settings,
89+
...sharedRulesForImportX,
90+
'import-x/resolver-next': [
91+
createOxcImportResolver({
92+
tsConfig: {
93+
configFile: rootTsConfigPath,
94+
references: 'auto'
95+
}
96+
})
97+
]
98+
}
9599
}
96100
}
97-
})
101+
}
98102

99103
const importFlatConfigsForScript = getImportXFlatConfigs(false)
100104
const importFlatConfigsForModule = getImportXFlatConfigs(true)
@@ -126,13 +130,13 @@ module.exports = [
126130
}
127131
}
128132
},
133+
linterOptions: {
134+
reportUnusedDisableDirectives: 'off'
135+
},
129136
plugins: {
130137
...sharedPlugins,
131138
'@typescript-eslint': tsEslint.plugin
132139
},
133-
linterOptions: {
134-
reportUnusedDisableDirectives: 'off'
135-
},
136140
rules: {
137141
...sharedRules,
138142
// Define @typescript-eslint/no-extraneous-class because oxlint defines
@@ -167,17 +171,10 @@ module.exports = [
167171
}
168172
},
169173
{
170-
files: ['scripts/**/*.js', 'test/**/*.cjs'],
171-
...nodePlugin.configs['flat/recommended-script']
172-
},
173-
{
174-
files: ['scripts/**/*.js', 'test/**/*.cjs'],
175-
plugins: {
176-
...sharedPlugins
177-
},
174+
files: ['scripts/**/*.{c,}js', 'test/**/*.{c,}js'],
175+
...nodePlugin.configs['flat/recommended-script'],
178176
rules: {
179-
...js.configs.recommended.rules,
180-
...sharedRules,
177+
...nodePlugin.configs['flat/recommended-script'].rules,
181178
'n/exports-style': ['error', 'module.exports'],
182179
// The n/no-unpublished-bin rule does does not support non-trivial glob
183180
// patterns used in package.json "files" fields. In those cases we simplify
@@ -199,5 +196,15 @@ module.exports = [
199196
{ argsIgnorePattern: '^_|^this$', ignoreRestSiblings: true }
200197
]
201198
}
199+
},
200+
{
201+
files: ['scripts/**/*.{c,}js', 'test/**/*.{c,}js'],
202+
plugins: {
203+
...sharedPlugins
204+
},
205+
rules: {
206+
...js.configs.recommended.rules,
207+
...sharedRules
208+
}
202209
}
203210
]

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@
7878
"@inquirer/prompts": "^7.1.0",
7979
"@npmcli/promise-spawn": "^8.0.2",
8080
"@socketsecurity/config": "^2.1.3",
81-
"@socketsecurity/registry": "^1.0.33",
81+
"@socketsecurity/registry": "^1.0.35",
8282
"@socketsecurity/sdk": "^1.3.0",
8383
"blessed": "^0.1.81",
8484
"blessed-contrib": "^4.11.0",

src/shadow/arborist.ts

Lines changed: 55 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,17 @@ const kRiskyReify = Symbol('riskyReify')
248248
const formatter = new ColorOrMarkdown(false)
249249
const pubToken = getDefaultKey() ?? FREE_API_KEY
250250

251+
type BatchIssue = {
252+
type: string
253+
value: {
254+
severity: string
255+
category: string
256+
locations: ({ [key: string]: any })[]
257+
label: string
258+
description: string
259+
props: { [key: string]: any }
260+
}
261+
}
251262
type IssueUXLookup = ReturnType<typeof createIssueUXLookup>
252263
type IssueUXLookupSettings = Parameters<IssueUXLookup>[0]
253264
type IssueUXLookupResult = ReturnType<IssueUXLookup>
@@ -271,7 +282,12 @@ async function* batchScan(
271282
): AsyncGenerator<
272283
{ eco: string; pkg: string; ver: string } & (
273284
| { type: 'missing' }
274-
| { type: 'success'; value: { issues: any[] } }
285+
| {
286+
type: 'success'
287+
value: {
288+
issues: BatchIssue[]
289+
}
290+
}
275291
)
276292
> {
277293
const query = {
@@ -369,6 +385,14 @@ function findSpecificOverrideSet(
369385
return undefined
370386
}
371387

388+
function isIssueFixable(issue: BatchIssue): boolean {
389+
const { type } = issue
390+
if (type === 'cve' || type === 'mediumCVE' || type === 'mildCVE' || type === 'criticalCVE') {
391+
return !!issue.value.props['firstPatchedVersionIdentifier']
392+
}
393+
return type === 'socketUpgradeAvailable'
394+
}
395+
372396
function maybeReadfileSync(filepath: string): string | undefined {
373397
try {
374398
return readFileSync(filepath, 'utf8')
@@ -400,26 +424,27 @@ async function packagesHaveRiskyIssues(
400424
const id = `${name}@${version}`
401425

402426
let displayWarning = false
403-
let failures: {
427+
let issues: {
404428
type: string
405429
block: boolean
430+
fixable: boolean
406431
raw?: any
407432
}[] = []
408433
if (pkgData.type === 'missing') {
409434
result = true
410-
failures.push({
435+
issues.push({
411436
type: 'missingDependency',
412437
block: false,
438+
fixable: false,
413439
raw: undefined
414440
})
415441
} else {
416442
let blocked = false
417-
for (const failure of pkgData.value.issues) {
418-
const { type } = failure
443+
for (const issue of pkgData.value.issues) {
419444
// eslint-disable-next-line no-await-in-loop
420445
const ux = await uxLookup({
421446
package: { name, version },
422-
issue: { type }
447+
issue: { type: issue.type }
423448
})
424449
if (ux.block) {
425450
result = true
@@ -429,10 +454,11 @@ async function packagesHaveRiskyIssues(
429454
displayWarning = true
430455
}
431456
if (ux.block || ux.display) {
432-
failures.push({
433-
type,
457+
issues.push({
458+
type: issue.type,
434459
block: ux.block,
435-
raw: failure
460+
raw: issue,
461+
fixable: isIssueFixable(issue)
436462
})
437463
// Before we ask about problematic issues, check to see if they
438464
// already existed in the old version if they did, be quiet.
@@ -445,10 +471,10 @@ async function packagesHaveRiskyIssues(
445471
(await batchScan([pkg.existing]).next()).value
446472
)
447473
if (oldPkgData.type === 'success') {
448-
failures = failures.filter(
449-
issue =>
474+
issues = issues.filter(
475+
({ type }) =>
450476
oldPkgData.value.issues.find(
451-
oldIssue => oldIssue.type === issue.type
477+
oldIssue => oldIssue.type === type
452478
) === undefined
453479
)
454480
}
@@ -469,30 +495,32 @@ async function packagesHaveRiskyIssues(
469495
}
470496
}
471497
}
498+
if (displayWarning && isBlessedPackageName(name)) {
499+
issues = issues.filter(
500+
({ type }) =>
501+
type !== 'unpopularPackage' && type !== 'unstableOwnership'
502+
)
503+
displayWarning = issues.length > 0
504+
}
472505
if (displayWarning) {
473506
spinner.stop(
474507
`(socket) ${formatter.hyperlink(id, `https://socket.dev/npm/package/${name}/overview/${version}`)} contains risks:`
475508
)
476-
// Filter issues for blessed packages.
477-
if (isBlessedPackageName(name)) {
478-
failures = failures.filter(
479-
({ type }) =>
480-
type !== 'unpopularPackage' && type !== 'unstableOwnership'
481-
)
482-
}
483-
failures.sort((a, b) => (a.type < b.type ? -1 : 1))
484-
509+
issues.sort((a, b) => (a.type < b.type ? -1 : 1))
485510
const lines = new Set()
486-
for (const failure of failures) {
487-
const { type } = failure
511+
for (const issue of issues) {
488512
// Based data from { pageProps: { alertTypes } } of:
489513
// https://socket.dev/_next/data/94666139314b6437ee4491a0864e72b264547585/en-US.json
490-
const info = translations.issues[type]
491-
const title = info?.title ?? type
492-
const maybeBlocking = failure.block ? '' : ' (non-blocking)'
514+
const info = translations.issues[issue.type]
515+
const title = info?.title ?? issue.type
516+
const attributes = [
517+
...(issue.fixable ? ['fixable'] : []),
518+
...(issue.block ? [] : ['non-blocking'])
519+
]
520+
const maybeAttributes = attributes.length ? ` (${attributes.join('; ')})` : ''
493521
const maybeDesc = info?.description ? ` - ${info.description}` : ''
494522
// TODO: emoji seems to mis-align terminals sometimes
495-
lines.add(` ${title}${maybeBlocking}${maybeDesc}\n`)
523+
lines.add(` ${title}${maybeAttributes}${maybeDesc}\n`)
496524
}
497525
for (const line of lines) {
498526
output?.write(line)

0 commit comments

Comments
 (0)