@@ -248,6 +248,17 @@ const kRiskyReify = Symbol('riskyReify')
248
248
const formatter = new ColorOrMarkdown ( false )
249
249
const pubToken = getDefaultKey ( ) ?? FREE_API_KEY
250
250
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
+ }
251
262
type IssueUXLookup = ReturnType < typeof createIssueUXLookup >
252
263
type IssueUXLookupSettings = Parameters < IssueUXLookup > [ 0 ]
253
264
type IssueUXLookupResult = ReturnType < IssueUXLookup >
@@ -271,7 +282,12 @@ async function* batchScan(
271
282
) : AsyncGenerator <
272
283
{ eco : string ; pkg : string ; ver : string } & (
273
284
| { type : 'missing' }
274
- | { type : 'success' ; value : { issues : any [ ] } }
285
+ | {
286
+ type : 'success'
287
+ value : {
288
+ issues : BatchIssue [ ]
289
+ }
290
+ }
275
291
)
276
292
> {
277
293
const query = {
@@ -369,6 +385,14 @@ function findSpecificOverrideSet(
369
385
return undefined
370
386
}
371
387
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
+
372
396
function maybeReadfileSync ( filepath : string ) : string | undefined {
373
397
try {
374
398
return readFileSync ( filepath , 'utf8' )
@@ -400,26 +424,27 @@ async function packagesHaveRiskyIssues(
400
424
const id = `${ name } @${ version } `
401
425
402
426
let displayWarning = false
403
- let failures : {
427
+ let issues : {
404
428
type : string
405
429
block : boolean
430
+ fixable : boolean
406
431
raw ?: any
407
432
} [ ] = [ ]
408
433
if ( pkgData . type === 'missing' ) {
409
434
result = true
410
- failures . push ( {
435
+ issues . push ( {
411
436
type : 'missingDependency' ,
412
437
block : false ,
438
+ fixable : false ,
413
439
raw : undefined
414
440
} )
415
441
} else {
416
442
let blocked = false
417
- for ( const failure of pkgData . value . issues ) {
418
- const { type } = failure
443
+ for ( const issue of pkgData . value . issues ) {
419
444
// eslint-disable-next-line no-await-in-loop
420
445
const ux = await uxLookup ( {
421
446
package : { name, version } ,
422
- issue : { type }
447
+ issue : { type : issue . type }
423
448
} )
424
449
if ( ux . block ) {
425
450
result = true
@@ -429,10 +454,11 @@ async function packagesHaveRiskyIssues(
429
454
displayWarning = true
430
455
}
431
456
if ( ux . block || ux . display ) {
432
- failures . push ( {
433
- type,
457
+ issues . push ( {
458
+ type : issue . type ,
434
459
block : ux . block ,
435
- raw : failure
460
+ raw : issue ,
461
+ fixable : isIssueFixable ( issue )
436
462
} )
437
463
// Before we ask about problematic issues, check to see if they
438
464
// already existed in the old version if they did, be quiet.
@@ -445,10 +471,10 @@ async function packagesHaveRiskyIssues(
445
471
( await batchScan ( [ pkg . existing ] ) . next ( ) ) . value
446
472
)
447
473
if ( oldPkgData . type === 'success' ) {
448
- failures = failures . filter (
449
- issue =>
474
+ issues = issues . filter (
475
+ ( { type } ) =>
450
476
oldPkgData . value . issues . find (
451
- oldIssue => oldIssue . type === issue . type
477
+ oldIssue => oldIssue . type === type
452
478
) === undefined
453
479
)
454
480
}
@@ -469,30 +495,32 @@ async function packagesHaveRiskyIssues(
469
495
}
470
496
}
471
497
}
498
+ if ( displayWarning && isBlessedPackageName ( name ) ) {
499
+ issues = issues . filter (
500
+ ( { type } ) =>
501
+ type !== 'unpopularPackage' && type !== 'unstableOwnership'
502
+ )
503
+ displayWarning = issues . length > 0
504
+ }
472
505
if ( displayWarning ) {
473
506
spinner . stop (
474
507
`(socket) ${ formatter . hyperlink ( id , `https://socket.dev/npm/package/${ name } /overview/${ version } ` ) } contains risks:`
475
508
)
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 ) )
485
510
const lines = new Set ( )
486
- for ( const failure of failures ) {
487
- const { type } = failure
511
+ for ( const issue of issues ) {
488
512
// Based data from { pageProps: { alertTypes } } of:
489
513
// 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 ( '; ' ) } )` : ''
493
521
const maybeDesc = info ?. description ? ` - ${ info . description } ` : ''
494
522
// TODO: emoji seems to mis-align terminals sometimes
495
- lines . add ( ` ${ title } ${ maybeBlocking } ${ maybeDesc } \n` )
523
+ lines . add ( ` ${ title } ${ maybeAttributes } ${ maybeDesc } \n` )
496
524
}
497
525
for ( const line of lines ) {
498
526
output ?. write ( line )
0 commit comments