@@ -55,74 +55,59 @@ export async function batchGetCVEIssues(
5555async function getCveUpgradeIssues (
5656 coordinates : string [ ]
5757) : Promise < CveUpgradeIssue [ ] > {
58+ if ( coordinates . length === 0 ) {
59+ return [ ] ;
60+ }
5861 const deps = coordinates
5962 . map ( ( d ) => d . split ( ":" , 3 ) )
6063 . map ( ( p ) => ( { name : `${ p [ 0 ] } :${ p [ 1 ] } ` , version : p [ 2 ] } ) )
6164 . filter ( ( d ) => d . version ) ;
6265
6366 const depsCves = await fetchCves ( deps ) ;
64- return mapCvesToUpgradeIssues ( depsCves , deps ) ;
67+ return mapCvesToUpgradeIssues ( depsCves ) ;
6568}
6669
6770async function fetchCves ( deps : { name : string ; version : string } [ ] ) {
68- const allCves : CVE [ ] = await retrieveVulnerabilityData ( deps ) ;
69-
70- // group the cves by coordinate
71- const depsCves : { dep : string ; cves : CVE [ ] ; minVersion ?: string | null } [ ] =
72- [ ] ;
73-
74- for ( const dep of deps ) {
75- const depCves : CVE [ ] = allCves . filter ( ( cve ) =>
76- cve . affectedDeps . some ( ( d ) => d . name === dep . name )
77- ) ;
78-
79- if ( depCves . length < 1 ) {
80- continue ;
81- }
82-
83- // find the min patched version for each coordinate
84- const maxPatchedVersion = calculateMaxPatchedVersion ( depCves , dep ) ;
85-
86- depsCves . push ( {
87- dep : dep . name ,
88- cves : depCves ,
89- minVersion : maxPatchedVersion ,
90- } ) ;
71+ if ( deps . length === 0 ) {
72+ return [ ] ;
9173 }
74+ try {
75+ const allCves : CVE [ ] = await retrieveVulnerabilityData ( deps ) ;
9276
93- return depsCves ;
94- }
95-
96- function calculateMaxPatchedVersion (
97- depCves : CVE [ ] ,
98- dep : { name : string ; version : string }
99- ) {
100- let maxPatchedVersion : string | undefined | null ;
101-
102- for ( const cve of depCves ) {
103- const patchedVersion = cve . affectedDeps . find (
104- ( d ) => d . name === dep . name && d . patchedVersion
105- ) ?. patchedVersion ;
106-
107- const coercedPatchedVersion = semver . coerce ( patchedVersion ) ;
108- const coercedMaxPatchedVersion = semver . coerce ( maxPatchedVersion ) ;
109-
110- if (
111- ! maxPatchedVersion ||
112- ( coercedPatchedVersion &&
113- coercedMaxPatchedVersion &&
114- semver . gt ( coercedPatchedVersion , coercedMaxPatchedVersion ) )
115- ) {
116- maxPatchedVersion = patchedVersion ;
77+ if ( allCves . length === 0 ) {
78+ return [ ] ;
79+ }
80+ // group the cves by coordinate
81+ const depsCves : { dep : string ; version : string ; cves : CVE [ ] } [ ] = [ ] ;
82+
83+ for ( const dep of deps ) {
84+ const depCves : CVE [ ] = allCves . filter ( ( cve ) =>
85+ isCveAffectingDep ( cve , dep . name , dep . version )
86+ ) ;
87+
88+ if ( depCves . length < 1 ) {
89+ continue ;
90+ }
91+
92+ depsCves . push ( {
93+ dep : dep . name ,
94+ version : dep . version ,
95+ cves : depCves ,
96+ } ) ;
11797 }
118- }
11998
120- return maxPatchedVersion ;
99+ return depsCves ;
100+ } catch ( error ) {
101+ return [ ] ;
102+ }
121103}
122104
123105async function retrieveVulnerabilityData (
124106 deps : { name : string ; version : string } [ ]
125107) {
108+ if ( deps . length === 0 ) {
109+ return [ ] ;
110+ }
126111 const octokit = new Octokit ( ) ;
127112
128113 const response = await octokit . securityAdvisories . listGlobalAdvisories ( {
@@ -156,26 +141,24 @@ async function retrieveVulnerabilityData(
156141}
157142
158143function mapCvesToUpgradeIssues (
159- depsCves : { dep : string ; cves : CVE [ ] ; minVersion ?: string | null } [ ] ,
160- deps : { name : string ; version : string } [ ]
144+ depsCves : { dep : string ; version : string ; cves : CVE [ ] } [ ]
161145) {
146+ if ( depsCves . length === 0 ) {
147+ return [ ] ;
148+ }
162149 const upgradeIssues = depsCves . map ( ( depCve ) => {
163- const currentDep = deps . find ( ( d ) => d . name === depCve . dep ) ;
164- const mostCriticalCve = [ ...depCve . cves ] . sort (
165- ( a , b ) => Severity [ b . severity ] - Severity [ a . severity ]
166- ) [ 0 ] ;
150+ const mostCriticalCve = [ ...depCve . cves ]
151+ . filter ( ( cve ) => isCveAffectingDep ( cve , depCve . dep , depCve . version ) )
152+ . sort ( ( a , b ) => Severity [ b . severity ] - Severity [ a . severity ] ) [ 0 ] ;
167153 return {
168154 packageId : depCve . dep ,
169155 packageDisplayName : depCve . dep ,
170- currentVersion : currentDep ? .version || "unknown" ,
156+ currentVersion : depCve . version || "unknown" ,
171157 name : `${ mostCriticalCve . id || "CVE" } ` ,
172158 reason : UpgradeReason . CVE as const ,
173159 suggestedVersion : {
174- name : depCve . minVersion || "unknown" ,
175- description :
176- mostCriticalCve . description ||
177- mostCriticalCve . summary ||
178- "Security vulnerability detected" ,
160+ name : "" ,
161+ description : "" ,
179162 } ,
180163 severity : mostCriticalCve . severity ,
181164 description :
@@ -187,3 +170,22 @@ function mapCvesToUpgradeIssues(
187170 } ) ;
188171 return upgradeIssues ;
189172}
173+
174+ function isCveAffectingDep (
175+ cve : CVE ,
176+ depName : string ,
177+ depVersion : string
178+ ) : boolean {
179+ if ( ! cve . affectedDeps || cve . affectedDeps . length === 0 ) {
180+ return false ;
181+ }
182+ return cve . affectedDeps . some ( ( d ) => {
183+ if ( d . name !== depName ) {
184+ return false ;
185+ }
186+ if ( ! d . vulVersions || ! d . patchedVersion ) {
187+ return false ;
188+ }
189+ return semver . satisfies ( depVersion || "0.0.0" , d . vulVersions ) ;
190+ } ) ;
191+ }
0 commit comments