はじめに
ソフトウェアサプライチェーンの透明性とセキュリティ確保のために、SBOM(Software Bill of Materials) の重要性が高まっています。SBOMは、ソフトウェアに含まれるすべてのコンポーネントの一覧を記録したソフトウェア部品表であり、脆弱性管理やライセンスコンプライアンスに不可欠な情報源です。
そこで、SBOM生成ツールを利用して、ソースコード、バイナリ、コンテナなどからソフトウェアに含まれるすべてのコンポーネントや依存関係を自動的に検出し、SBOMとして出力します。
しかし、SBOM生成ツールはライセンス情報や外部参照などが欠落していることも多く、実運用においてはEnrichment(エンリッチメント)が必要になります。
そこで、SBOMのEnrichmentについて調べてみました。
Enrichmentとは
Enrichmentとは、SBOM生成ツールが出力したSBOMに対して、追加情報を付加するプロセスを指します。これには、以下のような情報が含まれます:
- ライセンス情報の追加
- 脆弱性情報の付与
- 外部参照の追加 (CPE、PURLなど)
- メタデータの補完 (バージョン情報、リリース日など)
Enrichmentを行うことで、SBOMの有用性が向上し、セキュリティリスクの評価やコンプライアンスチェックがより効果的に行えるようになります。
Enrichmentの方法
Enrichmentを実施する方法として、以下のアプローチがあります:
- 手動による補完: 専門家がSBOMをレビューし、必要な情報を手動で追加します。これは小規模なプロジェクトや特定の重要なコンポーネントに対して有効です
- 自動化ツールの利用: 複数のSBOM Enrichmentツールが存在し、これらを利用して自動的に情報を付加します。例えば、OSSライセンスデータベースや脆弱性データベースと連携することで、効率的にEnrichmentが可能です
- カスタムスクリプトの作成: 特定のニーズに応じて、独自のスクリプトを作成し、SBOMに必要な情報を追加する方法もあります
Enrichmentのツール例
以下は、SBOMのEnrichmentに利用できる代表的なツールの例です:
- parlay: SBOMにライセンス情報や脆弱性情報を追加するためのオープンソースツールです。
- Syft: コンテナイメージやファイルシステムからSBOMを生成し、Enrichmentもサポートしています。
- cdx-enrich: CycloneDX形式のSBOMに対して、脆弱性情報やライセンス情報を追加するためのツールです。
- sbomasm: SBOMの生成とEnrichmentを行うためのツールであり、複数のデータソースと連携して情報を補完します。
以下は代表的なツールの parlay と sbomasm の比較です:
| sbomasm | parlay | |
|---|---|---|
| 概要 | 完全なSBOM管理ツールキット | SBOMを外部サービスのデータで強化するツール |
| 主な機能 | SBOM生成・管理 | SBOM拡張 (Snyk連携) |
| 用途 | SBOMの作成・管理 | SBOMに脆弱性情報や外部データを追加 |
| 対応SBOM形式 | SPDX, CycloneDX | SPDX, CycloneDX |
| データソース | ClearlyDefined | ecosyste.ms, Snyk, OpenSSF Scorecard |
| 開発言語 | Go | Go |
| ライセンス | Apache License Version 2.0 | Apache License Version 2.0 |
| 強み | SBOM生成・標準対応 | 外部サービス連携による情報強化 |
| 利用シナリオ | DevSecOpsでSBOMを標準化・管理 | SBOMに脆弱性情報を追加しリスク評価を強化 |
SBOMのライセンス情報の自動補完
sbomasm の enrich 機能とParlayを使ってライセンス情報を自動補完してみます。
以下は、GridDB の修正前 SBOM です。このSBOMを使ってどのように補完されるか確認します。なお、確認用のため最小項目で記述しています。
{
"bomFormat" : "CycloneDX",
"specVersion" : "1.6",
"metadata" : {
"component" : {
"type" : "library",
"name" : "com.github.griddb:gridstore",
"version" : "5.6.0",
"purl" : "pkg:maven/com.github.griddb/gridstore@5.6.0"
}
},
"components" : [
{
"type" : "library",
"name" : "org.slf4j:slf4j-api",
"version" : "1.7.7",
"purl" : "pkg:maven/org.slf4j/slf4j-api@1.7.7"
},
{
"type" : "library",
"name" : "org.slf4j:slf4j-jdk14",
"version" : "1.7.7",
"purl" : "pkg:maven/org.slf4j/slf4j-jdk14@1.7.7"
}
]
}
実行環境はAlmaLinux 9.7 です。
sbomasmのenrich機能でSBOMのライセンス情報を自動補完する方法
sbomasm の enrich 機能を使って ライセンス情報を自動補完してみます。
- 対象:ライセンス情報が NOASSERTION や OTHER のコンポーネント
- 必須条件:PURL (Package URL) が存在すること。PURLがない場合、補完はできません
- データソース:ClearlyDefined API
sbomasm で GridDB のSBOMにライセンス情報を補完します:
$ sbomasm enrich --fields="license" griddb.cdx.json --output enriched_griddb1.cdx.json
Fetching Components Response...
3 / 3 [--------------------------------------------------------------------------------------------------] 100.00% 4 p/s
Enriching SBOM...
3 / 3 [--------------------------------------------------------------------------------------------------] 100.00% ? p/s
Total: 3, Selected: 3, Enriched: 3, Skipped: 0, Failed: 0
3つのコンポーネントが enrich されていることが出力されています。
以下は、enrich 後の SBOM です。3つのコンポーネントのライセンス情報が追加されています:
{
"bomFormat": "CycloneDX",
"specVersion": "1.6",
+ "version": 0,
"metadata": {
"component": {
"type": "library",
"name": "com.github.griddb:gridstore",
"version": "5.6.0",
+ "licenses": [
+ {
+ "license": {
+ "id": "Apache-2.0",
+ "acknowledgement": "declared"
+ }
+ }
+ ],
"purl": "pkg:maven/com.github.griddb/gridstore@5.6.0"
}
},
"components": [
{
"type": "library",
"name": "org.slf4j:slf4j-api",
"version": "1.7.7",
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT",
+ "acknowledgement": "declared"
+ }
+ }
+ ],
"purl": "pkg:maven/org.slf4j/slf4j-api@1.7.7"
},
{
"type": "library",
"name": "org.slf4j:slf4j-jdk14",
"version": "1.7.7",
+ "licenses": [
+ {
+ "license": {
+ "id": "MIT",
+ "acknowledgement": "declared"
+ }
+ }
+ ],
"purl": "pkg:maven/org.slf4j/slf4j-jdk14@1.7.7"
}
]
}
このように、sbomasm の enrich 機能でライセンス情報を補完することができました。
現在、sbomasm の enrich 機能ではライセンス情報しか enrich できませんが、copyright, security, metadata の補完を計画しているそうです。
parlayでSBOMのライセンス情報を自動補完する方法
parlay を使って ライセンス情報を自動補完してみます。
- 対象:パッケージが対応するエコシステムであること (npm, maven, pypi, gem, cargo, composer, golang, nugetなど)
- 必須条件:PURL (Package URL) が存在すること、PURLがない場合、パッケージ名、エコシステム情報が必要
- データソース:ecosyste.ms
parlay で GridDB のSBOMにライセンス情報を補完します:
$ cat griddb.cdx.json | parlay ecosystems enrich - | jq > enriched_griddb2.cdx.json
以下は、enrich 後の SBOM です。3つのコンポーネントのライセンス情報が追加されています:
{
"bomFormat": "CycloneDX",
"specVersion": "1.6",
+ "version": 0,
"metadata": {
"component": {
"type": "library",
+ "supplier": {
+ "name": "GridDB",
+ "url": [
+ "https://griddb.org"
+ ]
+ },
+ "author": "GridDB",
"name": "com.github.griddb:gridstore",
"version": "5.6.0",
- "purl" : "pkg:maven/com.github.griddb/gridstore@5.6.0"
+ "description": "Java Client for GridDB CE",
+ "licenses": [
+ {
+ "expression": "(The Apache License OR Version 2.0)"
+ }
+ ],
+ "purl": "pkg:maven/com.github.griddb/gridstore@5.6.0",
+ "externalReferences": [
+ {
+ "url": "https://github.com/griddb/griddb/tree/master/java_client",
+ "type": "website"
+ },
+ {
+ "url": "https://central.sonatype.com/artifact/com.github.griddb/gridstore/",
+ "type": "distribution"
+ },
+ {
+ "url": "https://github.com/griddb/griddb",
+ "type": "vcs"
+ },
+ {
+ "url": "https://appdoc.app/artifact/com.github.griddb/gridstore/",
+ "type": "documentation"
+ }
+ ],
+ "properties": [
+ {
+ "name": "ecosystems:first_release_published_at",
+ "value": "2019-02-05T06:03:28Z"
+ },
+ {
+ "name": "ecosystems:latest_release_published_at",
+ "value": "2025-06-03T10:41:02Z"
+ },
+ {
+ "name": "ecosystems:topic",
+ "value": "bigdata"
+ },
+ {
+ "name": "ecosystems:topic",
+ "value": "database"
+ },
+ {
+ "name": "ecosystems:topic",
+ "value": "fast"
+ },
+ {
+ "name": "ecosystems:topic",
+ "value": "griddb"
+ },
+ {
+ "name": "ecosystems:topic",
+ "value": "iot"
+ },
+ {
+ "name": "ecosystems:topic",
+ "value": "newsql"
+ },
+ {
+ "name": "ecosystems:topic",
+ "value": "nosql"
+ },
+ {
+ "name": "ecosystems:topic",
+ "value": "sql"
+ },
+ {
+ "name": "ecosystems:topic",
+ "value": "time-series"
+ },
+ {
+ "name": "ecosystems:topic",
+ "value": "timeseries"
> }
> ]
}
},
"components": [
{
"type": "library",
+ "supplier": {
+ "name": "QOS.CH (Switzerland)",
+ "url": [
+ "http://www.qos.ch"
+ ]
+ },
+ "author": "QOS.CH (Switzerland)",
"name": "org.slf4j:slf4j-api",
"version": "1.7.7",
- "purl" : "pkg:maven/org.slf4j/slf4j-api@1.7.7"
+ "description": "The slf4j API",
+ "licenses": [
+ {
+ "expression": "(MIT)"
+ }
+ ],
+ "purl": "pkg:maven/org.slf4j/slf4j-api@1.7.7",
+ "externalReferences": [
+ {
+ "url": "http://www.slf4j.org",
+ "type": "website"
+ },
+ {
+ "url": "https://central.sonatype.com/artifact/org.slf4j/slf4j-api/",
+ "type": "distribution"
+ },
+ {
+ "url": "https://github.com/qos-ch/slf4j",
+ "type": "vcs"
+ },
+ {
+ "url": "https://appdoc.app/artifact/org.slf4j/slf4j-api/",
+ "type": "documentation"
+ }
+ ],
+ "properties": [
+ {
+ "name": "ecosystems:first_release_published_at",
+ "value": "2006-11-09T20:49:35Z"
+ },
+ {
+ "name": "ecosystems:latest_release_published_at",
+ "value": "2025-02-25T16:43:14Z"
+ },
+ {
+ "name": "ecosystems:owner_location",
+ "value": "Switzerland"
+ }
+ ]
},
{
"type": "library",
+ "supplier": {
+ "name": "QOS.CH (Switzerland)",
+ "url": [
+ "http://www.qos.ch"
+ ]
+ },
+ "author": "QOS.CH (Switzerland)",
"name": "org.slf4j:slf4j-jdk14",
"version": "1.7.7",
- "purl" : "pkg:maven/org.slf4j/slf4j-jdk14@1.7.7"
+ "description": "SLF4J JDK14 Provider",
+ "licenses": [
+ {
+ "expression": "(MIT)"
+ }
+ ],
+ "purl": "pkg:maven/org.slf4j/slf4j-jdk14@1.7.7",
+ "externalReferences": [
+ {
+ "url": "http://www.slf4j.org",
+ "type": "website"
+ },
+ {
+ "url": "https://central.sonatype.com/artifact/org.slf4j/slf4j-jdk14/",
+ "type": "distribution"
+ },
+ {
+ "url": "https://github.com/qos-ch/slf4j",
+ "type": "vcs"
+ },
+ {
+ "url": "https://appdoc.app/artifact/org.slf4j/slf4j-jdk14/",
+ "type": "documentation"
+ }
+ ],
+ "properties": [
+ {
+ "name": "ecosystems:first_release_published_at",
+ "value": "2005-11-08T22:27:38Z"
+ },
+ {
+ "name": "ecosystems:latest_release_published_at",
+ "value": "2025-02-25T16:43:58Z"
+ },
+ {
+ "name": "ecosystems:owner_location",
+ "value": "Switzerland"
+ }
+ ]
}
]
}
parlayはsbomasmと比較して、より多くの外部情報(supplier、author、description、externalReferencesなど)を追加できていることを確認できます。
Enrichmentのベストプラクティス
Enrichmentを効果的に行うためのベストプラクティスとして、以下の点が挙げられます:
- 信頼性の高いデータソースの利用: ライセンス情報や脆弱性情報は、信頼性の高いデータベースから取得することが重要です
- 定期的な更新: ソフトウェアコンポーネントは頻繁に更新されるため、SBOMも定期的にEnrichmentを行い、最新の情報を反映させることが必要です
- ドキュメント化: Enrichmentのプロセスや使用したデータソースをドキュメント化し、将来的なメンテナンスや監査に備えることが推奨されます
Enrichmentの課題
Enrichmentにはいくつかの課題も存在します。
- データの一貫性: 複数のデータソースから情報を取得する場合、データの一貫性を保つことが難しいことがあります:
- スケーラビリティ: 大規模なプロジェクトでは、Enrichmentのプロセスが複雑化し、スケーラビリティの問題が発生することがあります
- コスト: 手動でのEnrichmentは時間とコストがかかるため、効率的な自動化が求められます
まとめ
本記事では、SBOMのEnrichment(エンリッチメント)について、その概念から実践的な活用方法まで紹介しました。
SBOM生成ツールだけでは、ライセンス情報や外部参照などの重要な情報が欠落していることが多く、実運用においてEnrichmentは不可欠なプロセスです。Enrichmentを行うことで、以下のメリットが得られます:
- セキュリティリスクの可視化: 脆弱性情報を付与することで、リスク評価が容易になります
- ライセンスコンプライアンスの確保: 正確なライセンス情報により、法的リスクを低減できます
-
運用効率の向上: 自動化により、継続的なSBOM管理が実現できます
また、本記事で紹介したsbomasmとparlayは、それぞれ異なる特徴を持っています: - sbomasm: ライセンス情報の補完に特化し、シンプルで使いやすい。今後の機能拡張も期待できます
- parlay: より多くの外部情報(supplier、author、description、externalReferencesなど)を追加でき、包括的なEnrichmentが可能です
プロジェクトの要件に応じて、適切なツールを選択することが重要です。
SBOMのEnrichmentは、ソフトウェアサプライチェーンセキュリティにおいて今後ますます重要になっていくと考えられます。自動化ツールの進化により、より効率的で正確なEnrichmentが可能になることが期待されます。
掲載内容は、個人の見解です。コメント等は広くご意見を頂ければ幸いです。
掲載内容は個人の見解です。ご意見・ご指摘はコメントや編集リクエストでフィードバックいただけると幸いです。
参考資料
- sbomasm
- parlay
- sbomasm VS parlay : Compare sbomasm vs parlay and see what are their differences.
- parlayで脆弱性情報をSBOMの結果に出力させてみた
商標について
本ページに記載されている社名及び商品名はそれぞれ各社が商標または登録商標として使用している場合があります。本ページでは、商標「™」、登録商標「®」マークは原則として明記しておりません。