概要
npm (yarn) によるパッケージ管理は非常に楽ですが、ときには脆弱性を含むパッケージを入れてしまうこともあるかもしれません。
CI/CD パイプラインで 脆弱性チェックを行うのも良いかもしれませんが、ローカルで依存パッケージを追加・コミットする前に脆弱性チェックを行い、無駄なコミットが含まれないようにするほうがスマートだと私は思っています。
そこで、 lint-staged
とhusky
を使って、依存関係を追加した場合のcommitで脆弱性チェック(audit
)をする設定をします。
関連パッケージ等
- yarn (npmでも脆弱性チェックはできますが、ここではyarnを使います)
- lint-staged
- husky
やったこと(結論)
husky
とlint-staged
をdevDependenciesに入れて、package.json
に以下を追加しましょう。
{
"scripts": {
"audit:moderate": "yarn audit --level moderate || EXIT_CODE=$? && if [ $EXIT_CODE -ge 4 ]; then exit EXIT_CODE; else exit 0; fi;"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"yarn.lock": [
"audit:moderate"
]
},
}
設定の詳細
- 脆弱性チェック
- 脆弱性チェックを、中レベル以上に限定する
- コミット時に脆弱性チェックが走るようにする
- 中レベル以上の脆弱性チェックが正常終了するようにする
1. 脆弱性チェック
yarn には 脆弱性チェックを行う audit
というコマンドがあるので、それを使います。
詳細は公式ドキュメント:https://classic.yarnpkg.com/en/docs/cli/audit/#toc-yarn-audit
$ yarn audit
もし脆弱性のあるパッケージがある場合、下記の表のような形式で脆弱性のあるパッケージが出力されます。
$ yarn audit
yarn audit v1.22.5
┌───────────────┬──────────────────────────────────────────────────────────────┐
│ low │ Denial of Service │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package │ node-fetch │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Patched in │ >=2.6.1 <3.0.0-beta.1|| >= 3.0.0-beta.9 │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ next │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path │ next > @ampproject/toolbox-optimizer > │
│ │ @ampproject/toolbox-core > cross-fetch > node-fetch │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info │ https://www.npmjs.com/advisories/1556 │
└───────────────┴──────────────────────────────────────────────────────────────┘
...
2. 脆弱性チェックを、中レベル以上に限定する
すべてのレベルの脆弱性を排除することが望ましいですが、依存パッケージのさらに依存パッケージの低レベル脆弱性まで気にすると、実運用する上では使えないパッケージが増えてしまいます。
例えば、React開発で最も優れている(と私が思う) Next.js
でも、上記のようにnode-fetch
などのパッケージの低レベル脆弱性が対応しきれていません。
そこで、中程度(moderate
)以上の脆弱性のみを検知したいと思います。
$ yarn audit --level moderate
yarn audit v1.22.5
5 vulnerabilities found - Packages audited: 2235
Severity: 5 Low
✨ Done in 2.02s.
低レベル脆弱性が検知されているものの、レベルをmoderate
にしているのでコマンドは脆弱性のレポートを表示することなく終了しています。
3. コミット時に脆弱性チェックが走るようにする
lint-staged
とhusky
を使って、依存パッケージに変更があるコミットで自動で脆弱性チェックが走るようにします。
これらの設定は主にeslint
やprettier
と組み合わせて使われており有名かと思うので割愛します。
依存パッケージに変更がある場合、yarn.lock
が更新されているので、yarn.lock
のコミットをトリガーに脆弱性チェックを行います。
{
"husky": {
"hooks": {
"pre-commit": "lint-staged",
}
},
"lint-staged": {
"yarn.lock": [
"yarn audit --level moderate"
]
},
}
4. 中レベル以上の脆弱性チェックが正常終了するようにする
前述の脆弱性チェックコマンドは一見正常終了に見えますが、実はエラー終了扱いとなっています。
試しにprecommit
を走らせると、下記のように。
$ git commit yarn.lock
husky > pre-commit (node v12.18.0)
✔ Preparing...
⚠ Running tasks...
↓ No staged files match *.{js,json,md,yaml,yml} [SKIPPED]
↓ No staged files match *.{ts,tsx} [SKIPPED]
↓ No staged files match package.json [SKIPPED]
❯ Running tasks for yarn.lock
✖ yarn audit:moderate [FAILED]
↓ Skipped because of errors from tasks. [SKIPPED]
✔ Reverting to original state because of errors...
✔ Cleaning up...
✖ yarn audit:moderate:
error Command failed with exit code 2.
$ yarn audit --level moderate /Users/y.shogoro/dev/src/bitbucket.org/wanocoltd/tunecorejapan_frontend/yarn.lock
5 vulnerabilities found - Packages audited: 2235
Severity: 5 Low
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
husky > pre-commit hook failed (add --no-verify to bypass)
これは、yarn audit
が検知した脆弱性のレベルに応じて終了コードを変更しているからです。
https://classic.yarnpkg.com/en/docs/cli/audit/#toc-yarn-audit
The command will exit with a non-0 exit code if there are issues of any severity found. The exit code will be a mask of the severities.
1 for INFO
2 for LOW
4 for MODERATE
8 for HIGH
16 for CRITICAL
今回は、中程度の脆弱性から検知すると決めたので、exit codeが4以上の場合のみ以上終了とみなすscriptにします。
{
"scripts": {
"audit:moderate": "yarn audit --level moderate || EXIT_CODE=$? && if [ $EXIT_CODE -ge 4 ]; then exit EXIT_CODE; else exit 0; fi;"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"yarn.lock": [
"audit:moderate"
]
},
}
以上で完成です。
これで、依存パッケージに変更があった際、中程度以上の脆弱性が自動でチェックされるようになりました。
余談
設定されている方も多いかと思いますが、lint-staged
とhusky
を使った設定で、以下もおすすめです。
特に、なんでもかんでもlint
かけたい気持ちなのでsort-package-json
はイチオシです。
-
json
やmd
,yaml
などにprettier
をかけて整形する -
package.json
にsort-package-json
をかけて、keyの並べ替えを行う -
js
,ts
にjest --findRelatedTests
をかけて、関連するテストのみ実行する
{
"lint-staged": {
"*.{json,md,yaml,yml}": [
"prettier --write"
],
"*.{js,jsx,ts,tsx}": [
"eslint --fix",
"jest --findRelatedTests"
],
"package.json": [
"sort-package-json"
],
}
}
公式ページ
Wano
Wanoは積極的にエンジニア採用 / デザイナー採用を行なっています!
まずはオンラインでVPoEとのカジュアル面談から。お好きな入り口からお気軽にお声がけください!
- Wano Recruitページ https://group.wano.co.jp/recruit/
- QiitaJobs https://jobs.qiita.com/employers/wano-inc/postings/1297
- Wantedly https://www.wantedly.com/companies/wano/projects
- Findy https://findy-code.io/companies/522
- CINRA.JOB https://job.cinra.net/company/wano/