diff --git a/lib/h1-cve.js b/lib/h1-cve.js index 9f88e902..48ca3b8a 100644 --- a/lib/h1-cve.js +++ b/lib/h1-cve.js @@ -32,22 +32,29 @@ export default class HackerOneCve { assignCVEtoReport(cves, reports) { for (const cve of cves) { - reports.find(report => report.id === cve.reportId).cve_ids = [cve]; + const report = reports.find(report => report.id === cve.reportId); + report.cve_ids = [cve.cve_identifier]; } } async updateHackonerReportCve(req, reports) { for (const report of reports) { const { id, cve_ids } = report; + this.cli.startSpinner(`Updating report ${id} with CVEs ${cve_ids}..`); const body = { data: { - type: 'cve-report', + type: 'report-cves', attributes: { cve_ids } } }; - await req.updateReportCVE(id, body); + 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 ${cve_ids}..`); } } @@ -70,17 +77,42 @@ export default class HackerOneCve { const supportedVersions = (await nv('supported')); const cves = []; for (const report of reports) { - const { id, summary, title, affectedVersions } = report; - const h1Report = await req.getReport(id); - const weaknessId = h1Report.data.relationships.weakness?.data.id; - const vectorString = h1Report.data.relationships.severity?.data.attributes.cvss_vector_string; - const discoveredAt = h1Report.data.attributes.created_at; + const { id, summary, title, affectedVersions, created_at } = report; + + let severity = report.severity; + + if (!report.severity || report.severity === 'TBD') { + const fetchIt = await this.cli.prompt( +`Severity is missing for report ${id}. +Do you want to retrieve it from the report?`, +{ defaultAnswer: true } + ); + + if (fetchIt) { + try { + const h1Report = await req.getReport(id); + if (!h1Report.data.relationships.severity?.data.attributes.cvss_vector_string) { + throw new Error('No severity found'); + } + severity = { + weakness_id: h1Report.data.relationships.weakness?.data.id, + cvss_vector_string: + h1Report.data.relationships.severity?.data.attributes.cvss_vector_string, + rating: h1Report.data.relationships.severity?.data.attributes.rating + }; + } catch (error) { + this.cli.error(`Couldnt not retrieve severity from report ${id}, skipping...`); + continue; + } + } + } + const { cvss_vector_string, weakness_id } = severity; const create = await this.cli.prompt( `Request a CVE for: \n Title: ${title}\n Affected versions: ${affectedVersions.join(', ')}\n -Vector: ${vectorString}\n +Vector: ${cvss_vector_string}\n Summary: ${summary}\n`, { defaultAnswer: true }); @@ -94,17 +126,22 @@ Summary: ${summary}\n`, versions: await this.formatAffected(affectedVersions, supportedVersions), metrics: [ { - vectorString + vectorString: cvss_vector_string } ], - weakness_id: Number(weaknessId), + weakness_id: Number(weakness_id), description: title, - vulnerability_discovered_at: discoveredAt + vulnerability_discovered_at: created_at } } }; - const { attributes } = await req.requestCVE(programId, body); - const { cve_identifier } = attributes; + const data = await req.requestCVE(programId, body); + if (data.errors) { + this.cli.error(`Error requesting CVE for report ${id}`); + this.cli.error(JSON.stringify(data.errors, null, 2)); + continue; + } + const { cve_identifier } = data.attributes; cves.push({ cve_identifier, reportId: id }); } return cves; diff --git a/lib/request.js b/lib/request.js index f7b34f3f..4e8c830d 100644 --- a/lib/request.js +++ b/lib/request.js @@ -161,13 +161,14 @@ export default class Request { } async updateReportCVE(reportId, opts) { - const url = `"https://api.hackerone.com/v1/reports/${reportId}/cves"`; + const url = `https://api.hackerone.com/v1/reports/${reportId}/cves`; const options = { method: 'PUT', headers: { Authorization: `Basic ${this.credentials.h1}`, 'User-Agent': 'node-core-utils', - Accept: 'application/json' + Accept: 'application/json', + 'Content-Type': 'application/json' }, body: JSON.stringify(opts) };