この記事は “The Surprise of Multiple Dependency Graphs” を基に自分で更なる調査をした内容です。
Log4j や XZUtils の事件があってから、ますますソフトウェアサプライチェーンを管理する必要性が浸透してきました。これは、ソフトウェアを開発するにあたって使用しているパッケージやライブラリなどの他のソフトウェア(ディペンデンシー)を把握し、それらのソフトウェアに脆弱性が報告された際に対応できるようにすること。
実際に使用しているディペンデンシーを把握するのはそう簡単ではない。例えばパッケージAを使用しているとする。パッケージA自体がパッケージB、C、Dを使っているとする。これらはそれぞれパッケージAの直接的ディペンデンシー(direct dependency)である。そこでパッケージBも他のディペンデンシーを使っていて、パッケージE、Fをディペンデンシーとして持つ。するとパッケージEはパッケージAの推移的ディペンデンシー(transitive dependency)として定義される。
あるソフトウェアが使用するすべてのディペンデンシー、及びそれらの関係を表したものがディペンデンシーグラフ(dependency graph)と呼ばれている。
このディペンデンシーグラフを把握するために SBOM (Software Bill of Materials) というものが存在する。
ディペンデンシーグラフは一意に定まらない
SBOM とはその言葉の意味の通りで、使用しているディペンデンシーを列挙しているものである。
SBOM はエクセキュータブルなアプリケーションを配布する際には実際に効果的だと言える。なぜならそのアプリケーションに入るディペンデンシーは全て作者によって知られているためである。ではなぜこの記事のタイトルでは SBOM を虚構だと呼ぶのか。オープンソースのパッケージを見ると話が変わってくる。
例えば npm
にある webpack
という人気なパッケージには現在数百万通りの可能なディペンデンシーグラフがある。ディペンデンシーの関係を解決するときの状況の差異によりディペンデンシーグラフは一意に定まらない。例えばそのパッケージをビルドしているコンピュータの OS、ディペンデンシー管理ツールごとの違い(JavaScript には npm
、yarn
、pnpm
などによってディペンデンシーの解決の仕様が違う)などが挙げられる。
Lockfile も一意ではない
ディペンデンシーの解決の仕様が違うことから、今は多くのエコシステムにて Lockfile が導入されている。Lockfile で各ディペンデンシーの特定のバージョンを指定することによって、(多くの場合)SemVer で表記していた、幅のあるバージョンの表記より決定的である。
しかし、Lockfile は可能なディペンデンシーグラフの中の一つのグラフを提示しているものであって、唯一のグラフを示しているわけではない。
そのため、Lockfile を絶対的なディペンデンシーグラフとして参照するのも危険を孕んでいる。
一意に定まらないのはそんなに問題なのか?
Lockfile などの導入により、開発者の間でのディペンデンシーの差はほとんどなくなり、支障をきたすことが大分減った。
npm
の webpack
には数百万の可能なディペンデンシーグラフがあるが、実際にはグラフはランダムに決定しないため、似たようなグラフになる。他の似たような規模のディペンデンシーグラフ数を持つパッケージの調査によると、現実で行われるディペンデンシーの解決ではランダムに選ぶより遥かに高い確率で全く同じディペンデンシーグラフを取得し、同じ時間にディペンデンシーの取得を行うとその確率はさらに上がる。
現実ではほとんど問題なくソフトウェアが開発され、稼働しているため、多くの場合は問題ないと言える。けれどセキュリティのリスクを考えると、ディペンデンシーグラフが一意に定まらない問題は検討しても良いはずだ。
サプライチェーンセキュリティの対策の一つに脆弱性スキャナーがある。これらのスキャナーは SBOM や Lockfile を参照し、脆弱なディペンデンシーを探している。ただこの記事で書いてきたように、SBOM や Lockfile はあくまで何百万通りと有り得るディペンデンシーグラフの一つを表しており、それは開発者が作成した段階のものとなっている。そのため、攻撃される対象であるサーバで稼働している際に使用されているディペンデンシーとそれらのバージョンとは異なる可能性がある。デプロイされているものに脆弱なバージョンのディペンデンシーが稼働していれば、それは攻撃対象となってしまう。