【脆弱性対応】nodeパッケージのバージョンアップを安全に行う

2022/12/31に公開

2022年ももう終わりますね。
やり残したことがありますね?
そう、脆弱性対応です。やっていきましょう。

はじめに

nodeパッケージの脆弱性対応で調べると、 一例として npm audit で脆弱性を確認して npm audit fix で自動的にバージョンアップする方法が紹介されています。
しかし、バージョンアップによって動作しないパッケージがでてきたり、ビルド時に警告が表示されるようになったりとアプリへの影響が0とは言い切れません。

依存関係を調べつつ、慎重にバージョンアップを行う手順を記載していきます。
バージョンアップ方法というよりは調べ方をまとめた内容になります。

手順

基本的には脆弱性があるパッケージをバージョンアップして問題がないか動作確認を行えば良いのですが、依存関係がある場合は依存元のパッケージのバージョンを上げることで解決するのかを調べる必要があります。

脆弱性のあるパッケージの検出

yarn audit で脆弱性のあるパッケージを洗い出します。

$ yarn audit

脆弱性のレベルがCritical, High, Lowの3段階で出力されます。
最低限Criticalのみ解消します。

--level のオプションでCriticalのみ表示することもできます。

$ yarn audit --level critical

パッケージの依存関係一覧を確認

依存関係の大元のパッケージのバージョンを上げることで、脆弱性が解消されるのかを調べます。

$ npm ls {パッケージ名}

今回は例としてtrimの依存関係を見てみます。

$ npm ls trim

└─┬ textlint@11.9.1
  └─┬ @textlint/textlint-plugin-markdown@5.3.5
    └─┬ @textlint/markdown-to-ast@6.3.5
      └─┬ remark-parse@5.0.0
        └── trim@0.0.1

textlint@11.9.1に依存して使用されていることがわかります。

依存元のパッケージの最新バージョン確認

依存元パッケージの最新バージョンを確認します。

$ yarn info textlint

関係ない部分を省略した出力結果

{
  name: 'textlint',
  description: 'The pluggable linting tool for text and markdown.',
  'dist-tags': {
    latest: '12.2.3',
    beta: '12.0.0-beta.3',
    canary: '10.3.0-alpha.0f2fd6f9',
    next: '10.0.0-next.2'
  },
   dependencies: {
    '@textlint/textlint-plugin-markdown': '^12.2.3',
  },
}

textlintのlatestは 12.2.3 なので 11.9.1 -> 12.2.3 にバージョンアップの余地がありそうです。
dependenciesには先ほど依存関係で確認した @textlint/textlint-plugin-markdown の項目があり、こちらもtextlintをlatestにすれば 5.3.5 -> 12.2.3 にバージョンアップできます。

バージョンアップで解消されるか調査する

依存を辿っていき、textlintを12.2.3にあげればtrimのバージョンも上がるのか念のために確認してみます。

textlint@12.2.3では@textlint/textlint-plugin-markdown@12.2.3が使われているので、yarn infoのバージョン指定で調べます。

$ yarn info @textlint/textlint-plugin-markdown@12.2.3

結果↓(不要な部分は省略)

{
  name: '@textlint/textlint-plugin-markdown',
  description: 'Markdown support for textlint.',
  'dist-tags': {
    latest: '12.2.3',
    canary: '4.1.0-alpha.0f2fd6f9',
    beta: '12.0.0-beta.3'
  },
  dependencies: {
    '@textlint/markdown-to-ast': '^12.2.3'
  },
}

@textlint/markdown-to-astは12.2.3が使用されてることがわかりました。
同様に依存を調べていきます。

$ yarn info @textlint/markdown-to-ast@12.2.3

結果↓(不要な部分は省略)

{
  name: '@textlint/markdown-to-ast',
  description: 'Parse Markdown to AST with location info.',
  'dist-tags': {
    latest: '12.2.3',
    canary: '6.1.0-alpha.0f2fd6f9',
    beta: '12.0.0-beta.3'
  },
  dependencies: {
    'remark-parse': '^9.0.0',
  },
}

remark-parseは9.0.0が使用されているので調べます。

$ yarn info remark-parse@9.0.0

結果↓(不要な部分は省略)

{
  name: 'remark-parse',
  description: 'remark plugin to parse Markdown',
  'dist-tags': {
    latest: '10.0.1',
    next: '9.0.0-alpha.1'
  },
  dependencies: {
    'mdast-util-from-markdown': '^0.8.0'
  },
}

remark-parseのバージョン9.0.0ではtrimが使用されていないので、結果的にtextlintを12.2.3にアップデートすることでtrimの脆弱性は解消できることが確認できました。

バージョンアップを行う

yarn upgrade-interactiveでアップグレードしたいバージョンを指定します。
latestのオプションをつけてpackage.jsonに記述がないlatestも表示します。

$ yarn upgrade-interactive --latest

更新したいパッケージを選択して実行します。

バージョンアップ後の再確認

バージョンアップを行ったので、脆弱性が解消されたかを確認します。

$ npm ls trim

結果

└── (empty)

textlintをバージョンアップしたことで依存関係でtrimは使用されていません。

再度yarn auditを行うと脆弱性が少なくなっているはずです。

$ yarn audit

脆弱性対応自体はこれで完了です。

動作確認

バージョンアップを行った機能周辺の動作確認を行います。
yarn devでビルドしてみたり、エラーが起こっていないかを確認します。

今回の場合は、textlintを11.9.1 -> 12.2.3にメジャーバージョンをアップデートしました。
メジャーバージョンを上げたため、今まではリントエラーにならなかった文章が引っかかる可能性もあります。
(textlintを走らせると、実際に数点エラーになっていたので確認は大事です。)

おわりに

脆弱性対応で依存関係を追いながらバージョンアップを行いました。
今回のように1個1個調べながら対応するのは大変ですが、一気にアップデートしていざビルドするとエラーがたくさんでる みたいなことが起こると原因の特定が大変です。
安全に確実に脆弱性対応を行うのであれば1個づつ行いたいですし、3ヶ月に1回の頻度でこまめに確認できればコストも少なく対応できそうです。

Discussion