1- import type { OsvSeverityLevel } from '#utils/api/vulnerability'
1+ import type { OsvSeverityLevel , PackageVulnerabilityInfo } from '#utils/api/vulnerability'
22import type { DiagnosticRule } from '..'
33import { getVulnerability , SEVERITY_LEVELS } from '#utils/api/vulnerability'
44import { npmxPackageUrl } from '#utils/links'
5- import { isSupportedProtocol , parseVersion } from '#utils/version'
5+ import { formatVersion , isSupportedProtocol , lt , parseVersion } from '#utils/version'
66import { DiagnosticSeverity , Uri } from 'vscode'
77
88const DIAGNOSTIC_MAPPING : Record < Exclude < OsvSeverityLevel , 'unknown' > , DiagnosticSeverity > = {
@@ -12,6 +12,19 @@ const DIAGNOSTIC_MAPPING: Record<Exclude<OsvSeverityLevel, 'unknown'>, Diagnosti
1212 low : DiagnosticSeverity . Hint ,
1313}
1414
15+ function getBigestFixedInVersion ( vulnerablePackages : PackageVulnerabilityInfo [ ] ) : string | undefined {
16+ let bigest : string | undefined
17+ for ( const { depth, vulnerabilities } of vulnerablePackages ) {
18+ if ( depth !== 'root' )
19+ continue
20+ for ( const { fixedIn } of vulnerabilities ) {
21+ if ( fixedIn && ( ! bigest || lt ( bigest , fixedIn ) ) )
22+ bigest = fixedIn
23+ }
24+ }
25+ return bigest
26+ }
27+
1528export const checkVulnerability : DiagnosticRule = async ( dep , pkg ) => {
1629 const parsed = parseVersion ( dep . version )
1730 if ( ! parsed || ! isSupportedProtocol ( parsed . protocol ) )
@@ -26,7 +39,7 @@ export const checkVulnerability: DiagnosticRule = async (dep, pkg) => {
2639 if ( ! result )
2740 return
2841
29- const { totalCounts } = result
42+ const { totalCounts, vulnerablePackages } = result
3043 const message : string [ ] = [ ]
3144 let severity : DiagnosticSeverity | null = null
3245
@@ -45,10 +58,15 @@ export const checkVulnerability: DiagnosticRule = async (dep, pkg) => {
4558 if ( ! message . length )
4659 return
4760
61+ const fixedInVersion = getBigestFixedInVersion ( vulnerablePackages )
62+ const messageSuffix = fixedInVersion
63+ ? ` Upgrade to ${ formatVersion ( { ...parsed , semver : fixedInVersion } ) } to fix.`
64+ : ''
65+
4866 return {
4967 node : dep . versionNode ,
50- message : `This version has ${ message . join ( ', ' ) } ${ message . length === 1 ? 'vulnerability' : 'vulnerabilities' } ` ,
51- severity : DiagnosticSeverity . Error ,
68+ message : `This version has ${ message . join ( ', ' ) } ${ message . length === 1 ? 'vulnerability' : 'vulnerabilities' } . ${ messageSuffix } ` ,
69+ severity : severity ?? DiagnosticSeverity . Error ,
5270 code : {
5371 value : 'vulnerability' ,
5472 target : Uri . parse ( npmxPackageUrl ( dep . name , semver ) ) ,
0 commit comments