組み込みLinuxの開発で「SBOM」という言葉を聞く機会が増えた。EUの新しい規制は2027年にSBOMの提出義務を課す。医療機器ではすでに義務化されている。
この記事では、Yocto Scarthgap 5.0 LTS(BitBake 2.8)の標準機能だけで、SBOMの生成からCVE脆弱性スキャンまでを実践する。規制の背景から具体的な設定・運用方法まで、1記事で完結する内容だ。
組み込み開発でSBOMが必須になる背景
SBOM(Software Bill of Materials)は、ソフトウェアに含まれるコンポーネントの一覧表だ。どのライブラリが入っていて、バージョンはいくつで、ライセンスは何か。それを機械可読な形式で記録したものを指す。
「うちは小さいから関係ない」と思うかもしれない。しかし、EU向け・米国向け・車載向けに製品を出荷しているなら、すでにあなたのチームに影響がある。
EUサイバーレジリエンス法(CRA)
2024年12月に発効した。全要件の適用は 2027年12月11日。デジタル要素を含む製品をEU市場で販売するすべての事業者が対象だ。日本企業でもEU向けに輸出していれば適用される。
SBOMに関する具体的な要求:
- 機械可読形式(SPDX / CycloneDX)でSBOMを作成・維持する
- 市場監視当局への提出義務
- 違反時の罰則は最大 1,500万ユーロ または全世界年間売上の2.5%
医療機器(FDA)
米国FDAは 2023年3月 からSBOMの提出を義務化している。FD&C法 Section 524B(PATCH Act)に基づき、市販前申請にSBOMが必須だ。SBOM未提出の場合、FDAが申請の受理を拒否できる。
車載(UN-R155 / R156)
UN-R155はSBOMを名指しで要求する法規ではない。しかし、サイバーセキュリティ管理システム(CSMS)の運用にはソフトウェア構成の把握が不可欠で、SBOMなしでは脆弱性管理が回らない。日本では2024年7月から全新型車両でUN-R155準拠が必須になっている。
日本国内
法的な義務化はまだない。ただし、経産省が「SBOMの導入に関する手引」を整備しており(ver 2.0を2024年8月公表)、将来の法制化への布石とみられている。2025年9月には15か国共同のSBOM国際ガイダンスに日本も署名した。
create-spdxでSBOMを生成する
Scarthgapでは、Pokyのデフォルトdistro設定(poky.conf)が INHERIT += "create-spdx" を含んでおり、 デフォルトで有効 だ。通常のビルドを実行するだけで、SBOMが自動生成される。
有効になっているか確認する
bitbake-getvar -r core-image-minimal INHERIT
出力に create-spdx が含まれていれば有効だ。含まれていなければ、conf/local.conf に以下を追加する。
# conf/local.conf — create-spdxを手動で有効化(通常は不要)
INHERIT += "create-spdx"
推奨設定
# conf/local.conf — SBOM生成の推奨設定
SPDX_PRETTY = "1"
SPDX_PRETTY を有効にすると、JSONにインデントが入って人間が読みやすくなる。ファイルサイズは増えるが、デバッグやレビュー時に重宝する。
ソースコードの追跡まで必要な場合は、以下も追加する。
# conf/local.conf — ソース情報をSBOMに含める(オプション)
SPDX_INCLUDE_SOURCES = "1"
SPDX_ARCHIVE_SOURCES = "1"
ビルドと出力の確認
通常どおりビルドを実行する。
bitbake core-image-minimal
ビルド完了後、SBOMは以下に出力される。
tmp/deploy/images/<MACHINE>/core-image-minimal-<MACHINE>.spdx.tar.zst
展開して中身を確認する。
cd tmp/deploy/images/qemux86-64/
mkdir spdx-output && cd spdx-output
tar -I zstd -xf ../core-image-minimal-qemux86-64.spdx.tar.zst
ls *.spdx.json | head -10
SBOMの出力を読む
展開すると、レシピごとにSPDXファイルが生成されている。各ファイルはSPDX 2.2形式のJSONだ。
ファイル構成
spdx-output/
├── recipe-core-image-minimal.spdx.json ← イメージ全体
├── recipe-busybox.spdx.json ← 個別レシピ
├── recipe-glibc.spdx.json
├── recipe-openssl.spdx.json
└── ...
JSONの主要フィールド
個別のSPDXファイルを開くと、以下のような構造になっている(簡略化して表示)。
{
"spdxVersion": "SPDX-2.2",
"dataLicense": "CC0-1.0",
"name": "recipe-openssl",
"packages": [
{
"name": "openssl",
"versionInfo": "3.2.1",
"supplier": "Organization: OpenSSL",
"downloadLocation": "https://www.openssl.org/source/openssl-3.2.1.tar.gz",
"licenseConcluded": "Apache-2.0",
"licenseDeclared": "Apache-2.0"
}
],
"relationships": [
{
"spdxElementId": "SPDXRef-Recipe",
"relationshipType": "GENERATES",
"relatedSpdxElement": "SPDXRef-Package-openssl"
}
]
}
コンプライアンス対応で重要な情報:
- packages: パッケージ名、バージョン、ライセンス、ダウンロード元
- relationships: レシピとパッケージの依存関係
- licenseConcluded / licenseDeclared: ライセンス情報(監査で必ず確認される)
cve-checkで脆弱性をスキャンする
cve-check クラスは、ビルドしたパッケージをNIST NVD(National Vulnerability Database)と照合し、既知の脆弱性を検出する。create-spdx とは異なり、 手動で有効化が必要 だ。
有効化
# conf/local.conf — CVEチェックを有効化
INHERIT += "cve-check"
特定レシピのCVEチェック
bitbake -c cve_check openssl
イメージ全体のCVEチェック
INHERIT += "cve-check" が設定されていれば、通常のビルドでCVEレポートが自動生成される。
bitbake core-image-minimal
レポートの場所
tmp/deploy/cve/
├── openssl ← レシピ単位テキスト
├── openssl_cve.json ← レシピ単位JSON
└── ...
tmp/deploy/images/<MACHINE>/
├── core-image-minimal-<MACHINE>.cve ← イメージ全体テキスト
└── core-image-minimal-<MACHINE>.cve.json ← イメージ全体JSON
テキスト、JSON両方がデフォルトで出力される。
レポートの読み方
テキスト形式のレポートには、各CVEのステータスが記載される。
PACKAGE NAME: openssl
PACKAGE VERSION: 3.2.1
CVE: CVE-2024-XXXXX
CVE STATUS: Patched
CVE SUMMARY: ...
CVE: CVE-2024-YYYYY
CVE STATUS: Unpatched
CVE SUMMARY: ...
ステータスは3種類:
- Patched: Yoctoのパッチで修正済み
- Unpatched: 未修正。対応が必要
- Ignored: 意図的に無視(
CVE_STATUSで設定)
CVEレポートのノイズを減らす
CVEチェックを有効にすると、大量のCVEが報告される。特にLinuxカーネルは数千のCVEが登録されており、その大半は使用しているアーキテクチャやカーネルコンフィグに関係ないものだ。
CVE_STATUSで個別にマークする
特定のCVEがプラットフォームに該当しない場合、CVE_STATUS で除外できる。
# レシピ内またはbbappendで設定
CVE_STATUS[CVE-2024-12345] = "not-applicable-platform: Only affects Windows"
CVE_STATUS[CVE-2024-67890] = "not-applicable-config: Feature disabled in our config"
ステータス値は cve-check-map.conf で定義済みの種類から選ぶ。主なものは not-applicable-platform、not-applicable-config、cpe-incorrect、upstream-wontfix など。コロンの後に理由を記述することで、監査に耐える記録になる。bbappendを使えば、元のレシピを変更せずにCVE除外設定を管理できる。なお、Kirkstoneから移行する場合は CVE_CHECK_IGNORE から CVE_STATUS への書き換えが必要だ(移行チェックリストを参照)。
CVE_STATUS_GROUPSで一括管理する
同じ理由で除外するCVEが多い場合、グループ化すると管理しやすい。
# conf/local.conf またはカスタムincファイル
CVE_STATUS_GROUPS = "CVE_STATUS_WIN CVE_STATUS_ARM32"
CVE_STATUS_WIN = "CVE-2024-11111 CVE-2024-22222 CVE-2024-33333"
CVE_STATUS_WIN[status] = "not-applicable-platform: Windows-only vulnerability"
CVE_STATUS_ARM32 = "CVE-2024-44444 CVE-2024-55555"
CVE_STATUS_ARM32[status] = "not-applicable-platform: ARM32-only, we target ARM64"
レイヤー単位でスキャン範囲を制限する
自社レイヤーだけをチェックしたい場合に便利だ。
# conf/local.conf — 自社レイヤーのみチェック
CVE_CHECK_LAYER_INCLUDELIST = "meta-mylayer"
# または特定レイヤーを除外
CVE_CHECK_LAYER_EXCLUDELIST = "meta-poky"
公式の除外リストを活用する
Pokyには事前定義のCVE除外リストが含まれている。
# conf/local.conf
include conf/distro/include/cve-extra-exclusions.inc
実運用のワークフロー
SBOMとCVEチェックを日常のビルドフローに組み込む方法を整理する。
conf/local.confの推奨設定
# conf/local.conf — SBOM + CVEの推奨設定
# SBOM生成(デフォルト有効だが明示しておく)
INHERIT += "create-spdx"
SPDX_PRETTY = "1"
# CVEチェック
INHERIT += "cve-check"
# 公式CVE除外リスト
include conf/distro/include/cve-extra-exclusions.inc
ビルドごとのフロー
1. bitbake <image>
↓ 自動
2. SBOM生成 → tmp/deploy/images/MACHINE/IMAGE.spdx.tar.zst
↓ 自動
3. CVEレポート生成 → tmp/deploy/images/MACHINE/IMAGE.cve
↓
4. Unpatched CVEの確認・対応
↓
5. SBOM + CVEレポートをバージョン管理に保存
UnpatchedなCVEを抽出する
# テキスト形式でUnpatchedを抽出
grep -B 3 "CVE STATUS: Unpatched" \
tmp/deploy/images/qemux86-64/core-image-minimal-qemux86-64.cve
問題が見つかった場合の対処フローはビルドエラーデバッグガイドのdevshellセクションも参考になる。
EU CRA対応チェックリスト
| # | 項目 | Yoctoでの対応方法 |
|---|---|---|
| 1 | 機械可読SBOMの作成 | create-spdx(デフォルト有効) |
| 2 | 既知脆弱性のスキャン | cve-check |
| 3 | 脆弱性への対応記録 | CVE_STATUS に理由を記録 |
| 4 | SBOMの定期更新 | リリースビルドごとにSBOM再生成 |
| 5 | 当局への提出準備 | .spdx.tar.zst を成果物として保管 |
まとめ
SBOMとCVE管理は、もう「余裕があればやること」ではない。EU CRAの2027年期限、FDAの既存義務、車載UN-R155の実質要求——規制は確実に迫っている。
Yocto Scarthgapでの対応は、実はシンプルだ。
| やること | 方法 | 手間 |
|---|---|---|
| SBOM生成 | create-spdx(デフォルト有効) | ほぼゼロ |
| CVEスキャン | INHERIT += "cve-check" | conf/local.confに1行 |
| ノイズ除外 | CVE_STATUS + 理由記録 | 初回のみ手間がかかる |
| 運用 | ビルドごとにSBOM + CVEレポート保管 | CI/CDに組み込めば自動 |
SBOMはすでにデフォルトで生成されている。CVEチェックは1行の設定で有効になる。規制対応の第一歩は、思ったより簡単だ。