mirror of https://github.com/actions/toolkit
Resolve vulnerabilities found by `npm audit` (#846)
parent
11601c0d2d
commit
9167ce1f3a
|
@ -31,8 +31,9 @@ jobs:
|
||||||
- name: Bootstrap
|
- name: Bootstrap
|
||||||
run: npm run bootstrap
|
run: npm run bootstrap
|
||||||
|
|
||||||
- name: audit tools #disabled while we wait for https://github.com/actions/toolkit/issues/539
|
- name: audit tools
|
||||||
run: npm audit --audit-level=moderate
|
# `|| npm audit` to pretty-print the output if vulnerabilies are found after filtering.
|
||||||
|
run: npm audit --audit-level=moderate --json | scripts/audit-allow-list || npm audit --audit-level=moderate
|
||||||
|
|
||||||
- name: audit packages
|
- name: audit packages
|
||||||
run: npm run audit-all
|
run: npm run audit-all
|
||||||
|
|
|
@ -13828,9 +13828,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"normalize-url": {
|
"normalize-url": {
|
||||||
"version": "3.3.0",
|
"version": "6.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.0.1.tgz",
|
||||||
"integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==",
|
"integrity": "sha512-VU4pzAuh7Kip71XEmO9aNREYAdMHFGTVj/i+CaTImS8x0i1d3jUZkXhqluy/PRgjPLMgsLQulYY3PJ/aSbSjpQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"npm-bundled": {
|
"npm-bundled": {
|
||||||
|
@ -14487,13 +14487,13 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"parse-url": {
|
"parse-url": {
|
||||||
"version": "5.0.2",
|
"version": "5.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/parse-url/-/parse-url-5.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/parse-url/-/parse-url-5.0.3.tgz",
|
||||||
"integrity": "sha512-Czj+GIit4cdWtxo3ISZCvLiUjErSo0iI3wJ+q9Oi3QuMYTI6OZu+7cewMWZ+C1YAnKhYTk6/TLuhIgCypLthPA==",
|
"integrity": "sha512-nrLCVMJpqo12X8uUJT4GJPd5AFaTOrGx/QpJy3HNcVtq0AZSstVIsnxS5fqNPuoqMUs3MyfBoOP6Zvu2Arok5A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"is-ssh": "^1.3.0",
|
"is-ssh": "^1.3.0",
|
||||||
"normalize-url": "^3.3.0",
|
"normalize-url": "^6.0.1",
|
||||||
"parse-path": "^4.0.0",
|
"parse-path": "^4.0.0",
|
||||||
"protocols": "^1.4.0"
|
"protocols": "^1.4.0"
|
||||||
}
|
}
|
||||||
|
@ -16416,9 +16416,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"trim-newlines": {
|
"trim-newlines": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz",
|
||||||
"integrity": "sha512-C4+gOpvmxaSMKuEf9Qc134F1ZuOHVXKRbtEflf4NTtuuJDEIJ9p5PXsalL8SkeRw+qit1Mo+yuvMPAKwWg/1hA==",
|
"integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"trim-off-newlines": {
|
"trim-off-newlines": {
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
/*
|
||||||
|
This script takes the output of npm audit --json from stdin
|
||||||
|
and writes a filtered version to stdout.
|
||||||
|
The filtered version will have the entries listed in `AUDIT_ALLOW_LIST` removed.
|
||||||
|
Specifically, each property of `vulnerabilities` in the input is matched by name in the allow list.
|
||||||
|
|
||||||
|
Sample output of `npm audit --json` (NPM v6):
|
||||||
|
|
||||||
|
{
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"action": "review",
|
||||||
|
"module": "trim-newlines",
|
||||||
|
"resolves": [
|
||||||
|
{
|
||||||
|
"id": 1753,
|
||||||
|
"path": "lerna>@lerna/publish>@lerna/version>@lerna/conventional-commits>conventional-changelog-core>get-pkg-repo>meow>trim-newlines",
|
||||||
|
"dev": true,
|
||||||
|
"optional": false,
|
||||||
|
"bundled": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// Other properties ...
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
The reason we have this script is that there may be low-severity or unexploitable vulnerabilities
|
||||||
|
that have not yet been fixed in newer versions of the package.
|
||||||
|
|
||||||
|
Note: if we update to NPM v7, we will have to change this script because the `npm audit` output will be different.
|
||||||
|
See commit 935647112d96fa5cf82e61314f7135376d24f291 in https://github.com/actions/toolkit/pull/846.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict'
|
||||||
|
const fs = require('fs')
|
||||||
|
|
||||||
|
const USAGE = "Usage: npm audit --json | scripts/audit-allow-list"
|
||||||
|
|
||||||
|
// To add entires to the allow list:
|
||||||
|
// - Run `npm audit --json`
|
||||||
|
// - Copy `path` from each `actions[k].resolves` you want to allow
|
||||||
|
// - Fill in the `advisoryUrl` and `justification` (these are just for documentation)
|
||||||
|
const AUDIT_ALLOW_LIST = [
|
||||||
|
{
|
||||||
|
path: "lerna>@lerna/publish>@lerna/version>@lerna/conventional-commits>conventional-changelog-core>get-pkg-repo>meow>trim-newlines",
|
||||||
|
advisoryUrl: "https://www.npmjs.com/advisories/1753",
|
||||||
|
justification: "dependency of lerna (dev only); low severity"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "lerna>@lerna/version>@lerna/conventional-commits>conventional-changelog-core>get-pkg-repo>meow>trim-newlines",
|
||||||
|
advisoryUrl: "https://www.npmjs.com/advisories/1753",
|
||||||
|
justification: "dependency of lerna (dev only); low severity"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param audits - JavaScript object matching the schema of `npm audit --json`
|
||||||
|
* @param allowedPaths - List of dependency paths to exclude from the audit
|
||||||
|
*/
|
||||||
|
function filterVulnerabilities(audits, allowedPaths) {
|
||||||
|
const vulnerabilities = audits.actions.flatMap(x => x.resolves)
|
||||||
|
return vulnerabilities.filter(x => !allowedPaths.includes(x.path))
|
||||||
|
}
|
||||||
|
|
||||||
|
const input = fs.readFileSync("/dev/stdin", "utf-8")
|
||||||
|
if (input === "") {
|
||||||
|
console.error(USAGE)
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
const audits = JSON.parse(input)
|
||||||
|
const allowedPaths = AUDIT_ALLOW_LIST.map(x => x.path)
|
||||||
|
// This function assumes `audits` has the right structure.
|
||||||
|
// Just let the error terminate the process if the input doesn't match the schema.
|
||||||
|
const remainingVulnerabilities = filterVulnerabilities(audits, allowedPaths)
|
||||||
|
|
||||||
|
// `npm audit` will return exit code 1 if it finds vulnerabilities.
|
||||||
|
// This script should do the same.
|
||||||
|
const numVulnerabilities = remainingVulnerabilities.length
|
||||||
|
if (numVulnerabilities > 0) {
|
||||||
|
const pluralized = numVulnerabilities === 1 ? "y" : "ies"
|
||||||
|
console.log(`Found ${numVulnerabilities} unrecognized vulnerabilit${pluralized} from \`npm audit\`:`)
|
||||||
|
console.log(JSON.stringify(remainingVulnerabilities, null, 2))
|
||||||
|
process.exit(1)
|
||||||
|
}
|
Loading…
Reference in New Issue