@@ -141,46 +141,55 @@ export default class UpdateSecurityRelease extends SecurityRelease {
141141 const vulnerabilitiesJSONPath = this . getVulnerabilitiesJSONPath ( ) ;
142142 const content = this . readVulnerabilitiesJSON ( vulnerabilitiesJSONPath ) ;
143143 const { reports } = content ;
144+ this . validateReportsForCVE ( reports ) ;
144145 const req = new Request ( credentials ) ;
145146 const programId = await this . getNodeProgramId ( req ) ;
146- const cves = await this . promptCVECreation ( req , reports , programId ) ;
147- this . assignCVEtoReport ( cves , reports ) ;
148- this . updateVulnerabilitiesJSON ( content ) ;
149- this . updateHackonerReportCve ( req , reports ) ;
147+ await this . promptCVECreation ( req , reports , programId , content ) ;
150148 }
151149
152- assignCVEtoReport ( cves , reports ) {
153- for ( const cve of cves ) {
154- const report = reports . find ( report => report . id === cve . reportId ) ;
155- report . cveIds = [ cve . cve_identifier ] ;
156- report . patchedVersions = cve . patchedVersions ;
150+ validateReportsForCVE ( reports ) {
151+ const invalid = [ ] ;
152+ for ( const report of reports ) {
153+ if ( report . cveIds ?. length ) continue ;
154+ const missing = [ ] ;
155+ if ( ! report . summary ) missing . push ( 'description' ) ;
156+ if ( ! report . severity ?. weakness_id ) missing . push ( 'weakness_id' ) ;
157+ if ( ! report . severity ?. cvss_vector_string ) missing . push ( 'cvss_vector_string' ) ;
158+ if ( missing . length ) {
159+ invalid . push ( { id : report . id , missing } ) ;
160+ }
161+ }
162+ if ( invalid . length ) {
163+ for ( const { id, missing } of invalid ) {
164+ this . cli . error ( `Report ${ id } is missing: ${ missing . join ( ', ' ) } ` ) ;
165+ }
166+ throw new Error ( 'Some reports are missing required fields for CVE request. ' +
167+ 'Run `git node security --sync` to update them.' ) ;
157168 }
158169 }
159170
160- async updateHackonerReportCve ( req , reports ) {
161- for ( const report of reports ) {
162- const { id, cveIds } = report ;
163- this . cli . startSpinner ( `Updating report ${ id } with CVEs ${ cveIds } ..` ) ;
164- const body = {
165- data : {
166- type : 'report-cves' ,
167- attributes : {
168- cve_ids : cveIds
169- }
171+ async updateHackonerReportCve ( req , report ) {
172+ const { id, cveIds } = report ;
173+ this . cli . startSpinner ( `Updating report ${ id } with CVEs ${ cveIds } ..` ) ;
174+ const body = {
175+ data : {
176+ type : 'report-cves' ,
177+ attributes : {
178+ cve_ids : cveIds
170179 }
171- } ;
172- const response = await req . updateReportCVE ( id , body ) ;
173- if ( response . errors ) {
174- this . cli . error ( `Error updating report ${ id } ` ) ;
175- this . cli . error ( JSON . stringify ( response . errors , null , 2 ) ) ;
176180 }
177- this . cli . stopSpinner ( `Done updating report ${ id } with CVEs ${ cveIds } ..` ) ;
181+ } ;
182+ const response = await req . updateReportCVE ( id , body ) ;
183+ if ( response . errors ) {
184+ this . cli . error ( `Error updating report ${ id } ` ) ;
185+ this . cli . error ( JSON . stringify ( response . errors , null , 2 ) ) ;
178186 }
187+ this . cli . stopSpinner ( `Done updating report ${ id } with CVEs ${ cveIds } ..` ) ;
179188 }
180189
181- async promptCVECreation ( req , reports , programId ) {
190+ async promptCVECreation ( req , reports , programId , content ) {
182191 const supportedVersions = ( await nv ( 'supported' ) ) ;
183- const cves = [ ] ;
192+ const eolVersions = ( await nv ( 'eol' ) ) ;
184193 for ( const report of reports ) {
185194 const { id, summary, title, affectedVersions, cveIds, link } = report ;
186195 // skip if already has a CVE
@@ -222,7 +231,7 @@ Summary: ${summary}\n`,
222231 if ( ! create ) continue ;
223232
224233 const { h1AffectedVersions, patchedVersions } =
225- await this . calculateVersions ( affectedVersions , supportedVersions ) ;
234+ await this . calculateVersions ( affectedVersions , supportedVersions , eolVersions ) ;
226235 const body = {
227236 data : {
228237 type : 'cve-request' ,
@@ -243,16 +252,18 @@ Summary: ${summary}\n`,
243252 }
244253 }
245254 } ;
246- const { data } = await req . requestCVE ( programId , body ) ;
247- if ( data . errors ) {
255+ const response = await req . requestCVE ( programId , body ) ;
256+ if ( response . errors ) {
248257 this . cli . error ( `Error requesting CVE for report ${ id } ` ) ;
249- this . cli . error ( JSON . stringify ( data . errors , null , 2 ) ) ;
258+ this . cli . error ( JSON . stringify ( response . errors , null , 2 ) ) ;
250259 continue ;
251260 }
252- const { cve_identifier } = data . attributes ;
253- cves . push ( { cve_identifier, reportId : id , patchedVersions } ) ;
261+ const { cve_identifier } = response . data . attributes ;
262+ report . cveIds = [ cve_identifier ] ;
263+ report . patchedVersions = patchedVersions ;
264+ this . updateVulnerabilitiesJSON ( content ) ;
265+ await this . updateHackonerReportCve ( req , report ) ;
254266 }
255- return cves ;
256267 }
257268
258269 async getNodeProgramId ( req ) {
@@ -266,7 +277,7 @@ Summary: ${summary}\n`,
266277 }
267278 }
268279
269- async calculateVersions ( affectedVersions , supportedVersions ) {
280+ async calculateVersions ( affectedVersions , supportedVersions , eolVersions ) {
270281 const h1AffectedVersions = [ ] ;
271282 const patchedVersions = [ ] ;
272283 let isPatchRelease = true ;
@@ -300,6 +311,22 @@ Summary: ${summary}\n`,
300311 affected : true
301312 } ) ;
302313 }
314+
315+ // All EOL versions are affected since they no longer receive security patches
316+ for ( const eolVersion of eolVersions ) {
317+ const version = semver . valid ( eolVersion . version ) ;
318+ if ( version ) {
319+ h1AffectedVersions . push ( {
320+ vendor : 'nodejs' ,
321+ product : 'node' ,
322+ func : '<=' ,
323+ version,
324+ versionType : 'semver' ,
325+ affected : true
326+ } ) ;
327+ }
328+ }
329+
303330 return { h1AffectedVersions, patchedVersions } ;
304331 }
305332}
0 commit comments