Log4Shellが公表された2021年12月、多くの企業が最初にぶつかったのは「直すのが難しい」ではありませんでした。そもそも自社の製品にlog4jが入っているのか分からない、でした。持ち物の一覧がなければ、危ないと言われても照合のしようがありません。SBOM(Software Bill of Materials)は、この一覧をつくる仕組みです。
部品表という発想
BOM(Bill of Materials)は製造業の言葉で、製品を構成する部品の一覧を指します。自動車のリコールが成立するのは、どの車体にどのロットの部品が付いたかを追えるからです。
ソフトウェアには長いあいだ、これがありませんでした。手元のアプリケーションには何百というパッケージが入ります。そのほとんどは依存の依存として自動で降ってきたもので、開発した本人でさえ全部は把握していません。何を積んだか分からないまま出荷している、という状態が普通にありました。
SBOMは、その中身を機械可読な形で書き出したものです。何が、どの版で、どこから来て、何に依存しているか。それだけを持ちます。
SPDXとCycloneDX
代表的な形式は二つあり、生まれた動機が違います。
SPDXはLinux Foundationが育てた形式で、出自はライセンス管理にあります。オープンソースを製品に組み込むとき、どのライセンスが混ざっているかを追う必要がありました。2021年にISO/IEC 5962:2021として国際規格になっています。
CycloneDXはOWASPのプロジェクトです。最初からセキュリティを向いていて、脆弱性情報やVEXとの連携が設計に入っています。
どちらを選ぶかは、何に使うかで決まります。ライセンス監査まで含めるならSPDX、脆弱性の照合が主目的ならCycloneDXが扱いやすくなります。両方を出力できるツールも多くあります。
何が書かれているか
形式は違っても、中心にある情報は近いものです。
- コンポーネント名と版:
log4j-coreの2.14.1のように特定できる粒度で - 識別子:
purl(Package URL)のような、エコシステムを含めた一意の名前 - ハッシュ:本当にその中身かを確かめるため
- ライセンス:法務側が使う
- 依存関係:どの部品がどの部品を必要としているか
なかでもpurlが効きます。エコシステム(npmやPyPIのような、言語ごとの部品配布の仕組み)と名前と版を、一つの文字列にまとめる書き方です。
pkg:npm/lodash@4.17.21
pkg:pypi/requests@2.31.0
pkg:maven/org.apache.logging.log4j/log4j-core@2.14.1
同名でもnpmとPyPIは別物です。この区別がないまま名前だけで突き合わせると、無関係な脆弱性を拾います。逆に、エコシステムの表記が揺れていれば該当を見落とします。地味ですが、照合の成否はここで決まります。
深さが問題になります
SBOMを出したから安心、とはなりません。どこまで深く書けているかで価値が変わります。
直接インストールしたパッケージだけを並べたSBOMは、ほとんど役に立ちません。実際の脆弱性の多くが依存の依存として入ってきたものから出るためです。Log4Shellのときも、log4jを直接指定していた組織は少数派でした。
依存ツリー全体を辿れているかは、生成の方法で決まります。
ビルド時に取るのが正確です。実際に解決された版が確定しているので、ロックファイルと同じ情報が得られます。
できあがったものから推測する方法もあります。コンテナイメージを走査してパッケージを見つけ出す形で、手軽なかわりに、静的にリンクされたものやパッケージ管理を経ずに置かれたファイルは落ちます。
ソースコードから読む方法は、その中間です。宣言を読むだけなので速いのですが、版が固定されていなければ実際に入るものと食い違います。package.jsonの^1.2.0という記述からは、入る版が決まりません。
三つのうちどれを選ぶかは、何を保証したいかによります。出荷物の中身を証明したいならビルド時、既に動いているものを調べたいなら走査、設計段階の見通しならソースコードになります。
脆弱性データベースと組み合わせる
SBOM単体では何も判定しません。判定は、脆弱性データベースと突き合わせて初めて出ます。
SBOMが「何を持っているか」、OSVやGHSAが「何が壊れているか」。片方だけでは何も出ませんが、この二つを突き合わせると「自分に該当するものはどれか」がようやく決まります。
そのためSBOMの品質は、そのまま照合の精度になります。版が曖昧なら該当判定も曖昧になりますし、間接依存が抜けていればそこは丸ごと見えません。
AIを積むと、部品表の対象が広がります
モデルを組み込んだシステムでは、SBOMの守備範囲が足りなくなります。
動いているのはコードだけではありません。事前学習モデル、微調整の重み、埋め込みの索引、プロンプトの雛形。どれも外から持ち込まれて差し替わっていくのに、従来のパッケージ管理には乗りません。
そこでAI BOM(AI Bill of Materials)という考え方が出てきました。モデルの出所、版、学習データの由来、評価の結果までを部品として記録します。CycloneDXは機械学習向けの記述に対応しています。
考え方は同じです。外から持ち込んだものを、持ち込んだと書き残す。 対象がライブラリからモデルへ広がっただけになります。
制度がSBOMを求めはじめました
技術的な便利さだけでなく、外から要求されるようになってきました。
アメリカでは2021年の大統領令14028が、連邦政府に納入するソフトウェアへのSBOM添付を求めました。調達の条件になった時点で、事実上の必須になります。
EUのサイバーレジリエンス法(CRA)も、デジタル製品にコンポーネントの把握を求めます。適用は段階的ですが、向いている方向は同じです。
日本でも、経済産業省がSBOM導入の手引を出しています。まだ義務ではありませんが、取引先から求められる場面は増えています。
受け取る側が、何を求めるか
自分で作っていないソフトウェアを社内に入れるとき、SBOMは調達の道具になります。
「セキュアに作ってください」では何も決まりませんが、「納品物にSBOMを付けてください」なら確かめられます。しかも受け取ったあと、新しい脆弱性が公表されるたびに自分で照合できます。開発会社に問い合わせて返事を待つ必要がなくなります。
求めるときは、三点を書いておくと揉めにくくなります。
- 形式と版:SPDXかCycloneDXか、どの版か
- 深さ:直接依存だけか、間接依存まで含むか
- 更新の約束:リリースのたびに出し直すのか、年に一度なのか
三番目が抜けやすいところです。初回だけ受け取っても、次のリリースで中身が変わればその一覧は使えなくなるので、いつ出し直すかまで含めて合意しておく必要があります。
過信しないための注意
SBOMは、ある時点の写しにすぎません。 ビルドのたびに中身は変わります。古いSBOMを見て「入っていない」と判断すると外れます。生成を自動化して、成果物と一緒に配るのが前提になります。
書いてあることの正しさは、生成器の性能で決まります。 同じイメージから複数のツールでSBOMを取ると結果が一致しないことがあり、取りこぼしも余計な検出も起きます。
一覧があることと、安全であることは違います。 SBOMは「何を持っているか」に答えるだけで、「危ないか」には答えません。そこは到達可能性の判断や、VEXのような仕組みが受け持ちます。
配り方も決めておく必要があります。 作っただけで手元に置いていては、取引先から求められたときに出せません。成果物と同じ場所に置き、版ごとに残します。署名を添えて改ざんを検出できるようにする組織もあります。
まとめ
SBOMが解決したのは、脆弱性そのものではありません。問いに答えられる状態をつくったことの方が大きな変化でした。
「うちにlog4jは入っていますか」に、調べればすぐ答えられます。この一点が、事故が起きてからの動きを変えます。持ち物が分かっていない状態では、対処の前に調査から始めることになります。
外から出所の分からない部品を取り込んで動かす場面が増えるほど、何を取り込んだかを書き残しておく価値は上がっていきます。自社の状況を確かめるなら、直近の納品物にSBOMが付いているか、付いているなら間接依存まで含まれているかの二点から見てください。次のリリースで出し直す約束があるかどうかも、あわせて確認しておく価値があります。