Skip to content

Commit f4c586e

Browse files
authored
feat: add git node security --sync (#818)
1 parent e3e19b3 commit f4c586e

File tree

3 files changed

+72
-8
lines changed

3 files changed

+72
-8
lines changed

components/git/security.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ const securityOptions = {
1212
describe: 'Start security release process',
1313
type: 'boolean'
1414
},
15+
sync: {
16+
describe: 'Synchronize an ongoing security release with HackerOne',
17+
type: 'boolean'
18+
},
1519
'update-date': {
1620
describe: 'Updates the target date of the security release',
1721
type: 'string'
@@ -46,6 +50,10 @@ export function builder(yargs) {
4650
.example(
4751
'git node security --start',
4852
'Prepare a security release of Node.js')
53+
.example(
54+
'git node security --sync',
55+
'Synchronize an ongoing security release with HackerOne'
56+
)
4957
.example(
5058
'git node security --update-date=YYYY/MM/DD',
5159
'Updates the target date of the security release'
@@ -76,6 +84,9 @@ export function handler(argv) {
7684
if (argv.start) {
7785
return startSecurityRelease(argv);
7886
}
87+
if (argv.sync) {
88+
return syncSecurityRelease(argv);
89+
}
7990
if (argv['update-date']) {
8091
return updateReleaseDate(argv);
8192
}
@@ -142,6 +153,13 @@ async function startSecurityRelease(argv) {
142153
return release.start();
143154
}
144155

156+
async function syncSecurityRelease(argv) {
157+
const logStream = process.stdout.isTTY ? process.stdout : process.stderr;
158+
const cli = new CLI(logStream);
159+
const release = new UpdateSecurityRelease(cli);
160+
return release.sync();
161+
}
162+
145163
async function notifyPreRelease() {
146164
const logStream = process.stdout.isTTY ? process.stdout : process.stderr;
147165
const cli = new CLI(logStream);

lib/security-release/security-release.js

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ export async function getSupportedVersions() {
8787
return supportedVersions;
8888
}
8989

90-
export async function getSummary(reportId, req) {
91-
const { data } = await req.getReport(reportId);
90+
export function getSummary(report) {
91+
const { data } = report;
9292
const summaryList = data?.relationships?.summaries?.data;
9393
if (!summaryList?.length) return;
9494
const summaries = summaryList.filter((summary) => summary?.attributes?.category === 'team');
@@ -139,17 +139,25 @@ export async function createIssue(title, content, repository, { cli, req }) {
139139
}
140140
}
141141

142-
export async function pickReport(report, { cli, req }) {
142+
export function getReportSeverity(report) {
143143
const {
144-
id, attributes: { title, cve_ids },
145-
relationships: { severity, weakness, reporter, custom_field_values }
144+
relationships: { severity, weakness }
146145
} = report;
147-
const link = `https://hackerone.com/reports/${id}`;
148146
const reportSeverity = {
149147
rating: severity?.data?.attributes?.rating || '',
150148
cvss_vector_string: severity?.data?.attributes?.cvss_vector_string || '',
151149
weakness_id: weakness?.data?.id || ''
152150
};
151+
return reportSeverity;
152+
}
153+
154+
export async function pickReport(report, { cli, req }) {
155+
const {
156+
id, attributes: { title, cve_ids },
157+
relationships: { reporter, custom_field_values }
158+
} = report;
159+
const link = `https://hackerone.com/reports/${id}`;
160+
const reportSeverity = getReportSeverity(report);
153161

154162
cli.separator();
155163
cli.info(`Report: ${link} - ${title} (${reportSeverity?.rating})`);
@@ -185,7 +193,7 @@ export async function pickReport(report, { cli, req }) {
185193
}
186194
}
187195

188-
const summaryContent = await getSummary(id, req);
196+
const summaryContent = getSummary(report);
189197

190198
return {
191199
id,

lib/update_security_release.js

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@ import {
22
NEXT_SECURITY_RELEASE_FOLDER,
33
NEXT_SECURITY_RELEASE_REPOSITORY,
44
checkoutOnSecurityReleaseBranch,
5+
checkRemote,
56
commitAndPushVulnerabilitiesJSON,
67
validateDate,
7-
pickReport
8+
pickReport,
9+
getReportSeverity,
10+
getSummary
811
} from './security-release/security-release.js';
912
import fs from 'node:fs';
1013
import path from 'node:path';
@@ -18,6 +21,41 @@ export default class UpdateSecurityRelease {
1821
this.cli = cli;
1922
}
2023

24+
async sync() {
25+
checkRemote(this.cli, this.repository);
26+
27+
const vulnerabilitiesJSONPath = this.getVulnerabilitiesJSONPath();
28+
const content = this.readVulnerabilitiesJSON(vulnerabilitiesJSONPath);
29+
const credentials = await auth({
30+
github: true,
31+
h1: true
32+
});
33+
const req = new Request(credentials);
34+
for (let i = 0; i < content.reports.length; ++i) {
35+
let report = content.reports[i];
36+
const { data } = await req.getReport(report.id);
37+
const reportSeverity = getReportSeverity(data);
38+
const summaryContent = getSummary(data);
39+
const link = `https://hackerone.com/reports/${report.id}`;
40+
let prURL = report.prURL;
41+
if (data.relationships.custom_field_values.data.length) {
42+
prURL = data.relationships.custom_field_values.data[0].attributes.value;
43+
}
44+
45+
report = {
46+
...report,
47+
title: data.attributes.title,
48+
cveIds: data.attributes.cve_ids,
49+
severity: reportSeverity,
50+
summary: summaryContent ?? report.summary,
51+
link,
52+
prURL
53+
};
54+
}
55+
fs.writeFileSync(vulnerabilitiesJSONPath, JSON.stringify(content, null, 2));
56+
this.cli.ok('Synced vulnerabilities.json with HackerOne');
57+
}
58+
2159
async updateReleaseDate(releaseDate) {
2260
const { cli } = this;
2361

0 commit comments

Comments
 (0)