npmの脆弱性をゼロにするための手順

## はじめに

npm install した時に表示される脆弱性をそのままにしていませんか？

```
43 vulnerabilities (10 low, 18 moderate, 15 high)
```

時間がない時は仕方がないのですが、時間が経つにつれて脆弱性は増え、解消にかかる時間も増えてしまいます。

そこで、脆弱性が表示されたときに素早く対応できるように、解消方法を備忘録として残します。

※各パッケージのバージョンについて古いことがありますので、ご了承ください。

## エラーの確認方法

`npm audit` コマンドで確認します。

https://docs.npmjs.com/cli/v9/commands/npm-audit

脆弱性があるパッケージの一覧が出力され、同時に脆弱性の修正方法も表示されます。

```
% npm audit
# npm audit report

// 脆弱性があるパッケージの一覧が出力

43 vulnerabilities (10 low, 18 moderate, 15 high)

To address issues that do not require attention, run:
  npm audit fix

To address all issues possible (including breaking changes), run:
  npm audit fix --force

Some issues need review, and may require choosing a different dependency.
```


## 脆弱性の修正方法

npm audit 実行時に出力される脆弱性の修正方法をもとに修正を行います。

### fix available via `npm audit fix`

```
fix available via `npm audit fix`
```

`npm audit fix` コマンドで修正可能です。
ただし、稀にコマンドの実行では解消できないことがあります。そのため、脆弱性の原因となっているパッケージがどこで使用されているかを確認して、個別にアップデートするか、後述の `package.json` の `overrides` 項目にパッケージを上書きするように修正しましょう。

### fix available via `npm audit fix --force`

```
fix available via `npm audit fix --force`
```
`npm audit fix --force` コマンドで修正可能です。ただし、依存関係を含めパッケージのバージョンが更新されるため、アプリの機能に支障が出るかもしれません。対応は慎重に行いましょう。

npm audit fix --force の実行で解消できますが、バージョンアップの影響が広すぎる場合は、1件1件確認して脆弱性を潰していきましょう。

例えば、`nth-check`に脆弱性が確認された場合です。`react-scripts`の`@svgr/webpack`に依存している`nth-check`に脆弱性があるようです。

``` shell
nth-check  <2.0.1
Severity: high
Inefficient Regular Expression Complexity in nth-check - https://github.com/advisories/GHSA-rp65-9cf3-cjxr
fix available via `npm audit fix --force`
Will install react-scripts@3.0.1, which is a breaking change
node_modules/svgo/node_modules/nth-check
  css-select  <=3.1.0
  Depends on vulnerable versions of nth-check
  node_modules/svgo/node_modules/css-select
    svgo  1.0.0 - 1.3.2
    Depends on vulnerable versions of css-select
    node_modules/svgo
      @svgr/plugin-svgo  <=5.5.0
      Depends on vulnerable versions of svgo
      node_modules/@svgr/plugin-svgo
        @svgr/webpack  4.0.0 - 5.5.0
        Depends on vulnerable versions of @svgr/plugin-svgo
        node_modules/@svgr/webpack
          react-scripts  >=2.1.4
          Depends on vulnerable versions of @svgr/webpack
          Depends on vulnerable versions of resolve-url-loader
          node_modules/react-scripts
```

#### package.jsonのoverridesからパッケージを上書きする

`react-scripts`を@3.0.1にバージョンアップすれば解消できそうですが、影響範囲が広いため`@svgr/webpack`を直接修正します。

`package.json`に`overrides`項目を追加して、アプリで使用している`@svgr/webpack`を依存関係として修正することで、`react-scripts`の`@svgr/webpack`がバージョンアップされて脆弱性が解消できます。

``` json
{
  "dependencies": {
    "@svgr/webpack": "^8.1.0",
  },
  "overrides": {
    "react-scripts": {
      "@svgr/webpack": "$@svgr/webpack",
      "webpack-dev-server": "4.15.2",
      "ws": "^8.18.0",
      "postcss": "8.4.31"
    },
  },
}
```

### No fix available

```
No fix available
```

npmのコマンドでは修正不可です。手動で修正するしかありません。この場合、依存先のパッケージで発生していることが多いです。

例えば、`axios`に脆弱性が確認された場合です`aws-api-gateway-client`に依存している`axios`が古いようです。

```
axios  0.8.1 - 0.27.2
Severity: moderate
Axios Cross-Site Request Forgery Vulnerability - https://github.com/advisories/GHSA-wf5p-g6vw-rhxx
No fix available
node_modules/axios
  aws-api-gateway-client  *
  Depends on vulnerable versions of axios
  node_modules/aws-api-gateway-client
```

ここは`package.json`の`overrides`に`aws-api-gateway-client`の`axios`のバージョンを上書きする形で追記します。

``` json
{
  "dependencies": {
    "aws-api-gateway-client": "^0.3.7",
  },
  "overrides": {
    "aws-api-gateway-client@^0.3.7": {
      "axios": "$axios"
    }
  },
}
```

ここでパッケージ名（aws-api-gateway-client）にバージョン（@^0.3.7）を指定しないと、正しく依存関係が上書きされないので注意しましょう。

## まとめ

- `npm audit`で脆弱性を確認する
- `npm audit fix --force`で解決できない時は1件ずつ対応する
- 依存関係が複雑なパッケージの脆弱性が解消できない場合は`package.json`の`overrides`項目でパッケージを更新する

上記の対応を繰り返し実施することで、最終的に43件あった脆弱性を0件に解消することができました。
```
found 0 vulnerabilities
```

依存関係が複雑になると脆弱性の解消が一層困難になります。npm install の実行時でも良いので定期的にチェックし、0件をキープできるように努めていきたいです。