NPMプロジェクトにおける脆弱性の姑息的解決法(override)
はじめに
仕事で、Snykが検出した脆弱性に対処する機会があったので、ベストプラクティスとは言い難いが、npmのoverrideについて検証する。ちなみに、Javaのgradle関してはdependency constraintがある。
検証環境
検証した環境は以下のとおりだが、nodeとnpmのバージョンには注意してほしい。
overrideの機能はnpm v8.3.0から導入されたものであるのと同時に、バージョンが低いとlockfileが更新されなかったり、破損してしまい、npm ciがうまく動かなかったりするようだ。
詳しくは、このissueを参照してほしい。
OS | Arch Linux 6.6.1-arch1-1 |
---|---|
node | v18.18.2 |
npm | 10.2.3 |
事前準備
脆弱性を含むプロジェクトを再現してみる
# 質問にはテキトーに答える
$ npx create-react-app my-app
以下のようにNPMからも脆弱性を指摘してくれている
added 1460 packages, and audited 1461 packages in 1m
242 packages are looking for funding
run `npm fund` for details
8 vulnerabilities (2 moderate, 6 high)
To address all issues (including breaking changes), run:
npm audit fix --force
Run `npm audit` for details.
ここで、本来であればnpm audit fix --force
を行って、直接依存のパッケージを更新することにより、解決を試みるが、今回は最新版のreact-create-appで行っているのでこれ以上メジャーバージョンを上げることはできない。
また、react-create-appに関しても、最近では脆弱性が放置され気味のようだ。
Snykスキャン
スキャンの仕方についてはここでは、省略する。
一旦、Snykでこのプロジェクトのスキャン結果を見てみる。複数の脆弱性を確認できるが、
High Severityのものを1つ抜粋すると
Regular Expression Denial of Service (ReDoS) (High Severity)
Package Manager: npm
Vulnerable module: nth-check
Paths : react-scripts@5.0.1 › @svgr/webpack@5.5.0 › @svgr/plugin-svgo@5.5.0 › svgo@1.3.2 › css-select@2.1.0
› nth-check@1.0.2
どうやら、Snykによる指摘のPathsを見ると明らかだが、間接的に依存しているnth-check@1.0.2に脆弱性が出ているようだ。
$ npm ls nth-check
my-app@0.1.0 /home/chiiko/github.com/NaGaii1994/fix_vulnerability_npm/my-app
└─┬ react-scripts@5.0.1
├─┬ @svgr/webpack@5.5.0
│ └─┬ @svgr/plugin-svgo@5.5.0
│ └─┬ svgo@1.3.2
│ └─┬ css-select@2.1.0
│ └── nth-check@1.0.2 # ←間接的依存関係の末端に脆弱性を含むパッケージが存在
└─┬ html-webpack-plugin@5.5.3
└─┬ pretty-error@4.0.0
└─┬ renderkid@3.0.0
└─┬ css-select@4.3.0
└── nth-check@2.1.1
remediationとしてはnth-checkのバージョンを2.1.1以上に上げる必要があるので、それをnpmのoverrideを用いて行ってみる。
以下のようにpackage.jsonを修正した。
"dependencies": {
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
+ "overrides": {
+ "nth-check": "2.1.1"
+ },
パッケージを更新
$ npm install
up to date, audited 1531 packages in 4s
246 packages are looking for funding
run `npm fund` for details
3 moderate severity vulnerabilities
To address all issues (including breaking changes), run:
npm audit fix --force
Run `npm audit` for details.
どうやら、修正されたらしく6個あった high vulnerabilitiesが消えている。
また、修正後の依存関係ツリーを表示すると以下のように間接依存のnth-checkのバージョンを上書きできたことがわかる。
$ npm ls nth-check
my-app@0.1.0 /home/chiiko/github.com/NaGaii1994/fix_vulnerability_npm/my-app
└─┬ react-scripts@5.0.1
├─┬ @svgr/webpack@5.5.0
│ └─┬ @svgr/plugin-svgo@5.5.0
│ └─┬ svgo@1.3.2
│ └─┬ css-select@2.1.0
- │ └── nth-check@1.0.2
+ │ └── nth-check@2.1.1 overridden
└─┬ html-webpack-plugin@5.5.3
└─┬ pretty-error@4.0.0
└─┬ renderkid@3.0.0
└─┬ css-select@4.3.0
- └── nth-check@2.1.1
+ └── nth-check@2.1.1 deduped
npm ci
私が仕事で使用している環境では、nodeとnpmのバージョンが古く動作しなかったため、念の為検証する。
$ rm -rf node_modules
$ npm ci
npm WARN deprecated @babel/plugin-proposal-numeric-separator@7.18.6: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-numeric-separator instead.
npm WARN deprecated @babel/plugin-proposal-class-properties@7.18.6: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.
npm WARN deprecated @babel/plugin-proposal-private-methods@7.18.6: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-methods instead.
npm WARN deprecated stable@0.1.8: Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility
npm WARN deprecated @babel/plugin-proposal-nullish-coalescing-operator@7.18.6: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead.
npm WARN deprecated rollup-plugin-terser@7.0.2: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser
npm WARN deprecated @babel/plugin-proposal-optional-chaining@7.21.0: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead.
npm WARN deprecated w3c-hr-time@1.0.2: Use your platform's native performance.now() and performance.timeOrigin.
npm WARN deprecated sourcemap-codec@1.4.8: Please use @jridgewell/sourcemap-codec instead
npm WARN deprecated workbox-cacheable-response@6.6.0: workbox-background-sync@6.6.0
npm WARN deprecated svgo@1.3.2: This SVGO version is no longer supported. Upgrade to v2.x.x.
added 1530 packages, and audited 1531 packages in 22s
246 packages are looking for funding
run `npm fund` for details
3 moderate severity vulnerabilities
To address all issues (including breaking changes), run:
npm audit fix --force
Run `npm audit` for details.
lockfileは破損おらず、正常にnpm ciできているようだ。
Discussion