📄
概念 📚 software-design-concepts

依存関係管理

サプライチェーン攻撃・脆弱性のある依存パッケージの検出と、依存関係を安全に維持するための仕組み

現代のソフトウェアは大量のサードパーティライブラリに依存しており、依存パッケージのセキュリティはアプリケーション自体のセキュリティと同様に重要である。サプライチェーン攻撃とは、悪意あるコードを依存パッケージに混入させてダウンストリームの利用者を標的にする攻撃手法であり、2020年のSolarWinds事件・2021年のua-parser-js事件などが代表的な実例となっている。Typosquatting(lodashの代わりにl0dashのような誤字ドメインのパッケージ公開)や依存関係ハイジャック(所有者が変わったパッケージへの悪意あるコード挿入)が主な攻撃手法である。

npm audit・Snyk・GitHub Dependabotなどのツールは、既知の脆弱性(CVE)を持つ依存パッケージを検出し、修正バージョンへのアップグレードを推奨する。これらをCI/CDパイプラインに組み込むことで、脆弱性のある依存関係を持つコードのマージを自動的にブロックできる。SBOM(Software Bill of Materials)は、アプリケーションが依存するすべてのコンポーネントのリストであり、特定の脆弱性が公開された際に影響範囲を素早く特定するために活用される。

ロックファイル(package-lock.jsonyarn.lockpnpm-lock.yaml)は、依存パッケージの正確なバージョンとチェックサムを記録することで、異なる環境での同一ビルドを保証し、依存関係のバージョンドリフトを防ぐ。ロックファイルをgitignoreに追加して無視する設定は、再現性とセキュリティの両面で誤りである。依存パッケージの最小化も重要であり、使用していないパッケージが残り続けると攻撃面が広がる。

コードレビューで着目するポイント

  • ロックファイル(package-lock.json等)がgitリポジトリに含まれており、コミットされているか
  • 新しく追加される依存パッケージが信頼できるソースから取得されており、インストール数・メンテナンス状況・オーナーが確認されているか
  • npm audit / snyk testがCIパイプラインに組み込まれており、高・致命的な脆弱性がブロック対象になっているか
  • 使われていない依存パッケージがpackage.jsonに残っていないか
  • 依存パッケージのバージョンが^によるマイナーバージョン自動更新で固定されているか(パッチ・マイナーの範囲が意図的か)
  • 本番依存(dependencies)と開発依存(devDependencies)が正しく分類されているか
  • 内部パッケージの配布にプライベートレジストリが使われており、パブリックレジストリから同名パッケージを引っ張れない設定になっているか

典型的なアンチパターン

ロックファイルをgitignoreに追加: package-lock.json.gitignoreに追加し、npm installのたびに解決バージョンが変わる状態にする設定。CI環境と開発環境でパッケージバージョンが異なり、再現性がなくなると同時に悪意あるバージョンへの意図しないアップグレードが発生しうる。

脆弱性スキャンなしの依存関係更新: npm updatedependabotの自動更新PRを内容確認なしに機械的にマージする運用。パッケージのマイナーアップデートに行動変更が含まれることがあり、自動マージは最低限CIパイプラインでのテスト通過を確認してから行うべき。

本番コードへの不必要な依存: 左パッド(left-pad)事件のように、1行で代替できる処理のために外部パッケージに依存する設計。依存数が多いほど攻撃面が広がるため、標準ライブラリで代替できる場合は外部依存を避けることを検討する。

参考リソース

  • npm audit — Node.jsプロジェクトの脆弱性スキャン組み込みコマンド
  • Snyk (https://snyk.io/) — 依存関係・コンテナ・IaCの脆弱性スキャンとモニタリングサービス
  • GitHub Dependabot — GitHubリポジトリの依存関係自動更新・セキュリティアラート機能
  • CycloneDX SBOM標準 (https://cyclonedx.org/) — ソフトウェア部品表(SBOM)の業界標準フォーマット
  • CNCF Supply Chain Security White Paper — クラウドネイティブ環境でのサプライチェーンセキュリティのベストプラクティス
  1. 1. 📄アーキテクチャスタイル
  2. 2. 📄ドメインモデリング
  3. 3. 📄モジュール分割と依存管理
  4. 4. 📄データモデリング
  5. 5. 📄API設計
  6. 6. 📄整合性とトランザクション
  7. 7. 📄非同期処理(Queue/Event)
  8. 8. 📄キャッシング
  9. 9. 📄ユーザーリサーチ
  10. 10. 📄情報アーキテクチャ
  11. 11. 📄インタラクションデザイン
  12. 12. 📄UX原則とヒューリスティクス
  13. 13. 📄アクセシビリティ(UX観点)
  14. 14. 📄UXメトリクス
  15. 15. 📄スケーラビリティ
  16. 16. 📄可用性とレジリエンス
  17. 17. 📄オブザーバビリティ
  18. 18. 📄環境・インフラ設計
  19. 19. 📄データマイグレーション
  20. 20. 📄セキュリティ設計原則
  21. 21. 📄データ保護とマルチテナント
  22. 22. 📄LLMセキュリティ
  23. 23. 📄ビジュアルデザイン原則
  24. 24. 📄デザインシステム
  25. 25. 📄コンポーネント設計
  26. 26. 📄スタイリング
  27. 27. 📄状態管理
  28. 28. 📄フロントエンドパフォーマンス
  29. 29. 📄アクセシビリティ(実装観点)
  30. 30. 📄アニメーションとインタラクション
  31. 31. 📄設計原則
  32. 32. 📄デザインパターン(GoF)
  33. 33. 📄エンタープライズパターン
  34. 34. 📄クリーンコード
  35. 35. 📄リファクタリング
  36. 36. 📄型設計とコントラクト
  37. 37. 📄関数型プログラミング概念
  38. 38. 📄エラーハンドリング
  39. 39. 📄テスト戦略と哲学
  40. 40. 📄テスト種別(機能テスト)
  41. 41. 📄テスト種別(UI・ビジュアル)
  42. 42. 📄テスト種別(契約・境界)
  43. 43. 📄テスト種別(非機能テスト)
  44. 44. 📄テストダブル
  45. 45. 📄テスト設計技法
  46. 46. 📄並行処理・マルチスレッド
  47. 47. 📄パフォーマンス最適化
  48. 48. 📄ドキュメント管理
  49. 49. 📄バージョン管理と開発プロセス
  50. 50. 📄脅威モデリング
  51. 51. 📄通信保護(TLS)
  52. 52. 📄暗号化・機密情報管理
  53. 53. 📄認証・セッション管理
  54. 54. 📄認可・アクセス制御
  55. 55. 📄入力バリデーション
  56. 56. 📄インジェクション攻撃
  57. 57. 📄出力エンコーディング
  58. 58. 📄エラーハンドリング(セキュリティ観点)
  59. 59. 📄SSRF(サーバーサイドリクエストフォージェリ)
  60. 60. 📄依存関係管理
  61. 61. 📄設計・実装 参考書籍
  62. 62. 📄セキュリティ参考資料
  63. 63. 📄正規化(データベース正規化)