From 68b6e1d2748db6060ce0bfc52cf2c32626aad85a Mon Sep 17 00:00:00 2001 From: RafaelGSS Date: Tue, 17 Mar 2026 12:07:00 -0300 Subject: [PATCH] fix: improve --request-cve --- lib/update_security_release.js | 97 ++++++++++++++++++++++------------ 1 file changed, 62 insertions(+), 35 deletions(-) diff --git a/lib/update_security_release.js b/lib/update_security_release.js index df636d75..8125e648 100644 --- a/lib/update_security_release.js +++ b/lib/update_security_release.js @@ -141,46 +141,55 @@ export default class UpdateSecurityRelease extends SecurityRelease { const vulnerabilitiesJSONPath = this.getVulnerabilitiesJSONPath(); const content = this.readVulnerabilitiesJSON(vulnerabilitiesJSONPath); const { reports } = content; + this.validateReportsForCVE(reports); const req = new Request(credentials); const programId = await this.getNodeProgramId(req); - const cves = await this.promptCVECreation(req, reports, programId); - this.assignCVEtoReport(cves, reports); - this.updateVulnerabilitiesJSON(content); - this.updateHackonerReportCve(req, reports); + await this.promptCVECreation(req, reports, programId, content); } - assignCVEtoReport(cves, reports) { - for (const cve of cves) { - const report = reports.find(report => report.id === cve.reportId); - report.cveIds = [cve.cve_identifier]; - report.patchedVersions = cve.patchedVersions; + validateReportsForCVE(reports) { + const invalid = []; + for (const report of reports) { + if (report.cveIds?.length) continue; + const missing = []; + if (!report.summary) missing.push('description'); + if (!report.severity?.weakness_id) missing.push('weakness_id'); + if (!report.severity?.cvss_vector_string) missing.push('cvss_vector_string'); + if (missing.length) { + invalid.push({ id: report.id, missing }); + } + } + if (invalid.length) { + for (const { id, missing } of invalid) { + this.cli.error(`Report ${id} is missing: ${missing.join(', ')}`); + } + throw new Error('Some reports are missing required fields for CVE request. ' + + 'Run `git node security --sync` to update them.'); } } - async updateHackonerReportCve(req, reports) { - for (const report of reports) { - const { id, cveIds } = report; - this.cli.startSpinner(`Updating report ${id} with CVEs ${cveIds}..`); - const body = { - data: { - type: 'report-cves', - attributes: { - cve_ids: cveIds - } + async updateHackonerReportCve(req, report) { + const { id, cveIds } = report; + this.cli.startSpinner(`Updating report ${id} with CVEs ${cveIds}..`); + const body = { + data: { + type: 'report-cves', + attributes: { + cve_ids: cveIds } - }; - const response = await req.updateReportCVE(id, body); - if (response.errors) { - this.cli.error(`Error updating report ${id}`); - this.cli.error(JSON.stringify(response.errors, null, 2)); } - this.cli.stopSpinner(`Done updating report ${id} with CVEs ${cveIds}..`); + }; + const response = await req.updateReportCVE(id, body); + if (response.errors) { + this.cli.error(`Error updating report ${id}`); + this.cli.error(JSON.stringify(response.errors, null, 2)); } + this.cli.stopSpinner(`Done updating report ${id} with CVEs ${cveIds}..`); } - async promptCVECreation(req, reports, programId) { + async promptCVECreation(req, reports, programId, content) { const supportedVersions = (await nv('supported')); - const cves = []; + const eolVersions = (await nv('eol')); for (const report of reports) { const { id, summary, title, affectedVersions, cveIds, link } = report; // skip if already has a CVE @@ -222,7 +231,7 @@ Summary: ${summary}\n`, if (!create) continue; const { h1AffectedVersions, patchedVersions } = - await this.calculateVersions(affectedVersions, supportedVersions); + await this.calculateVersions(affectedVersions, supportedVersions, eolVersions); const body = { data: { type: 'cve-request', @@ -243,16 +252,18 @@ Summary: ${summary}\n`, } } }; - const { data } = await req.requestCVE(programId, body); - if (data.errors) { + const response = await req.requestCVE(programId, body); + if (response.errors) { this.cli.error(`Error requesting CVE for report ${id}`); - this.cli.error(JSON.stringify(data.errors, null, 2)); + this.cli.error(JSON.stringify(response.errors, null, 2)); continue; } - const { cve_identifier } = data.attributes; - cves.push({ cve_identifier, reportId: id, patchedVersions }); + const { cve_identifier } = response.data.attributes; + report.cveIds = [cve_identifier]; + report.patchedVersions = patchedVersions; + this.updateVulnerabilitiesJSON(content); + await this.updateHackonerReportCve(req, report); } - return cves; } async getNodeProgramId(req) { @@ -266,7 +277,7 @@ Summary: ${summary}\n`, } } - async calculateVersions(affectedVersions, supportedVersions) { + async calculateVersions(affectedVersions, supportedVersions, eolVersions) { const h1AffectedVersions = []; const patchedVersions = []; let isPatchRelease = true; @@ -300,6 +311,22 @@ Summary: ${summary}\n`, affected: true }); } + + // All EOL versions are affected since they no longer receive security patches + for (const eolVersion of eolVersions) { + const version = semver.valid(eolVersion.version); + if (version) { + h1AffectedVersions.push({ + vendor: 'nodejs', + product: 'node', + func: '<=', + version, + versionType: 'semver', + affected: true + }); + } + } + return { h1AffectedVersions, patchedVersions }; } }