Skip to content

Commit

Permalink
feat: add report to vulnerabilities.json (#783)
Browse files Browse the repository at this point in the history
  • Loading branch information
marco-ippolito authored Mar 19, 2024
1 parent 2d4fced commit 9a8605e
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 17 deletions.
19 changes: 19 additions & 0 deletions components/git/security.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ const securityOptions = {
'update-date': {
describe: 'Updates the target date of the security release',
type: 'string'
},
'add-report': {
describe: 'Extracts data from HackerOne report and adds it into vulnerabilities.json',
type: 'string'
}
};

Expand All @@ -26,6 +30,10 @@ export function builder(yargs) {
.example(
'git node security --update-date=31/12/2023',
'Updates the target date of the security release'
)
.example(
'git node security --add-report=H1-ID',
'Fetches HackerOne report based on ID provided and adds it into vulnerabilities.json'
);
}

Expand All @@ -36,9 +44,20 @@ export function handler(argv) {
if (argv['update-date']) {
return updateReleaseDate(argv);
}
if (argv['add-report']) {
return addReport(argv);
}
yargsInstance.showHelp();
}

async function addReport(argv) {
const reportId = argv['add-report'];
const logStream = process.stdout.isTTY ? process.stdout : process.stderr;
const cli = new CLI(logStream);
const update = new UpdateSecurityRelease(cli);
return update.addReport(reportId);
}

async function updateReleaseDate(argv) {
const releaseDate = argv['update-date'];
const logStream = process.stdout.isTTY ? process.stdout : process.stderr;
Expand Down
14 changes: 3 additions & 11 deletions lib/prepare_security.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import {
NEXT_SECURITY_RELEASE_REPOSITORY,
PLACEHOLDERS,
checkoutOnSecurityReleaseBranch,
commitAndPushVulnerabilitiesJSON
commitAndPushVulnerabilitiesJSON,
getSummary
} from './security-release/security-release.js';

export default class SecurityReleaseSteward {
Expand Down Expand Up @@ -175,7 +176,7 @@ class PrepareSecurityRelease {
questionType: 'input',
defaultAnswer: supportedVersions
});
const summaryContent = await this.getSummary(id);
const summaryContent = await getSummary(id, this.req);

selectedReports.push({
id,
Expand All @@ -190,15 +191,6 @@ class PrepareSecurityRelease {
return selectedReports;
}

async getSummary(reportId) {
const { data } = await this.req.getReport(reportId);
const summaryList = data?.relationships?.summaries?.data;
if (!summaryList?.length) return;
const summaries = summaryList.filter((summary) => summary?.attributes?.category === 'team');
if (!summaries?.length) return;
return summaries?.[0].attributes?.content;
}

async createVulnerabilitiesJSON(reports, { cli }) {
cli.separator('Creating vulnerabilities.json...');
const file = JSON.stringify({
Expand Down
17 changes: 17 additions & 0 deletions lib/security-release/security-release.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { runSync } from '../run.js';
import nv from '@pkgjs/nv';

export const NEXT_SECURITY_RELEASE_BRANCH = 'next-security-release';
export const NEXT_SECURITY_RELEASE_FOLDER = 'security-release/next-security-release';
Expand Down Expand Up @@ -56,3 +57,19 @@ export function commitAndPushVulnerabilitiesJSON(filePath, commitMessage, { cli,
runSync('git', ['push', '-u', 'origin', NEXT_SECURITY_RELEASE_BRANCH]);
cli.ok(`Pushed commit: ${commitMessage} to ${NEXT_SECURITY_RELEASE_BRANCH}`);
}

export async function getSupportedVersions() {
const supportedVersions = (await nv('supported'))
.map((v) => `${v.versionName}.x`)
.join(',');
return supportedVersions;
}

export async function getSummary(reportId, req) {
const { data } = await req.getReport(reportId);
const summaryList = data?.relationships?.summaries?.data;
if (!summaryList?.length) return;
const summaries = summaryList.filter((summary) => summary?.attributes?.category === 'team');
if (!summaries?.length) return;
return summaries?.[0].attributes?.content;
}
67 changes: 61 additions & 6 deletions lib/update_security_release.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@ import {
NEXT_SECURITY_RELEASE_FOLDER,
NEXT_SECURITY_RELEASE_REPOSITORY,
checkoutOnSecurityReleaseBranch,
commitAndPushVulnerabilitiesJSON
commitAndPushVulnerabilitiesJSON,
getSupportedVersions,
getSummary
} from './security-release/security-release.js';
import fs from 'node:fs';
import path from 'node:path';
import auth from './auth.js';
import Request from './request.js';

export default class UpdateSecurityRelease {
repository = NEXT_SECURITY_RELEASE_REPOSITORY;
Expand Down Expand Up @@ -39,23 +43,74 @@ export default class UpdateSecurityRelease {
cli.ok('Done!');
}

async updateVulnerabilitiesJSON(releaseDate) {
const vulnerabilitiesJSONPath = path.join(process.cwd(),
NEXT_SECURITY_RELEASE_FOLDER, 'vulnerabilities.json');

readVulnerabilitiesJSON(vulnerabilitiesJSONPath) {
const exists = fs.existsSync(vulnerabilitiesJSONPath);

if (!exists) {
this.cli.error(`The file vulnerabilities.json does not exist at ${vulnerabilitiesJSONPath}`);
process.exit(1);
}

const content = JSON.parse(fs.readFileSync(vulnerabilitiesJSONPath, 'utf8'));
return JSON.parse(fs.readFileSync(vulnerabilitiesJSONPath, 'utf8'));
}

getVulnerabilitiesJSONPath() {
return path.join(process.cwd(),
NEXT_SECURITY_RELEASE_FOLDER, 'vulnerabilities.json');
}

async updateVulnerabilitiesJSON(releaseDate) {
const vulnerabilitiesJSONPath = this.getVulnerabilitiesJSONPath();
const content = this.readVulnerabilitiesJSON(vulnerabilitiesJSONPath);
content.releaseDate = releaseDate;

fs.writeFileSync(vulnerabilitiesJSONPath, JSON.stringify(content, null, 2));

this.cli.ok(`Updated the release date in vulnerabilities.json: ${releaseDate}`);
return [vulnerabilitiesJSONPath];
}

async addReport(reportId) {
const { cli } = this;
const credentials = await auth({
github: true,
h1: true
});

const req = new Request(credentials);
// checkout on the next-security-release branch
checkoutOnSecurityReleaseBranch(cli, this.repository);

// get h1 report
const { data: report } = await req.getReport(reportId);
const { id, attributes: { title, cve_ids }, relationships: { severity, reporter } } = report;
// if severity is not set on h1, set it to TBD
const reportLevel = severity ? severity.data.attributes.rating : 'TBD';

// get the affected versions
const supportedVersions = await getSupportedVersions();
const versions = await cli.prompt('Which active release lines this report affects?', {
questionType: 'input',
defaultAnswer: supportedVersions
});

// get the team summary from h1 report
const summaryContent = await getSummary(id, req);

const entry = {
id,
title,
cve_ids,
severity: reportLevel,
summary: summaryContent ?? '',
affectedVersions: versions.split(',').map((v) => v.replace('v', '').trim()),
reporter: reporter.data.attributes.username
};

const vulnerabilitiesJSONPath = this.getVulnerabilitiesJSONPath();
const content = this.readVulnerabilitiesJSON(vulnerabilitiesJSONPath);
content.reports.push(entry);
fs.writeFileSync(vulnerabilitiesJSONPath, JSON.stringify(content, null, 2));
this.cli.ok(`Updated vulnerabilities.json with the report: ${id}`);
}
}

0 comments on commit 9a8605e

Please sign in to comment.