ソフトウェアサプライチェーンのセキュリティは、専任のセキュリティ部門を持つ大きな組織の課題のように聞こえます。しかし、その捉え方こそが誤解のもとです。いくつかのサービスを運用しているだけの小さなチームでも、実際には誰も中身を読んだことのない数百のパッケージに依存しています。それらはビルドのたびに、自分たちが管理していないレジストリから取得され、デプロイ用の認証情報が置かれているマシンの上でインストールスクリプトを実行します。

危険にさらされる度合いは、会社の規模には比例しません。依存パッケージの数と、ビルドがどこまで自動化されているかに比例します。そして小さなチームほど、前者は多く抱えている一方で、後者に目を光らせる人は少ない、という状態になりがちです。この問題を公に心配している大きな組織と比べても、条件はむしろ厳しいのです。

居心地の悪い計算: あなたのアプリケーションには、直接の依存関係がおそらく十数個、間接的な依存関係が数百個あります。十数個はあなたが選びました。残りはあなたが選んだものではなく、そのどれ一つとして中身を読んでいません。そして、そのうちのどれか一つがインストールスクリプトを実行すれば、あなたのビルドプロセスとまったく同じ権限を手にします。これが実際の攻撃面であり、あなた自身が書いた依存関係の一覧を眺めても、そこには見えてきません。


サプライチェーンの危険はインストール時に始まる

危険な瞬間は、たいていコードを実行するときではありません。コードをインストールするときです。

パッケージマネージャーは、インストールの最中にスクリプトを実行することを許しています。つまり、乗っ取られたパッケージや悪意をもって作られたパッケージは、インストールコマンドを打った人の権限でそのまま動きます。開発者のマシンであれば、その開発者の認証情報です。ビルドパイプラインであれば、デプロイ用の鍵です。後者のほうが、はるかに深刻な事態になります。

実際に起きている事故の大半は、次の三つの攻撃の形で説明できます。

タイポスクワッティング。 よく使われるパッケージと名前が一文字だけ違うパッケージを公開しておき、インストールコマンドの打ち間違いを待つ手口です。仕掛けるコストはほとんどかからず、母数が大きくなるほど確実に成果が出ます。

正規パッケージのアカウント乗っ取り。 広く使われているパッケージのメンテナーが認証情報を盗まれ、有害なものを混ぜた新しいバージョンが公開されるケースです。これがいちばん防ぎにくい形です。名前にもダウンロード数にも、おかしなところが何一つないからです。

Dependency Confusion、つまり依存関係の取り違え。 社内向けパッケージと同じ名前で公開レジストリにパッケージを置かれ、設定を誤ったリゾルバが自社のプライベートレジストリよりも公開レジストリを優先してしまう攻撃です。まるごと設定の問題であり、まるごと防げます。

いずれの攻撃も、誰かがあなたを名指しで狙う必要がありません。そこが肝心な点です。機会があれば誰にでも当たり、いくらでも規模を広げられます。

小さなチームでも効果が見合う対策

ロックファイルをリポジトリに入れ、そこからインストールする。 ロックファイルは、正確なバージョンとそのハッシュを固定します。これに対してマニフェストからインストールすると、ビルドのたびに新しいバージョンが解決されます。ビルドは再現できなくなり、上流の変更が誰のレビューも通らないまま本番へ届いてしまいます。ロックファイルと食い違ったときに黙って書き換えるコマンドではなく、その場で失敗するコマンドを使ってください。

インストールスクリプトは、止められるところでは止める。 多くのエコシステムがこの設定に対応しており、大半のパッケージはそもそもインストールスクリプトを必要としていません。追加のツールを一つも導入せずに得られる、最大の露出削減です。そして、これを止めたせいで動かなくなる少数のパッケージこそ、中身を把握しておく価値のあるパッケージです。

脆弱性の通知を自動化し、そのうえで仕分ける。 スキャナーは、小さなチームが手を動かせる量をはるかに超える検出結果を吐き出します。失敗の形は、通知を見落とすことではありません。ほとんどが自分たちには関係ないという理由で、通知そのものを全部無視するようになることです。自分たちのコードから実際に到達しうるものだけに絞り込み、それだけを片づけてください。誰も読まないキューは、キューが無いよりも悪い状態です。

ビルドのツール類も固定する。 コンテナイメージ、ランタイムのバージョン、パイプラインが呼び出すアクションやプラグインも、すべて依存関係です。不変のダイジェストではなく変更可能なタグを参照している限り、ビルドはあなたの知らないところで変わり続けます。

ビルド用の認証情報を、他のすべてから切り離す。 デプロイできるパイプラインが、それ以上のことができる認証情報まで抱えているべきではありません。そして、乗っ取られたビルドから本番のデータに手が届くようであってもいけません。

SBOMで分かることと分からないこと

ソフトウェア部品表、略してSBOMは、アプリケーションの中に何が入っているかを一覧にしたものです。その価値は、たった一つの問いに素早く答えられることに尽きます。うちは影響を受けるのか、という問いです。

かつてこの問いに答えるには何日もかかりました。広く使われている部品に脆弱性が見つかったとき、最新の一覧を持っている組織は数分で答えを出し、持っていない組織は一週間を探索に費やします。この差こそが根拠のすべてであり、SBOMの導入が推し進められているのも、それが高度な対策ではなく基本的な実務だからです。

一方でSBOMがしてくれないのは、あなたを安全にすることです。一覧は一覧であって、防御ではありません。そこに並んだ脆弱性が自分たちのコードから到達しうるのか、自分たちの構成で本当に問題になるのか、すでに何かが侵害されているのか。そのどれについてもSBOMは答えません。作って保管しただけのチームは、対策ではなく書類を一つ増やしただけです。

生成はビルドの工程から行ってください。そうすれば、マニフェストが主張していた内容ではなく、実際に出荷されたものを記述できます。リリースごとに、それに対応するものを残しておいてください。そして、その価値が、追い詰められた状況で投げかけられる問いにどれだけ速く答えられるか、という一点にあることを受け入れてください。

小さなチームが実際に痛い目を見る場所

珍しいパッケージ侵害が原因になることは、めったにありません。もっとありふれたことが原因です。

リポジトリに置かれたシークレット。 削除しても履歴には残り続け、プッシュから数分のうちに自動スキャナーに見つかります。三年前から更新されていない依存関係。 公開済みの攻撃コードがあるのに、アップグレードの道筋がありません。上げる作業を先送りし続けた結果、それ自体が一つのプロジェクトの規模になってしまったからです。権限が広すぎるビルドパイプライン。 フォークから来たプルリクエストが、本来持つべきでないアクセス権で動いてしまいます。誰も見ていないこと。 どの通知も人間のところまで届かないため、侵害された状態がそのまま続きます。

華やかさのない結論になりますが、実務におけるサプライチェーンセキュリティの大半は、依存関係を最新に保つ作業そのものです。多くのチームが任意のものとして扱うソフトウェア保守費用は、まさに同じ作業を指しています。そして先送りは、日常的なアップグレードを、攻撃コード付きの緊急事態へと変えてしまいます。

身の丈に合った出発点

小さなチームなら、この順番で進めてください。まずリポジトリからシークレットを取り除き、外に出た可能性のあるものはすべて入れ替えます。次にロックファイルをコミットし、そこから厳密にインストールします。依存関係の通知を有効にし、常時ではなく週に一度まとめて仕分けます。ビルドのツール類を不変の参照に固定します。パイプラインの権限を必要最小限まで削ります。ここまで整ってから、リリースごとにSBOMを生成します。

この順番なら、専任のセキュリティ部門がなくても現実的な脅威をひととおり覆えますし、それぞれの工程にかかるのは週単位ではなく時間単位です。その先にある対策、つまり来歴の証明、再現可能なビルド、署名済みの成果物は、いずれも本当に価値があります。ただし、それらは基礎がすでに安定して回っている段階のための対策です。

Mecanikはアプリケーションセキュリティ分析の一環として、ビルドパイプラインの点検と強化を行っています。見つかるものが高度な侵害であることは、ほとんどありません。リポジトリに残されたトークンが一つ、そして選ばれた日から誰も更新していない依存関係が一つ、というのが実情です。



よくある質問

パッケージのインストールが危険な瞬間なのはなぜですか。 パッケージマネージャーがインストール中のスクリプト実行を許しており、そのスクリプトがインストールを実行した人の権限で動くからです。開発者のマシンならその人の認証情報、ビルドパイプラインならデプロイ用の鍵にあたります。そのコードがアプリケーションから呼び出されていなくても、被害を出すことは十分に可能です。

Dependency Confusionとは何ですか。 社内向けパッケージと同じ名前で公開レジストリにパッケージが登録され、設定を誤ったリゾルバが自社のプライベートレジストリより公開レジストリを優先してしまう攻撃です。誰かがあなたを名指しで狙う必要はなく、リゾルバの設定を正すことでまるごと防げます。

SBOMは実際に何をもたらしますか。 たった一つの問いに素早く答えられることです。うちは影響を受けるのか、という問いに、最新の一覧があれば数分で、なければ一週間の探索で答えることになります。並んだ脆弱性が自分たちのコードから到達しうるのか、すでに何かが侵害されているのかは分かりません。だから、作って保管しただけのSBOMは対策ではなく書類にとどまります。

ロックファイルはコミットすべきですか。 はい。そのうえで、食い違ったときに黙って更新するコマンドではなく失敗するコマンドを使い、厳密にそこからインストールしてください。マニフェストからインストールすると、ビルド時に新しいバージョンが解決され、ビルドは再現できなくなり、上流の変更がレビューを一切経ずに本番へ届いてしまいます。

小さなチームはどこから始めるべきですか。 リポジトリからシークレットを取り除いて外に出たものを入れ替え、ロックファイルをコミットして厳密にインストールし、依存関係の通知を有効にして週ごとに仕分け、ビルドのツール類を不変の参照に固定し、パイプラインの権限を削り、そのうえでリリースごとにSBOMを生成してください。どの工程も週単位ではなく時間単位で終わります。