コンテンツにスキップ

サプライチェーン攻撃の対策:npmエコシステムへの攻撃から学ぶ

概要

kawasima氏のscrapbox記事「サプライチェーン攻撃の対策」をHasegawa氏が紹介。2025年9月のShai-Hulud攻撃でnpmの正規パッケージが改ざんされ、認証情報が窃取された事件を背景に、具体的な対策をまとめたもの。

背景:何が起きたか

2025年9月 Shai-Hulud攻撃:
  - ngx-bootstrap、ng2-file-upload、@ctrl/tinycolor 等の正規パッケージが改ざん
  - postinstall フックに難読化済み bundle.js を埋め込み
  - npm / GitHub / クラウドの認証情報を窃取
  - webhook 経由で外部へ送信
  - 最終的に数百パッケージが汚染される

→ 「信頼できる」パッケージも攻撃の踏み台になりうる

サプライチェーン攻撃の種類

1. パッケージの乗っ取り(Account Takeover)
   メンテナのアカウントを奪いパッケージを改ざん

2. タイポスクワッティング
   人気パッケージに似た名前の悪意あるパッケージを公開
   例: 'lodash' → 'l0dash'

3. 依存関係の混入
   間接依存(transitive dependency)に悪意あるコードを仕込む

4. ビルドツールの汚染
   CI/CD パイプラインや build script を改ざん

5. postinstall フックの悪用
   npm install 時に自動実行されるスクリプトに悪意あるコードを仕込む

対策

1. lock ファイルを必ずコミットする

# package-lock.json / yarn.lock / pnpm-lock.yaml を必ずコミット
# → インストールするバージョンをピン留めする

# NG: lock ファイルを .gitignore に追加
# OK: lock ファイルをリポジトリに含める

2. npm audit を CI に組み込む

# GitHub Actions の例
- name: Security audit
  run: npm audit --audit-level=high
  # high 以上の脆弱性があればビルドを失敗させる

3. postinstall スクリプトを無効化する

# インストール時に postinstall を実行しない
npm install --ignore-scripts

# .npmrc に設定する場合
ignore-scripts=true

注意: 一部のパッケージは postinstall が必要なため、ホワイトリスト形式で管理する。

4. 依存関係のバージョン固定(ピン留め)

// package.json
{
  "dependencies": {
    // NG: "lodash": "^4.17.0"  (マイナーアップデートが自動で入る)
    // OK: "lodash": "4.17.21"  (バージョンを固定)
  }
}

Dependabot / Renovate で定期的に更新しつつ、テストを通してから更新する。

5. Supply Chain Levels for Software Artifacts (SLSA)

SLSA フレームワークの活用:
  - ソースコードの来歴(provenance)を検証
  - ビルド環境の完全性を保証
  - 段階的なレベル(SLSA Level 1〜4)で対策強度を選択

Level 1: ビルドプロセスのスクリプト化
Level 2: バージョン管理 + ホステッドビルドサービス
Level 3: 監査可能なビルドサービス
Level 4: 2者による検証、密閉されたビルド環境

6. Subresource Integrity (SRI)

<!-- CDN から読み込むスクリプトのハッシュを検証 -->
<script
  src="https://cdn.example.com/library.js"
  integrity="sha384-xxxx..."
  crossorigin="anonymous">
</script>

7. 依存関係の最小化

使っていないパッケージを定期的に削除:
  npx depcheck  # 使われていない依存を検出

1つの機能のために大きなライブラリを入れない:
  例: 日付フォーマットだけのために moment.js 全体を入れない
  → date-fns の必要な関数だけ使う

8. プライベートレジストリの活用

npm の代替:
  - GitHub Packages(プライベートリポジトリと統合)
  - Artifactory / Nexus(エンタープライズ向け)
  - Verdaccio(セルフホスト型)

→ 内部パッケージは社内レジストリに置き
  外部からの改ざんリスクを下げる

9. 環境変数・シークレットの保護

# postinstall 攻撃で窃取されやすいもの
~/.npmrc        # npm トークン
~/.ssh/         # SSH 秘密鍵
~/.aws/         # AWS 認証情報
.env            # 環境変数ファイル

対策:
  - CI/CD ではシークレットを環境変数として注入(ファイルに書かない)
  - ローカル開発でも .env は暗号化ツールで管理
  - 最小権限の原則(npm トークンは publish 権限のみ)

10. パッケージの公開者を確認する

# パッケージの公開者・メンテナを確認
npm info <package-name> maintainers

# ダウンロード数・最終更新日・GitHub スター数なども参考に
# → 急にメンテナが変わっていたら注意

検知・モニタリング

Socket.dev: npm パッケージの悪意あるコードを自動検出
Snyk: 脆弱性スキャン + 修正PR の自動作成
GitHub Advanced Security: secret scanning + dependency review
OpenSSF Scorecard: プロジェクトのセキュリティスコア評価

なぜ重要か / いつ使うか

  • npm / yarn を使うすべてのプロジェクトに関係する
  • 「有名パッケージだから安全」という思い込みは危険
  • CI/CD パイプラインに npm audit と lock ファイルチェックを組み込む最低限の対策はすぐ実施できる
  • セキュリティレビュー・新規パッケージ追加時のチェックリストとして活用