From 6c907192f372b597345d75fec328da561f1eecbe Mon Sep 17 00:00:00 2001 From: Vesa Luusua Date: Mon, 4 Feb 2019 21:24:57 +0200 Subject: [PATCH] Add audit script to check dependency vulnerabilities --- .circleci/config.yml | 24 ++++++++++++ .nsprc | 10 ++--- package.json | 2 + scripts/audit.js | 90 ++++++++++++++++++++++++++++++++++++++++++++ yarn.lock | 30 +++++++++++++++ 5 files changed, 150 insertions(+), 6 deletions(-) create mode 100644 scripts/audit.js diff --git a/.circleci/config.yml b/.circleci/config.yml index 4c1ca3e9ae..ba44aee3b7 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -69,6 +69,29 @@ jobs: - run: name: Build client application command: yarn run build + audit: + docker: + - image: circleci/node:10.14 + steps: + - checkout + - restore_cache: + name: Restore Yarn Package Cache + keys: + - yarn-packages-{{ .Branch }}-{{ checksum "yarn.lock" }} + - yarn-packages-{{ .Branch }} + - yarn-packages-master + - yarn-packages- + - run: + name: Install Dependencies + command: yarn install + - save_cache: + name: Save Yarn Package Cache + key: yarn-packages-{{ .Branch }}-{{ checksum "yarn.lock" }} + paths: + - node_modules/ + - run: + name: Audit dependencies + command: yarn run audit workflows: version: 2 format_test_build_audit: @@ -76,3 +99,4 @@ workflows: - format - test - build + - audit diff --git a/.nsprc b/.nsprc index eb9adf46b3..8886e3c69f 100644 --- a/.nsprc +++ b/.nsprc @@ -1,10 +1,8 @@ { "exceptions": [ - "https://nodesecurity.io/advisories/532", - "https://nodesecurity.io/advisories/157", - "https://nodesecurity.io/advisories/577", - "https://nodesecurity.io/advisories/654", - "https://nodesecurity.io/advisories/664", - "https://nodesecurity.io/advisories/678" + "https://npmjs.com/advisories/532", + "https://npmjs.com/advisories/577", + "https://npmjs.com/advisories/722", + "https://npmjs.com/advisories/725" ] } diff --git a/package.json b/package.json index 71bdccf5e8..e2b725037a 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,7 @@ "url": "^0.11.0" }, "devDependencies": { + "bfj": "^6.1.1", "chalk": "^2.4.1", "enzyme": "^3.7.0", "enzyme-adapter-react-16": "^1.7.0", @@ -65,6 +66,7 @@ "prettier": "^1.15.3" }, "scripts": { + "audit": "yarn audit --json | node scripts/audit.js", "clean": "rm -rf build/*", "config": "node scripts/config.js", "dev": "node scripts/config.js --check && sharetribe-scripts start", diff --git a/scripts/audit.js b/scripts/audit.js new file mode 100644 index 0000000000..508e6e2ec8 --- /dev/null +++ b/scripts/audit.js @@ -0,0 +1,90 @@ +// Check possible npm dependency vulnerabilities +// Usage: execute "yarn run audit" in the shell +// +// You can add exceptions through .nsprc file, which is a hidden file in root folder. +// +// Note: to use this script, you should pipe in the output of 'yarn audit --json' + +const bfj = require('bfj'); +const fs = require('fs'); + +const INDENT = ' '; +const isAuditAdvisory = o => o.type === 'auditAdvisory'; + +// get an advisory or empty object +const getAdvisory = o => (!o ? {} : !o.data ? {} : !o.data.advisory ? {} : o.data.advisory); +// get a resolution or empty object +const getResolution = o => (!o ? {} : !o.data ? {} : !o.data.resolution ? {} : o.data.resolution); + +// Read exceptions +let exceptions = []; +bfj + .parse(fs.createReadStream('.nsprc'), {}) + .then(data => { + exceptions = data.exceptions ? data.exceptions : []; + }) + .catch(error => { + console.error('Could not process .nsprc file.'); + process.exit(1); + }); + +// Read the output of 'yarn audit --json', which should be piped in through stdin +const stdinStream = process.stdin.resume(); +let advisories = {}; +bfj + .match(stdinStream, (key, value, depth) => depth === 0, { ndjson: true }) + .on('data', object => { + if (isAuditAdvisory(object)) { + const { id, severity, title, url } = getAdvisory(object); + const { path } = getResolution(object); + const isInExceptionList = url && exceptions.includes(url); + + if (!isInExceptionList && url && path) { + const advisory = advisories[id] ? advisories[id] : { url, severity, title }; + const paths = advisory.paths ? advisory.paths : []; + advisories[id] = { ...advisory, paths: paths.concat(path) }; + } + } + }) + .on('dataError', error => { + // A syntax error was found in the JSON + console.error( + `An error occurred while processing data. + You need to pipe the results of "yarn audit --json" to this script from shell. + Error`, + error + ); + process.exit(1); + }) + .on('error', error => { + // Some kind of operational error occurred + console.error( + `An error occurred while processing data. + You need to pipe the results of "yarn audit --json" to this script from shell. + Error`, + error + ); + process.exit(1); + }) + .on('end', error => { + const advisoryKeys = Object.keys(advisories); + if (advisoryKeys.length > 0) { + console.log('Vulneralibilities found:'); + console.log('\n----------------------------------------\n'); + + advisoryKeys.forEach(key => { + const { title, severity, url, paths } = advisories[key]; + console.log(key, `(${title})`); + console.log('Severity:', severity); + console.log('More info:', url); + console.log('Affected dependencies:'); + paths.forEach(path => { + console.log(INDENT, path); + }); + console.log('\n----------------------------------------\n'); + }); + process.exit(1); + } else { + process.exit(); + } + }); diff --git a/yarn.lock b/yarn.lock index 6d748f1417..d224fb9f3d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1220,6 +1220,16 @@ bcrypt-pbkdf@^1.0.0: dependencies: tweetnacl "^0.14.3" +bfj@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/bfj/-/bfj-6.1.1.tgz#05a3b7784fbd72cfa3c22e56002ef99336516c48" + integrity sha512-+GUNvzHR4nRyGybQc2WpNJL4MJazMuvf92ueIyA0bIkPRwhhQu3IfZQ2PSoVPpCBJfmoSdOxu5rnotfFLlvYRQ== + dependencies: + bluebird "^3.5.1" + check-types "^7.3.0" + hoopy "^0.1.2" + tryer "^1.0.0" + big.js@^3.1.3: version "3.2.0" resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" @@ -1232,6 +1242,11 @@ bluebird@^3.4.7: version "3.5.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.2.tgz#1be0908e054a751754549c270489c1505d4ab15a" +bluebird@^3.5.1: + version "3.5.3" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.3.tgz#7d01c6f9616c9a51ab0f8c549a79dfe6ec33efa7" + integrity sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw== + bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: version "4.11.8" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" @@ -1610,6 +1625,11 @@ chardet@^0.7.0: resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== +check-types@^7.3.0: + version "7.4.0" + resolved "https://registry.yarnpkg.com/check-types/-/check-types-7.4.0.tgz#0378ec1b9616ec71f774931a3c6516fad8c152f4" + integrity sha512-YbulWHdfP99UfZ73NcUDlNJhEIDgm9Doq9GhpyXbF+7Aegi3CVV7qqMCKTTqJxlvEvnQBp9IA+dxsGN6xK/nSg== + cheerio@^1.0.0-rc.2: version "1.0.0-rc.2" resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.2.tgz#4b9f53a81b27e4d5dac31c0ffd0cfa03cc6830db" @@ -3821,6 +3841,11 @@ homedir-polyfill@^1.0.1: dependencies: parse-passwd "^1.0.0" +hoopy@^0.1.2: + version "0.1.4" + resolved "https://registry.yarnpkg.com/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d" + integrity sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ== + hosted-git-info@^2.1.4: version "2.5.0" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c" @@ -8380,6 +8405,11 @@ trim-right@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" +tryer@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8" + integrity sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA== + tslib@^1.9.0, tslib@^1.9.3: version "1.9.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286"