npm パッケージのセキュリティアップデートをする備忘録
npm
パッケージの依存関係にセキュリティ警告があった際のアップデートについて、自分が進めた備忘録をさくっとまとめてみました。
npm audit
npm audit
はnpm
パッケージ内で依存しているライブラリにおいて、セキュリティ上の既知の脆弱性を持つものを洗い出して警告してくれます。
ということでまずはpackage.json
直下でnpm audit
を実行。
$ npm audit
# npm audit report
@babel/traverse <7.23.2
Severity: critical
Babel vulnerable to arbitrary code execution when compiling specifically crafted malicious code - https://github.com/advisories/GHSA-67hx-6x53-jw92
fix available via `npm audit fix`
node_modules/@babel/traverse
body-parser <1.20.3
Severity: high
body-parser vulnerable to denial of service when url encoding is enabled - https://github.com/advisories/GHSA-qwcr-r2fm-qrc7
fix available via `npm audit fix`
node_modules/body-parser
express <=4.21.1 || 5.0.0-alpha.1 - 5.0.0
Depends on vulnerable versions of body-parser
Depends on vulnerable versions of cookie
Depends on vulnerable versions of path-to-regexp
Depends on vulnerable versions of send
Depends on vulnerable versions of serve-static
node_modules/express
...
path-to-regexp <=0.1.11
Severity: high
path-to-regexp outputs backtracking regular expressions - https://github.com/advisories/GHSA-9wv6-86v2-598j
Unpatched `path-to-regexp` ReDoS in 0.1.x - https://github.com/advisories/GHSA-rhx6-c78j-4q9w
fix available via `npm audit fix --force`
Will install gatsby@3.3.1, which is a breaking change
node_modules/gatsby/node_modules/path-to-regexp
node_modules/path-to-regexp
yaml 2.0.0-5 - 2.2.1
Severity: high
Uncaught Exception in yaml - https://github.com/advisories/GHSA-f9xv-q969-pqx4
fix available via `npm audit fix`
node_modules/yaml-loader/node_modules/yaml
29 vulnerabilities (10 low, 4 moderate, 14 high, 1 critical)
To address issues that do not require attention, run:
npm audit fix
To address all issues (including breaking changes), run:
npm audit fix --force
脆弱性が見つかった場合、ヤバさに応じてCritical
からLow
まで 4 段階があります。
今回の例では、10 つの任意レベル(Low)、4 つの時間がある時にアプデして欲しいレベル(Moderate)、14 個の優先度高くアプデするレベル(High)、1 つのすぐさまアプデしないとダメそうレベル(Critical)のセキュリティレポートを取得したことになります。
npm audit fix
脆弱性のうちfix available via npm audit fix
となっている依存ライブラリは、ライブラリ同士の依存関係に関して互換性のある更新が現状すでにできることを示しています。
こちらがあった折には、とりあえず脳死でサブコマンドのnpm audit fix
を実行してみます。脆弱な依存関係に対して、互換性のある更新を自動的にアップデートしてくれます。十中八九うまくいい感じにあってくれます。
fix available via npm audit fix --force
とある場合は、サクッと 1 コマンドで行かないので後回しにします。
npm audit fix --force
はわりと無理やりアップデートしてしまう印象なので、環境自体がぶっ壊れる可能性があるため実行しません。
とりあえずnpm audit fix
実行します。
$ npm audit fix
npm warn ERESOLVE overriding peer dependency
npm warn While resolving: react-server-dom-webpack@0.0.0-experimental-c8b778b7f-20220825
npm warn Found: react@18.2.0
npm warn node_modules/react
npm warn react@"^18.2.0" from the root project
npm warn 6 more (@gatsbyjs/reach-router, gatsby, gatsby-link, ...)
npm warn
npm warn Could not resolve dependency:
npm warn peer react@"0.0.0-experimental-c8b778b7f-20220825" from react-server-dom-webpack@0.0.0-experimental-c8b778b7f-20220825
npm warn node_modules/react-server-dom-webpack
npm warn react-server-dom-webpack@"0.0.0-experimental-c8b778b7f-20220825" from gatsby@5.14.1
npm warn node_modules/gatsby
npm warn
npm warn Conflicting peer dependency: react@0.0.0-experimental-c8b778b7f-20220825
npm warn node_modules/react
npm warn peer react@"0.0.0-experimental-c8b778b7f-20220825" from react-server-dom-webpack@0.0.0-experimental-c8b778b7f-20220825
npm warn node_modules/react-server-dom-webpack
npm warn react-server-dom-webpack@"0.0.0-experimental-c8b778b7f-20220825" from gatsby@5.14.1
npm warn node_modules/gatsby
changed 1 package, and audited 1399 packages in 19s
271 packages are looking for funding
run `npm fund` for details
# npm audit report
cookie <0.7.0
cookie accepts cookie name, path, and domain with out of bounds characters - https://github.com/advisories/GHSA-pxg6-pf52-xh8x
fix available via `npm audit fix --force`
Will install gatsby@3.3.1, which is a breaking change
node_modules/cookie
node_modules/gatsby/node_modules/cookie
engine.io 1.8.0 - 6.6.1
Depends on vulnerable versions of cookie
node_modules/engine.io
socket.io 1.6.0 - 4.7.5
Depends on vulnerable versions of engine.io
node_modules/socket.io
gatsby >=1.2.0
Depends on vulnerable versions of babel-plugin-remove-graphql-queries
Depends on vulnerable versions of cookie
Depends on vulnerable versions of gatsby-plugin-page-creator
Depends on vulnerable versions of gatsby-plugin-typescript
Depends on vulnerable versions of gatsby-plugin-utils
Depends on vulnerable versions of path-to-regexp
Depends on vulnerable versions of socket.io
node_modules/gatsby
babel-plugin-remove-graphql-queries 3.14.0-alpha-qe-sm.33 - 3.14.0-next.4 || >=4.0.0-alpha-9689ff.4
Depends on vulnerable versions of gatsby
node_modules/babel-plugin-remove-graphql-queries
gatsby-plugin-page-creator 3.14.0-alpha-qe-sm.9 - 3.14.0-next.3 || >=4.0.0-alpha-9689ff.5
Depends on vulnerable versions of gatsby
Depends on vulnerable versions of gatsby-plugin-utils
node_modules/gatsby-plugin-page-creator
gatsby-plugin-postcss 4.14.0-alpha-qe-sm.46 - 4.14.0-next.2 || >=5.0.0-alpha-9689ff.5
Depends on vulnerable versions of gatsby
node_modules/gatsby-plugin-postcss
gatsby-plugin-typescript 3.14.0-alpha-qe-sm.33 - 3.14.0-next.4 || >=4.0.0-alpha-9689ff.4
Depends on vulnerable versions of babel-plugin-remove-graphql-queries
Depends on vulnerable versions of gatsby
node_modules/gatsby-plugin-typescript
gatsby-plugin-utils 1.14.0-alpha-qe-sm.46 - 1.14.0-next.2 || >=2.0.0-alpha-9689ff.5
Depends on vulnerable versions of gatsby
node_modules/gatsby-plugin-utils
path-to-regexp <0.1.12
Severity: moderate
Unpatched `path-to-regexp` ReDoS in 0.1.x - https://github.com/advisories/GHSA-rhx6-c78j-4q9w
fix available via `npm audit fix --force`
Will install gatsby@3.3.1, which is a breaking change
node_modules/path-to-regexp
10 vulnerabilities (8 low, 2 moderate)
To address issues that do not require attention, run:
npm audit fix
To address all issues (including breaking changes), run:
npm audit fix --force
cookie
とpath-to-regexp
というのは、自動では互換性を保ってのアップデートができなかったことを示していそうです。
npm outdated
ここでcookie
とpath-to-regexp
のアップデートについて考える前に、これらが依存している大元のライブラリをアップデートすることで解決できないか確認します。
なぜかというと、大元のライブラリをアップデートすることで、もしかしたらライブラリの方で依存ライブラリをメンテしてくれていて、よしなに依存関係もアップデートされるかも?という淡い期待からですね。
$ npm list cookie
my-cording-standards@1.0.0 /Users/moepyxxx/dev/github.com/moepyxxx/cording_standards/my-cording-standards
└─┬ gatsby@5.14.1
├── cookie@0.5.0
├─┬ express@4.21.2
│ └── cookie@0.7.1
└─┬ socket.io@4.7.1
└─┬ engine.io@6.5.5
└── cookie@0.4.2
$ npm list path-to-regexp
my-cording-standards@1.0.0 /Users/moepyxxx/dev/github.com/moepyxxx/cording_standards/app
└─┬ gatsby@5.14.1
├─┬ express@4.21.2
│ └── path-to-regexp@0.1.12
└── path-to-regexp@0.1.10
どちらもgatsby
に依存しているみたいなので、gatsby
がアップデートできれば、もしかしたら望みがあるかもしれません。
npm outdated
コマンドは、package.json
に記載された主要の依存ライブラリ(dependencies
やdevDependencies
など)の指定したバージョン範囲内において、アップデート可能なものがあるかをチェックしてくれます。
このバージョン範囲の概念は、ここでは説明を省きますが、他で詳しく載っていますので参考にしてみてください。
いわゆる"hoge": ^1.2.3
みたいな指定のことですね。たとえば上記のようにキャレットの記述がある場合、hoge というライブラリはメジャーバージョン(たとえば2.0.0
)へのアップデートが許可されていませんが、マイナーアップデートやパッチアップデート(たとえば1.3.0
や1.2.4
)は OK としています。
npm outdated
はこの指定の範囲内でアップデートできるものを探してみます。
$ npm outdated
Package Current Wanted Latest Location Depended by
@types/node 20.17.12 20.17.14 22.10.7 node_modules/@types/node app
@types/react 18.2.56 18.3.18 19.0.7 node_modules/@types/react app
@types/react-dom 18.2.19 18.3.5 19.0.3 node_modules/@types/react-dom app
postcss 8.4.49 8.5.1 8.5.1 node_modules/postcss app
react 18.2.0 18.3.1 19.0.0 node_modules/react app
react-dom 18.2.0 18.3.1 19.0.0 node_modules/react-dom app
typescript 5.3.3 5.7.3 5.7.3 node_modules/typescript app
今回は、なさそうです。gatsby
は最新になっているみたいでした。
念のため以下で最新バージョンも問い合わせてみましたが、package.json
の中身と突合してみました。
$ npm view gatsby
gatsby@5.14.1 | MIT | deps: 167 | versions: 2979
Blazing fast modern site generator for React
https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby#readme
keywords: blog, generator, jekyll, markdown, react, ssg, website
bin: gatsby
package.json の override
こうなったら、cookie
とpath-to-regexp
の依存ライブラリについては個別でアップデートするしかありません。
package.json
の override という機能を利用してアップデートします。書き方や制御の方法は細かく指定できるため、公式ドキュメントを覗いてみてください。
以下のように記載を入れると、依存関係の中で指定されているバージョンをガン無視して、override に記載されたバージョンに無理やり上書きしてくれます。
"overrides": {
"cookie": "0.7.1"
}
ということで、インストールし直してみます。
$ npm install
npm warn ERESOLVE overriding peer dependency
npm warn While resolving: react-server-dom-webpack@0.0.0-experimental-c8b778b7f-20220825
npm warn Found: react@18.2.0
npm warn node_modules/react
npm warn react@"^18.2.0" from the root project
npm warn 6 more (@gatsbyjs/reach-router, gatsby, gatsby-link, ...)
npm warn
npm warn Could not resolve dependency:
npm warn peer react@"0.0.0-experimental-c8b778b7f-20220825" from react-server-dom-webpack@0.0.0-experimental-c8b778b7f-20220825
npm warn node_modules/react-server-dom-webpack
npm warn react-server-dom-webpack@"0.0.0-experimental-c8b778b7f-20220825" from gatsby@5.14.1
npm warn node_modules/gatsby
npm warn
npm warn Conflicting peer dependency: react@0.0.0-experimental-c8b778b7f-20220825
npm warn node_modules/react
npm warn peer react@"0.0.0-experimental-c8b778b7f-20220825" from react-server-dom-webpack@0.0.0-experimental-c8b778b7f-20220825
npm warn node_modules/react-server-dom-webpack
npm warn react-server-dom-webpack@"0.0.0-experimental-c8b778b7f-20220825" from gatsby@5.14.1
npm warn node_modules/gatsby
removed 2 packages, changed 1 package, and audited 1400 packages in 2s
272 packages are looking for funding
run `npm fund` for details
2 moderate severity vulnerabilities
To address all issues (including breaking changes), run:
npm audit fix --force
Run `npm audit` for details.
できました!
再度npm audit
で検査してみると、cookie
ライブラリのセキュリティ警告が消えていることが確認できました。
$ npm audit
# npm audit report
path-to-regexp <0.1.12
Severity: moderate
Unpatched `path-to-regexp` ReDoS in 0.1.x - https://github.com/advisories/GHSA-rhx6-c78j-4q9w
fix available via `npm audit fix --force`
Will install gatsby@5.12.12, which is a breaking change
node_modules/path-to-regexp
gatsby 3.4.0-alpha-parallel.36 - 3.14.2 || 4.0.0-alpha-9689ff.4 - 4.0.0-zz-next.9 || 5.13.0-alpha-alt-image-cdn.38 - 5.15.0-next.0
Depends on vulnerable versions of path-to-regexp
node_modules/gatsby
2 moderate severity vulnerabilities
To address all issues (including breaking changes), run:
npm audit fix --force
同じ要領でpath-to-regexp
も上書き&再インストールします。
"overrides": {
"cookie": "0.7.1",
"path-to-regexp": "0.1.12"
}
$ npm install
npm warn ERESOLVE overriding peer dependency
npm warn While resolving: react-server-dom-webpack@0.0.0-experimental-c8b778b7f-20220825
npm warn Found: react@18.2.0
npm warn node_modules/react
npm warn react@"^18.2.0" from the root project
npm warn 6 more (@gatsbyjs/reach-router, gatsby, gatsby-link, ...)
npm warn
npm warn Could not resolve dependency:
npm warn peer react@"0.0.0-experimental-c8b778b7f-20220825" from react-server-dom-webpack@0.0.0-experimental-c8b778b7f-20220825
npm warn node_modules/react-server-dom-webpack
npm warn react-server-dom-webpack@"0.0.0-experimental-c8b778b7f-20220825" from gatsby@5.14.1
npm warn node_modules/gatsby
npm warn
npm warn Conflicting peer dependency: react@0.0.0-experimental-c8b778b7f-20220825
npm warn node_modules/react
npm warn peer react@"0.0.0-experimental-c8b778b7f-20220825" from react-server-dom-webpack@0.0.0-experimental-c8b778b7f-20220825
npm warn node_modules/react-server-dom-webpack
npm warn react-server-dom-webpack@"0.0.0-experimental-c8b778b7f-20220825" from gatsby@5.14.1
npm warn node_modules/gatsby
removed 1 package, changed 1 package, and audited 1399 packages in 1s
272 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
$ npm audit
found 0 vulnerabilities
ということで、きれいになりました 🎉
依存関係を見ると、overridden
として上書きされたバージョンのライブラリが当たっていることがわかります。npm
便利ですね!
$ npm list path-to-regexp
my-cording-standards@1.0.0 /Users/moepyxxx/dev/github.com/moepyxxx/cording_standards/app
└─┬ gatsby@5.14.1
├─┬ express@4.21.2
│ └── path-to-regexp@0.1.12 deduped
└── path-to-regexp@0.1.12 overridden
ただ、こちらは正直npm audit fix --force
とやっていることはそう変わらないです。
公式の依存関係を無視して上書きするため、メジャーバージョンのアップデートなどは注意が必要で、もちろん動かなくなる可能性もあるかなと思います。
特にメジャーバージョンやマイナーバージョンなど、どかっと上げる場合は、周辺の細やかな動作確認が必要になりそうですね。
また、override は強い制約になるため、このままメンテせず放置していると、対象のパッケージ管理されたライブラリ群は、永遠にライブラリ本来の依存関係を無視して上書きしてしまいます。
たとえばライブラリのアップデートが追いついたら(今回の場合gatsby
がセキュリティ警告に従い、内部のcookie
やpath-to-regexp
パッケージのバージョンをアップグレードしたものをリリースした際)、override 機能の利用を取りやめるといった対応が必要になってきそうです。
アップデートは今必要?
今回の場合は練習がてらセキュリティ警告を 0 にしてみましたが、そもそも全てのセキュリティ警告に従って逐一頑張ってアップデートするべきなの?という点を確認することも大切かなと、個人的には思います。
アップデートは大切ですが、無理やりなアップデートが他の機能を動かなくしてしまったり、override のようにメンテコストや考慮ポイントを生んだり……、思わぬマイナス影響になったりする可能性もありそうかなと。
闇雲にアップデートを頑張るのではなく、以下のような観点も確認してみると良さそうだったりするかもと思っています。
-
cookie
やpath-to-regexp
が使われているライブラリgatsby
の機能群は、自分たちのコードベースでも利用しているのか。 - セキュリティ警告の警戒レベルはどのくらいか。
- (実際にライブラリの github を覗きに行って)どのようなセキュリティホールなのか、自分たちのコードベースに影響はあるか。
-
gatsby
本体のアップデートを待つ方が面倒くさくないか。
などなど、これらも考えてバランスよくセキュリティアップデートと向き合えるとより良いのかなと思いました ◎
ここまでお読みいただき、ありがとうございました。
Discussion