-
Notifications
You must be signed in to change notification settings - Fork 113
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: create git-node security release command (#715)
- Loading branch information
Showing
7 changed files
with
321 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import CLI from '../../lib/cli.js'; | ||
import SecurityReleaseSteward from '../../lib/prepare_security.js'; | ||
|
||
export const command = 'security [options]'; | ||
export const describe = 'Manage an in-progress security release or start a new one.'; | ||
|
||
const securityOptions = { | ||
start: { | ||
describe: 'Start security release process', | ||
type: 'boolean' | ||
} | ||
}; | ||
|
||
let yargsInstance; | ||
|
||
export function builder(yargs) { | ||
yargsInstance = yargs; | ||
return yargs.options(securityOptions).example( | ||
'git node security --start', | ||
'Prepare a security release of Node.js'); | ||
} | ||
|
||
export function handler(argv) { | ||
if (argv.start) { | ||
return startSecurityRelease(argv); | ||
} | ||
yargsInstance.showHelp(); | ||
} | ||
|
||
async function startSecurityRelease(argv) { | ||
const logStream = process.stdout.isTTY ? process.stdout : process.stderr; | ||
const cli = new CLI(logStream); | ||
const release = new SecurityReleaseSteward(cli); | ||
return release.start(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
## Planning | ||
|
||
* [X] Open an [issue](https://github.com/nodejs-private/node-private) titled | ||
`Next Security Release`, and put this checklist in the description. | ||
|
||
* [ ] Get agreement on the list of vulnerabilities to be addressed: | ||
%REPORTS% | ||
|
||
* [ ] PR release announcements in [private](https://github.com/nodejs-private/nodejs.org-private): | ||
* [ ] pre-release: %PRE_RELEASE_PRIV% | ||
* [ ] post-release: %POS_RELEASE_PRIV% | ||
* List vulnerabilities in order of descending severity | ||
* Ask the HackerOne reporter if they would like to be credited on the | ||
security release blog page | ||
|
||
* [ ] Get agreement on the planned date for the release: %RELEASE_DATE% | ||
|
||
* [ ] Get release team volunteers for all affected lines: | ||
%AFFECTED_LINES% | ||
|
||
## Announcement (one week in advance of the planned release) | ||
|
||
* [ ] Verify that GitHub Actions are working as normal: <https://www.githubstatus.com/>. | ||
|
||
* [ ] Check that all vulnerabilities are ready for release integration: | ||
* PRs against all affected release lines or cherry-pick clean | ||
* Approved | ||
* (optional) Approved by the reporter | ||
* Build and send the binary to the reporter according to its architecture | ||
and ask for a review. This step is important to avoid insufficient fixes | ||
between Security Releases. | ||
* Have CVEs | ||
* Make sure that dependent libraries have CVEs for their issues. We should | ||
only create CVEs for vulnerabilities in Node.js itself. This is to avoid | ||
having duplicate CVEs for the same vulnerability. | ||
* Described in the pre/post announcements | ||
|
||
* [ ] Pre-release announcement to nodejs.org blog: TBD | ||
(Re-PR the pre-approved branch from nodejs-private/nodejs.org-private to | ||
nodejs/nodejs.org) | ||
|
||
* [ ] Pre-release announcement [email](https://groups.google.com/forum/#!forum/nodejs-sec): TBD | ||
* Subject: `Node.js security updates for all active release lines, Month Year` | ||
|
||
* [ ] CC `[email protected]` on pre-release | ||
* [ ] Forward the email you receive to `[email protected]`. | ||
|
||
* [ ] Create a new issue in [nodejs/tweet](https://github.com/nodejs/tweet/issues) | ||
|
||
* [ ] Request releaser(s) to start integrating the PRs to be released. | ||
|
||
* [ ] Notify [docker-node](https://github.com/nodejs/docker-node/issues) of upcoming security release date: TBD | ||
|
||
* [ ] Notify build-wg of upcoming security release date by opening an issue | ||
in [nodejs/build](https://github.com/nodejs/build/issues) to request WG members are available to fix any CI issues: TBD | ||
|
||
## Release day | ||
|
||
* [ ] [Lock CI](https://github.com/nodejs/build/blob/HEAD/doc/jenkins-guide.md#before-the-release) | ||
|
||
* [ ] The releaser(s) run the release process to completion. | ||
|
||
* [ ] [Unlock CI](https://github.com/nodejs/build/blob/HEAD/doc/jenkins-guide.md#after-the-release) | ||
|
||
* [ ] Post-release announcement to Nodejs.org blog: https://github.com/nodejs/nodejs.org/pull/5447 | ||
* (Re-PR the pre-approved branch from nodejs-private/nodejs.org-private to | ||
nodejs/nodejs.org) | ||
|
||
* [ ] Post-release announcement in reply email: TBD | ||
|
||
* [ ] Create a new issue in nodejs/tweet | ||
|
||
* [ ] Comment in [docker-node][] issue that release is ready for integration. | ||
The docker-node team will build and release docker image updates. | ||
|
||
* [ ] For every H1 report resolved: | ||
* Close as Resolved | ||
* Request Disclosure | ||
* Request publication of H1 CVE requests | ||
* (Check that the "Version Fixed" field in the CVE is correct, and provide | ||
links to the release blogs in the "Public Reference" section) | ||
|
||
* [ ] PR machine-readable JSON descriptions of the vulnerabilities to the | ||
[core](https://github.com/nodejs/security-wg/tree/HEAD/vuln/core) | ||
vulnerability DB. https://github.com/nodejs/security-wg/pull/1029 | ||
* For each vulnerability add a `#.json` file, one can copy an existing | ||
[json](https://github.com/nodejs/security-wg/blob/0d82062d917cb9ddab88f910559469b2b13812bf/vuln/core/78.json) | ||
file, and increment the latest created file number and use that as the name | ||
of the new file to be added. For example, `79.json`. | ||
|
||
* [ ] Close this issue | ||
|
||
* [ ] Make sure the PRs for the vulnerabilities are closed. | ||
|
||
* [ ] PR in that you stewarded the release in | ||
[Security release stewards](https://github.com/nodejs/node/blob/HEAD/doc/contributing/security-release-process.md#security-release-stewards). | ||
If necessary add the next rotation of the steward rotation. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
import nv from '@pkgjs/nv'; | ||
import auth from './auth.js'; | ||
import Request from './request.js'; | ||
import fs from 'node:fs'; | ||
|
||
export default class SecurityReleaseSteward { | ||
constructor(cli) { | ||
this.cli = cli; | ||
} | ||
|
||
async start() { | ||
const { cli } = this; | ||
const credentials = await auth({ | ||
github: true, | ||
h1: true | ||
}); | ||
|
||
const req = new Request(credentials); | ||
const create = await cli.prompt( | ||
'Create the Next Security Release issue?', | ||
{ defaultAnswer: true }); | ||
if (create) { | ||
const issue = new SecurityReleaseIssue(req); | ||
const content = await issue.buildIssue(cli); | ||
const data = await req.createIssue('Next Security Release', content, { | ||
owner: 'nodejs-private', | ||
repo: 'node-private' | ||
}); | ||
if (data.html_url) { | ||
cli.ok('Created: ' + data.html_url); | ||
} else { | ||
cli.error(data); | ||
} | ||
} | ||
} | ||
} | ||
|
||
class SecurityReleaseIssue { | ||
constructor(req) { | ||
this.req = req; | ||
this.content = ''; | ||
this.title = 'Next Security Release'; | ||
this.affectedLines = {}; | ||
} | ||
|
||
getSecurityIssueTemplate() { | ||
return fs.readFileSync( | ||
new URL( | ||
'./github/templates/next-security-release.md', | ||
import.meta.url | ||
), | ||
'utf-8' | ||
); | ||
} | ||
|
||
async buildIssue(cli) { | ||
this.content = this.getSecurityIssueTemplate(); | ||
cli.info('Getting triaged H1 reports...'); | ||
const reports = await this.req.getTriagedReports(); | ||
await this.fillReports(cli, reports); | ||
|
||
this.fillAffectedLines(Object.keys(this.affectedLines)); | ||
|
||
const target = await cli.prompt('Enter target date in YYYY-MM-DD format:', { | ||
questionType: 'input', | ||
defaultAnswer: 'TBD' | ||
}); | ||
this.fillTargetDate(target); | ||
|
||
return this.content; | ||
} | ||
|
||
async fillReports(cli, reports) { | ||
const supportedVersions = (await nv('supported')) | ||
.map((v) => v.versionName + '.x') | ||
.join(','); | ||
|
||
let reportsContent = ''; | ||
for (const report of reports.data) { | ||
const { id, attributes: { title }, relationships: { severity } } = report; | ||
const reportLevel = severity.data.attributes.rating; | ||
cli.separator(); | ||
cli.info(`Report: ${id} - ${title} (${reportLevel})`); | ||
const include = await cli.prompt( | ||
'Would you like to include this report to the next security release?', | ||
{ defaultAnswer: true }); | ||
if (!include) { | ||
continue; | ||
} | ||
|
||
reportsContent += | ||
` * **[${id}](https://hackerone.com/bugs?subject=nodejs&report_id=${id}) - ${title} (TBD) - (${reportLevel})**\n`; | ||
const versions = await cli.prompt('Which active release lines this report affects?', { | ||
questionType: 'input', | ||
defaultAnswer: supportedVersions | ||
}); | ||
for (const v of versions.split(',')) { | ||
if (!this.affectedLines[v]) this.affectedLines[v] = true; | ||
reportsContent += ` * ${v} - TBD\n`; | ||
} | ||
} | ||
this.content = this.content.replace('%REPORTS%', reportsContent); | ||
} | ||
|
||
fillAffectedLines(affectedLines) { | ||
let affected = ''; | ||
for (const line of affectedLines) { | ||
affected += ` * ${line} - TBD\n`; | ||
} | ||
this.content = | ||
this.content.replace('%AFFECTED_LINES%', affected); | ||
} | ||
|
||
fillTargetDate(date) { | ||
this.content = this.content.replace('%RELEASE_DATE%', date); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters