現代のソフトウェア開発では、世界中のエンジニアが公開しているライブラリやフレームワークなどの外部部品(オープンソースソフトウェア等)を組み合わせ、迅速に機能を構築する開発スタイルが標準となっています。

しかし、この利便性の裏で、外部部品を足がかりに組織へ侵入する「ソフトウェアサプライチェーン攻撃」が深刻な脅威となっています。開発者が自ら選んで設定ファイルに記述した部品だけでなく、その部品が背後で頼る別の部品へと網の目のように連鎖(依存)しているためです。この連鎖構造により、開発者が存在を把握していない末端の部品に紛れ込んだ欠陥や改ざんが、最終製品全体へと波及する経路が生み出されます。外部部品を取り込むことがなぜ組織の安全を揺るがす攻撃につながるのか、その構造と成立条件、現実的な防衛策を整理します。

直接依存と間接依存――見えない深さへ広がる「波及経路」の仕組み

外部部品を取り入れる際、開発者が意識するのは通常、自分たちで直接導入した部品です。これを「直接依存」と呼びます。たとえば画像処理のために特定のライブラリを導入するようなケースです。

しかし、そのライブラリもまた別のライブラリを利用し、さらにその先でも別の部品が使われるというように、依存関係は何層にもわたって連鎖します。このように、直接依存している部品を経由して自動的に引き込まれる部品群を「間接依存(推移的依存)」と呼びます。

サードパーティ製ソフトウェアやオープンソースコンポーネントを取り込む近代的なソフトウェア開発全般において、ソフトウェアは多くの外部部品とその依存先を組み合わせて作られます。そのため、開発者が直接選んでいない部品の欠陥や改ざんが、最終的な製品へ波及する経路になり得ます(NIST SP 800-218 PO.1, PW.4)。開発者が明示的に選んだ部品が10個程度であっても、間接依存をすべて展開すると数百から数千個の部品がプロジェクトへ自動的に取り込まれることも珍しくありません。

この構造は一般に「依存ツリー(木構造)」と呼ばれますが、現実のソフトウェアでは複数の部品が同一の共通部品を共有することが多く、実際には網の目状に絡み合う「有向グラフ」を形成しています。

アプリはAとBを直接使い、AとBは共通部品Dを含む別部品を利用する。
解説図アプリはAとBを直接使い、AとBは共通部品Dを含む別部品を利用する。Dなどに欠陥や改ざんが混入する可能性があるが、被害の成立は実行経路・入力・権限などの条件による。矢印は利用する側から依存先への参照で、被害の必然的な伝播を意味しない。A〜Eは架空の説明用名。

上の図は、アプリケーションが直接利用する直接依存と、その背後に連なる膨大な間接依存の広がり、そして攻撃者が狙う混入位置の関係を示した模式図です。

この図を読み解く上で最も重要な点は、描かれている矢印が部品同士の参照関係や取り込み経路を示しているに過ぎず、「ある部品に問題があれば、すべての利用先システムへ必ず被害が及ぶ」という必然的な決定論を意味しているわけではないということです。混入した問題が実際の侵害につながるかどうかは、その部品が開発時・ビルド時・本番実行時のどの段階で関与するのか、実行経路が存在するのか、どの権限で動くのかといった条件によって左右されます。この図は、危険が伝わり得る「構造的な経路の存在」を示したものとして理解する必要があります。

なぜ攻撃者は依存関係を狙うのか――混入の手法と実行権限の共有

強固に防備された組織のサーバーを外部から直接攻撃することは容易ではありません。そこで攻撃者は、標的が利用している無名の外部部品や、個人のボランティアが保守している小さなライブラリなど、供給網(サプライチェーン)の相対的に守りが手薄な環に狙いを定めます。

ここで混同してはならないのが、「不具合(バグ)」「意図しない脆弱性」「悪意あるコード」の区別です。

  • 不具合(バグ):プログラムが意図通りに動作しない状態全般を指します。
  • 脆弱性:不具合のうち、外部からの不正操作や情報漏洩につながるセキュリティ上の欠陥を指し、開発者が意図せず作り込んでしまったものです。
  • 悪意あるコード(バックドア等):攻撃者が情報の窃取や不正操作のために、意図して仕組んだ不正なプログラムです。

攻撃者は、既存の脆弱性を探すだけでなく、悪意あるコードを依存関係に紛れ込ませようとします。その代表的な手口には以下があります。

  1. タイポスクワッティング(Typosquatting)

公開レジストリ(npmやPyPIなど)は、誰でも自由にプログラムを公開できる中立な「設定された入手先」に過ぎず、安全性が公的に保証された場所ではありません。攻撃者は有名部品と綴りが一文字だけ異なる名前で悪意ある部品を登録し、開発者の入力ミスを待ち構えます。

  1. 依存関係の取り違え(Dependency Confusion)

組織が内部専用に開発した非公開部品と同じ名前で、攻撃者が公開レジストリに高いバージョン番号を付けた部品を先回りして登録する手法です。パッケージマネージャーの探索順序の隙を突き、内部部品ではなく攻撃者の部品を優先してダウンロードさせます。

  1. アカウント乗っ取りやメンテナ偽装

保守が停滞している部品の協力者を装って公開権限を引き継いだり、認証情報を奪ったりして、正規のアップデートに見せかけて不正コードを混入させます。

こうして混入した悪意あるコードが致命的な脅威となる理由は、「実行権限の共有」と「実行タイミングの早さ」にあります。

多くのパッケージマネージャーには、導入時に自動で初期設定スクリプトを実行するフック機能(npmの preinstall や postinstall など)が備わっています。攻撃者はこれを利用し、開発端末やビルド環境でインストールコマンドが実行された瞬間に、プログラムの起動前であっても環境変数からクラウドの秘密鍵やAPIトークンを盗み出します。

さらに重大なのは、本番環境で読み込まれた外部部品は、本体のアプリケーションと「同一のプロセス」として動作する点です。OSやランタイムから見れば、自作コードも外部部品も区別がつかず、同一の権限(ファイルシステムの読み書き、外部ネットワーク通信、メモリ空間へのアクセス)を持ちます。コンテナ技術などでアプリ全体を隔離しても、同一プロセス内で動作する部品がメモリ上のパスワードを読み取ったり、正規の通信ポートから情報を持ち出したりする行為を完全に防ぐことは困難です。

脆弱性と悪用可能性――「一覧にある」ことと「攻撃が成立する」ことの違い

ソフトウェア構成分析(SCA)ツールを導入すると、依存関係から多数の脆弱性(CVE)が報告され、対応に追われることがあります。しかし、「脆弱性一覧に載っていること」と「現実に攻撃が可能であること」は別問題です。

まず前提として、開発時のテスト支援ツールやリンターなど、開発環境専用の部品は本番環境には含まれず、実行もされません。また、仮に脆弱性を含む部品が本番環境に含まれていたとしても、攻撃が成立するには以下の条件が揃う必要があります。

  1. 到達可能性(Reachability):外部からの通信や内部処理が、部品内の脆弱なコード行を実際に呼び出しているか。部品全体の安全な一部機能しか使っていなければ、脆弱性は発動しません。
  2. 入力経路:脆弱な処理に対し、外部入力や内部設定・環境変数を経由して攻撃データが届く経路が存在するか。
  3. 実行権限:攻撃が成功した際に、プロセスが機密データへのアクセス権やOSコマンド実行権限を実際に持っているか。

ソフトウェア構成分析(SCA)等で検出された脆弱性の対応優先度を判断する際、脆弱性一覧に登録されている欠陥であっても、対象環境における実行経路(到達可能性)、入力経路、実行権限などの成立条件や潜在的影響度を踏まえて悪用可能性を評価する必要があり、一覧の存在だけで直ちに悪用可能とは断定できません(NIST SP 800-218 RV.2.1, RV.2.2, PW.4.4)。

静的解析ツールを用いて脆弱な関数への到達可能性を判定する技術は、対応すべき脆弱性の優先度を絞り込む有効な手段です。ただし、静的解析はプログラム実行時の動的な呼び出し(リフレクション等)や設定変更による経路変更を完全には追跡できない限界があります。そのため、「解析で到達不能と判定されたから永久に安全」と過信するのではなく、ライブラリの更新や環境変更の都度、継続して再評価を行う体制が不可欠です。

防御技術の役割と限界――ロックファイル、SBOM、SLSAの正しい読み解き方

サプライチェーンの脅威に対抗する技術を導入する際は、「何を守り、何を守れないのか」という境界を正しく把握することが重要です。

1. ロックファイルとハッシュ検証

package-lock.json や Pipfile.lock などのロックファイルは、全部品の確定バージョンと暗号学的ハッシュ値を記録します。

  • 果たせる役割:以前検証したファイルと寸分違わず同一であることを照合する「完全性の保証」を提供し、レジストリ上での改ざんやすり替えを検知します。
  • 限界:ハッシュ検証は「記録時と同一であること」を確かめる仕組みであり、「内容が無害であること」を保証するものではありません。最初からバックドアが仕込まれたバージョンを取り込んでハッシュ値を固定してしまうと、不正なコードが正常な一致として通過し続けます。

2. SBOM(ソフトウェア部品表)

SBOMは、ソフトウェアに含まれるすべての部品の名称、バージョン、依存関係などを機械可読な形式(SPDXやCycloneDX等)で記録した一覧表です。

  • 果たせる役割:新たな脆弱性が公表された際、自社のどのシステムに該当部品が使われているかを横断的に把握し、初動調査を大幅に迅速化します。
  • 限界:SBOMは「部品の棚卸しリスト」であり、脆弱性の有無を検知したり、本番での到達可能性を判定したりする機能はありません。リストをもとに悪用可能性を評価する作業が別途必要です。

3. ビルド完全性の検証枠組み:SLSA(v1.2)

SLSA(Supply-chain Levels for Software Artifacts)仕様は、ソースコードから成果物がビルドされて配布されるまでの過程における改ざんを防ぐフレームワークです。

ソースコードからビルドを経て成果物を配布・検証するサプライチェーンにおいて、SLSA仕様(v1.2)は、ソフトウェア成果物の生成過程(ビルドプロセス)における改ざん防止と来歴(Provenance)検証の枠組みを提供しますが、コード自体の脆弱性の不存在や完全な安全性を証明するものではありません(SLSA v1.2 Specification Overview, Verifying artifacts)。

SLSAは、隔離されたビルド環境で生成されたことや、対象コミットの来歴情報に署名を付与し、ビルド途中での不正コード混入を防ぎます。組織全体のセキュリティ方針を包括的に定める NIST SP 800-218(SSDF)に対し、SLSAはパイプラインの改ざん防止と追跡可能性という技術的検証に特化しており、両者は補完関係にあります。

運用としてのサプライチェーン対策――自動テストの過信と「更新遅延」の罠

現場で直面する運用の課題として、「自動テストの過信」と「更新遅延」の二大リスクがあります。

CI/CD環境の自動テストがすべて成功しても、悪意あるコードが存在しない証明にはなりません。一般的なテストは仕様通りの動作を確かめるものであり、巧妙な不正コードは通常動作を妨げず、特定の環境変数や日時が揃ったときにだけ潜伏先から不正通信を行います。

一方で、リスクを恐れてライブラリの更新を長期間停止する「更新遅延」も危険です。古いバージョンを使い続けることは、世の中に公表された既知の脆弱性(CVE)を放置することを意味し、攻撃者にとって格好の標的となります。

現実的な運用としては、平時と有事の切り離しが有効です。

  • 平時の計画的更新:軽微な更新は定期的に適用します。一度に大量の更新を行わず、小さく頻繁に更新して変更差分(Changelog)を確認します。
  • 有事の緊急対応:悪用が確認された重大な脆弱性には、平時を待たずにパッチを適用する迅速なフローを用意します。
  • 段階的展開:更新成果物を開発・検証・本番環境へと段階的に展開し、ログや通信の異常を監視します。なお、最新版への更新によって新たな不具合が生じる可能性もあるため、動作検証を省略してはなりません。

よくある疑問と誤解(FAQ)

Q1: 有名でダウンロード数が多いライブラリだけを使っていれば安全ですか?

A1: 知名度や利用規模は安全性の保証になりません。 人気のある部品であっても、未発見の脆弱性が長年残っていることがあります。また、多忙なメンテナのアカウントが乗っ取られて悪意あるバージョンが公式配信されたり、有名部品が内部で依存している小さな間接依存部品が改ざんされたりするリスクもあります。知名度に関わらず、依存関係全体の把握と検証が必要です。

Q2: インストール時のスクリプト実行を無効化(--ignore-scripts 等)すれば安全ですか?

A2: 導入時のリスクは抑えられますが、完全な解決策ではありません。 パッケージ導入直後の初期設定スクリプト(preinstall など)による即時侵害を防ぐ効果はあります。しかし、アプリケーション起動時にライブラリが読み込まれた瞬間に動く不正コードや、明示的なビルド処理までは阻止できません。また、正規部品に必要なコンパイル処理が飛ばされ、正常に動かなくなる制約もあります。

Q3: ロックファイルとSLSAを導入すれば、サプライチェーン攻撃の脅威はなくなりますか?

A3: 製造・輸送の改ざんは防げますが、脅威がゼロになるわけではありません。 ロックファイルはファイルの一致を、SLSAはビルド手順の正しさを保証しますが、元のソースコード自体に含まれる脆弱性や、正規コードとして紛れ込んだ悪意あるロジックまでは無害化できません。完全性の検証に加え、コードレビュー、到達可能性の評価、最小権限での実行環境といった多層防御が不可欠です。

---

結び

ソフトウェアのサプライチェーン対策は、外部部品の排除や盲信ではなく、依存関係という「波及経路」を前提とした現実的な防御体制の構築にあります。

ロックファイルやSLSAによって製造・配布プロセスの完全性を確保し、改ざんを防ぎます。その上で、SBOMによる迅速な把握と、到達可能性や実行権限を踏まえた悪用可能性の評価を通じて、真に対処すべきリスクを優先度づけて管理します。各技術の役割と限界を理解し、多層防御と計画的な更新運用を両立させることが、依存関係の脅威からシステムを守る確かな指針となります。

出典・参考資料