Claude Media
Claude Codeでnpm auditとpip-auditの結果を仕分ける

Claude Codeでnpm auditとpip-auditの結果を仕分ける

npm auditとpip-auditのJSONをClaude Codeに渡し、実際に使っているか・dev依存か・どの依存経由かで仕分けて、直せるものだけ直して再実行で閉じる手順です。

npm audit や pip-audit を初めて回すと、数十件の警告が並ぶことがあります。その全部が自分のアプリの問題とは限りません。どちらも見ているのは依存関係の一覧で、コードがその部品をどう使っているかは見ていないからです。

そこでClaude Codeには、JSONの結果を読み、コードを検索し、結論を表にするところまでを任せます。直す操作は、範囲を決めてから、小さく実行します。最後に同じコマンドをもう一度回して、件数が減ったことで閉じます。

まず「警告の数」と「直す件数」は別と割り切る

npm audit は、プロジェクトの依存関係の記述をレジストリに送り、既知の脆弱性の報告を受け取るコマンドです。pip-auditも同じ発想で、Pythonの依存関係を脆弱性データベースに照会します。pip-auditのREADMEは、静的コード解析ではなく、コードではなく依存関係のツリーを調べるツールだと明記しています。

つまり、報告に出た時点では「入っている」ことしか分かりません。次の4つを調べて初めて、直す優先度が決まります。

観点

仕分けに使う4つの問い

  • コードから使っているか

    そのパッケージをimportしている箇所があるか。なければ、影響は限定的な可能性があります。

  • 本番に入るか

    devDependencies、テスト専用、ビルド専用のものは、本番の実行環境に載らないことがあります。

  • どの依存の先にあるか

    推移的依存なら、直接入れている親パッケージの更新で解消できるかを見ます。

  • 修正版があるか

    修正版がなければ、アップグレードでは閉じません。回避策か保留の記録になります。

この4つは機械的に調べられるので、Claude Codeに向いています。一方で「この脆弱性の悪用条件に、うちの使い方が当たるか」の最終判断は人が持ちます。表の「影響なし」は仮説として扱います。

触らせる範囲を権限で決めておく

結果を読む操作と、依存を書き換える操作は分けます。.claude/settings.json に、読み取り系だけを許可する例です。

{
  "permissions": {
    "allow": [
      "Bash(npm audit)",
      "Bash(npm audit --json)",
      "Bash(npm audit fix --dry-run *)",
      "Bash(npm explain *)",
      "Bash(npm ls *)",
      "Bash(pip-audit -r requirements.txt -f json)"
    ]
  }
}

npm audit * のように広く許可すると、npm audit fix --force まで通ってしまいます。そのため fix を伴うものは --dry-run 付きだけを書いています。allow に載せていない操作は、権限モードに従って確認の対象になります。本番の fix は、人が内容を見てから許可する運用です。

ルールの書き方は、* をサブコマンドの後ろに置くのが基本です。ルールの優先順位と書式は/permissionsコマンドの記事にまとめています。

npm auditの結果を読ませて仕分ける

最初は、直さずに現状を保存します。

npm audit --json > audit-npm.json
npm audit fix --dry-run --json > audit-npm-fix-plan.json

npm audit の終了コードは、脆弱性があると0以外になります。CIで止めたい重大度を絞る --audit-level は、レポートの表示を絞らず、失敗にする閾値だけを変えます。仕分けにはフルのレポートが要るので、ここでは使いません。

次に、Claude Codeへ依頼します。

audit-npm.json を読み、脆弱性ごとに次を調べて表にしてください。
1. 該当パッケージを src/ と scripts/ で import / require している箇所
2. package.json の dependencies か devDependencies か
3. 推移的依存なら、`npm explain <パッケージ名>` で出る親の連鎖
4. audit-npm-fix-plan.json で修正が適用される想定か
ファイルの変更はせず、表だけ出してください。

npm explain は、あるパッケージがなぜ入っているかをツリーで説明するコマンドです。親の連鎖を取る手段として、Claude Codeに指定すると調べ方がぶれません。

例えば次のような表になります(形の一例です)。

パッケージ直接/推移種別コードで使用修正の見込み区分
lodash直接/推移直接種別dependenciesコードで使用あり(3箇所)修正の見込み互換範囲で更新可区分1直す
minimatch直接/推移推移(glob経由)種別devDependenciesコードで使用なし修正の見込み親の更新が必要区分2親を更新
xml2js直接/推移推移(旧SDK経由)種別dependenciesコードで使用なし修正の見込みsemver-majorが必要区分3判断が必要

区分は「1すぐ直す」「2親を更新して間接的に直す」「3人が判断する(メジャー更新や修正版なし)」の3つに絞ると、次の作業を迷いません。

直せるものだけ直す

区分1と2は、npm audit fix で扱える範囲です。docsでは、npm audit fix を使うと、semverの互換範囲内で脆弱な依存を更新すると説明しています。範囲を超える更新が必要なものには --force が要ります。区分3は、この --force が必要なものと重なります。

npm audit fix の周辺オプションは、仕分けの結果に合わせて選びます。

やりたいことオプション
node_modulesは触らず、lockファイルだけ更新オプションnpm audit fix --package-lock-only
devDependenciesを更新対象から外すオプションnpm audit fix --only=prod
メジャー更新も許す(区分3)オプションnpm audit fix --force
何が変わるかだけ見るオプションnpm audit fix --dry-run --json

--force は、まず使いません。メジャー更新はAPIの互換が切れるので、テストが通ることを見てから、1パッケージずつ手で上げる運用が安全です。Claude Codeに頼むなら、次のように範囲を縛ります。

区分1と2だけを対象に npm audit fix --package-lock-only を実行して、
差分(package-lock.json)を見せてください。--force は使わないでください。
その後 npm test を実行して結果を報告してください。

実行後に npm audit --json を再度回し、区分1と2の件数が減っていれば、そこで一区切りです。区分3に残ったものは、理由つきで記録して終わります。

pip-auditも同じ型で回す

Pythonも、手順の骨格は同じです。まず現状をJSONで保存します。

pip-audit -r requirements.txt -f json -o audit-pip.json
pip-audit -r requirements.txt --fix --dry-run

pip-auditの終了コードは、脆弱性がなければ0、1件でもあれば1です。--fix --dry-run は、監査は実行し、どの依存を上げ、どれを見送るかを表示するだけで、実際の更新はしません。

注意したいのは、「修正版がある脆弱性だけ」で絞る部分です。READMEは、pip-auditには未修正の脆弱性を無視するオプションがないと書いています。代わりに、JSONを jq で処理する例を示しています。

pip-audit -r requirements.txt --format=json 2>/dev/null \
  | jq '.dependencies[].vulns[].fix_versions[]'

出力が空でなければ、修正版のある脆弱性が残っています。Claude Codeには、このJSONを読ませて、npmと同じ4つの問いに答えさせます。

Pythonでは、パッケージ名とimport名が違うことが仕分けの落とし穴になります。たとえばPyYAMLは import yaml で使います。依頼文には「パッケージ名ではなくimport名で検索すること」と書き添えます。

audit-pip.json の各脆弱性について、該当パッケージのimport名を特定し、
このリポジトリで使っている箇所を検索してください。
requirements.txt が直接の依存か、他のパッケージ経由かも示してください。

実際に直すときは、pip-audit --fix を使えますが、更新は仮想環境の中で行い、テストを通してから requirements.txt に反映します。READMEのセキュリティモデルの節は、pip-audit -r は pip install -r とほぼ同じ動きだと警告しています。信頼できないrequirements.txtに対しては実行しません。

「影響なし」は理由つきで除外する

使っていないことが確かめられた脆弱性は、報告から除外して、次回以降のノイズを減らせます。pip-auditは --ignore-vuln でIDを指定します。CVEやGHSAのIDでも指定できます。

pip-audit -r requirements.txt --ignore-vuln GHSA-xxxx-xxxx-xxxx

除外した事実は、コマンドの履歴だけでは残りません。除外したID、理由、確認した日付を、リポジトリのメモに書きます。CLAUDE.md に次のような規約を置くと、Claude Codeが除外の提案をするときに、同じ形式で書き出します。

## 依存関係の脆弱性対応
- 仕分けの区分は 1 すぐ直す / 2 親を更新 / 3 人が判断 の3つ
- `--force` と `--ignore-vuln` は、実行前に必ず確認を取る
- 除外するときは audit-ignore.md に ID・理由・確認日・見直し時期を書く
- 「コードから使っていない」は、検索したコマンドと件数を添えて報告する

最後の1行が効きます。「使っていない」という結論だけでは検証できませんが、検索した語と件数が付いていれば、人が数十秒で追えます。

区分3に残ったものをどう扱うか

メジャー更新が必要なもの、修正版がまだないものは、アップグレードでは閉じません。Claude Codeには、次の3点を調べさせて表の備考に入れます。

  1. 脆弱性の説明に書かれた悪用条件(特定の関数の呼び出し、特定の入力、特定の設定)
  2. その条件に、このリポジトリのコードが当たるかどうか(呼び出し箇所の検索結果)
  3. 回避策(該当機能を使わない、入力を制限する、より新しい親パッケージへ移る)

pip-auditは --desc で各脆弱性の説明を付けられ、JSON形式では既定で付きます。説明文の悪用条件を拾わせるときに使えます。

当たらない場合は、前の節の除外に進みます。当たる、または判断できない場合は、チケット化して担当を決めます。ここで大事なのは、Claude Codeの調査結果を「確定」ではなく「根拠つきの下書き」として渡すことです。

モノレポとワークスペースで気をつけること

npmのworkspacesを使うリポジトリでは、どのワークスペースの依存かが仕分けの軸に加わります。npm audit には --workspace、--workspaces、--include-workspace-root の設定があり、対象を絞れます。全体を1回で回した結果をClaude Codeに渡すより、ワークスペースごとにJSONを分けて保存すると、「このパッケージはどのアプリに入っているか」の説明が短くなります。

Python側は、サービスごとに requirements.txt が分かれているなら、ファイルごとに -r で回し、結果のファイル名にサービス名を入れます。同じ脆弱性がサービスAでは本番依存、サービスBではテスト専用ということがあり、区分が別々になるのは自然です。

npm audit signaturesは別の確認

npm audit には signatures という別の使い方があります。こちらは脆弱性の有無ではなく、ダウンロードしたパッケージのレジストリ署名を検証するコマンドです。脆弱性の仕分けとは目的が違うので、結果をまとめて1つの表に混ぜません。

再実行で閉じる

仕分けと修正が終わったら、最初と同じコマンドを回します。

npm audit --json > audit-npm-after.json
pip-audit -r requirements.txt -f json -o audit-pip-after.json

Claude Codeに渡すのは、before/afterの2つのファイルです。減った件数、残った件数、残った脆弱性の区分(判断待ちか、修正版なしか、除外済みか)を1つの表にします。これが、レビューに出す完了報告になります。

定期的に回すなら、claude -p で非対話にして、読み取り系のツールだけを許可する形が合います。

claude -p "audit-npm.json を仕分けて表にして" \
  --allowedTools "Read,Grep,Bash(npm explain *)"

非対話実行の書式と権限フラグは、claude -pオプションの記事に詳しくあります。

つまずきやすい点

  • npm audit が出す件数と、npm audit fix で消える件数は一致しません。修正版がない、または範囲外の更新が必要なものが残ります
  • devDependenciesだけの脆弱性は、--omit を指定すると、npm audit の送信対象から外れます。本番の観点で見たいときは、npm audit --omit=dev で別に回します
  • npm audit は、依存関係の記述をレジストリに送ります。社内レジストリや機密性の高いプロジェクトでは、何が送られるかを先に把握します
  • 修正版が出ていても、依存のバージョン範囲の制約で上げられないことがあります。区分3として理由を残します
  • 結果がすべて「影響なし」に仕分けられても、鵜呑みにしません。動的なimportや、設定ファイル経由で読み込まれる使い方は、単純な検索では拾えないからです

イメージ脆弱性のスキャンと修正はTrivyの回し方、取引先のSBOMを突合する場合はOSV-Scannerの手順が入口になります。一覧から是正対応表を作るところは脆弱性スキャン結果の優先度付けにあります。

まとめ

警告の件数は、そのまま作業量にはなりません。到達性、依存の種類、親子関係、修正版の有無で仕分けた区分1と2だけが、今日直せる範囲です。区分3は理由を残して保留し、再実行で件数の変化を確かめて閉じます。

参照した一次ソース

この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。

  1. docs.npmjs.com/cli/v10/commands/npm-audit
  2. github.com/pypa/pip-audit
  3. code.claude.com/docs/en/headless
  4. code.claude.com/docs/en/permissions
  5. code.claude.com/docs/en/common-workflows
この記事を共有:XはてブLinkedIn