0. はじめに
OWASP 発の SBOM 標準 CycloneDX については、概要・SPDX との位置づけ・スキーマ要素(Metadata / Components / Services / Dependencies / Compositions / Vulnerabilities / Formulation / Annotations / Extensions)・対応フォーマット(JSON / XML / Protobuf)を解説した入門記事が日本語・英語ともに出揃っています。本稿は仕様そのものの解説には踏み込みません。
代わりに、実プロダクトで CycloneDX をどう扱っているか を、CNAPP/CWPP ベンダーである Sysdig の実装に絞って踏み込んで解説します。読み終えると次が分かります。
- なぜ Sysdig が CycloneDX を採用したのか(SPDX ではなく)
- スキャナ種別(CLI / Cluster / Host / Registry / Agentless)と SBOM 抽出パイプラインの関係
- UI / API での SBOM 取得方法(curl 例つき)
- CycloneDX が規定する 9 要素が、Sysdig が吐き出す CycloneDX JSON のどこに対応するか
- ランタイム文脈(in-use 等)は SBOM の中に入るのか、それとも別経路なのか
- Dependency-Track など外部 SBOM プラットフォーム連携の現実解
⚠️ 本記事は公開ドキュメント・公式ブログを基にした執筆時点の情報です。API パスやスキーマは将来変更され得るため、運用に組み込む際は必ず最新の docs.sysdig.com を確認してください。
1. なぜ Sysdig は CycloneDX を選んだか
Sysdig はベンダーブログ "SBOM as a Core Element in Sysdig's CNAPP Strategy" で 「広く認知された CycloneDX フォーマットを採用する」 と明言しています。理由を整理すると次の 3 点です。
-
CNAPP の中核要素として SBOM が位置付けられている
Gartner が CNAPP の構成要素として SBOM を挙げており、Sysdig はこれを脆弱性管理ワークフローの「単一の真実」として据える設計を選びました。スキャナごとにバラバラのインベントリを持つのではなく、すべての検査経路から 同じ CycloneDX を出す ことで、後段(脆弱性突合、コンプラ、サプライチェーン連携)を一本化できます。 -
エコシステムの広さ
CycloneDX は OWASP プロジェクトで、Dependency-Track、cdxgen、cyclonedx-cli といった OSS 群が充実しています。Sysdig は SBOM の「生成 + リスク文脈付与」までを担当し、SBOM の保管・ダッシュボード化(Dependency-Track など)は外部 OSS に委ねるという棲み分けが組みやすい。 -
セキュリティ特化のスキーマ
CycloneDX は Vulnerabilities セクションをスキーマレベルで持つ(SPDX は主にライセンス起点)。Sysdig が出すのは「コンポーネント一覧 + 検出された脆弱性」の合体物なので、CycloneDX の方が表現がストレートです。
なお現時点で Sysdig が出力するのは CycloneDX JSON のみ で、XML / Protobuf や SPDX への変換は同梱されていません。SPDX が要件であれば、Sysdig から CycloneDX を取り出し、cyclonedx-cli convert などで橋渡しするのが現実解です。
2. 抽出パイプライン — どこで SBOM が生まれるか
Sysdig の Vulnerability Management は、検査位置の違う複数のスキャナを束ねる構成です。CycloneDX を吐き出す「SBOM 生成ツール」のレイヤがここに該当します。
| スキャナ | 対象 | 動作位置 |
|---|---|---|
| CLI Scanner | ローカル / CI のイメージ | 開発者 / Pipeline |
| Cluster Scanner | クラスタ上で稼働中のワークロード | Kubernetes 内 |
| Host Scanner | OS パッケージ・ホスト | VM / ノード |
| Registry Scanner | レジストリ上のイメージ | バックエンド |
| Agentless | クラウドの実体(イメージ・VM 等) | Sysdig 側 |
重要なのは、どの経路で検査しても CycloneDX 互換の SBOM がバックエンドに送られる という統一です。これによって、以下のような「同じ部品の見え方が違う」問題が抑えられます。
CI で scan したイメージ ─┐
クラスタで動いている同じイメージ ─┼─► 同じ assetId / 同じ SBOM
レジストリに置いてある同じイメージ ─┘
抽出された SBOM は内部の SBOM Database に格納されます。Sysdig ブログによれば、同一 SBOM の再抽出は回避され、以後は API 経由で参照 されます。これが効くのはレジストリスキャンとクラスタスキャンが同じイメージを指したときで、二重スキャンによる無駄を避ける設計です。
3. SBOM を取り出す — UI / API
3.1 UI から取り出す
Vulnerabilities → 該当スキャンタイプの Findings → 任意のスキャン結果を開く → Details タブ → Download SBOM で CycloneDX JSON が落ちます。
Vulnerabilities ─► <Pipeline / Runtime / Registry> ─► Findings
└─► Details ─► [Download SBOM]
「ある日付時点の構成証跡が欲しい」「監査人に渡すための凍結インベントリが必要」というユースケースはこれで足ります。
3.2 API で取り出す(自動化向け)
curl -X GET \
-H "Authorization: Bearer ${SYSDIG_API_TOKEN}" \
"https://${SYSDIG_HOSTNAME}/secure/vulnerability/v1beta1/sboms?assetId=sha256:xxxxxx&assetType=container-image"
クエリパラメータは次の 3 つ。
| パラメータ | 説明 |
|---|---|
assetId |
container-image なら imageId(sha256:...)、host なら hostId
|
assetType |
container-image または host
|
bomIdentifier |
単一 SBOM の URN(urn:uuid:...)。これだけでも取得可 |
「bomIdentifier のみ」と「assetId + assetType のセット」のどちらでも取得できる、というのが地味に効きます。コンプラ用途で 特定時点の SBOM スナップショット を保全しておきたい場合、bomIdentifier を控えておけば後から同じバージョンを再取得できる、という運用に向きます。
ホストの SBOM はイメージと違って レイヤ情報を持たない という点だけ注意。CycloneDX 上は components がフラットに並びます。
4. CycloneDX 9 要素と Sysdig 出力のマッピング
CycloneDX が規定する 9 要素について、Sysdig の出力でどう埋まる/埋まらないかを実務目線で整理します。
| CycloneDX 要素 | Sysdig 出力での状況 | コメント |
|---|---|---|
| Metadata | ◯ | スキャナ種別、対象アセット ID、タイムスタンプ等 |
| Components | ◎ | OS パッケージ + 言語ランタイム依存(Java / Python / Go / Node など)。コンテナイメージならレイヤ情報も保持 |
| Services | △ | 動的検出対象外。CycloneDX のサービスは「アプリが呼ぶ外部 API」を指す概念であり、SBOM 抽出器の責務外 |
| Dependencies | ◯ | パッケージマネージャから取れる範囲の依存関係 |
| Compositions | △ | 「完全か / 不完全か」のメタ。スキャナの取りこぼし宣言用途 |
| Vulnerabilities | ◎ | ここが Sysdig の本領。CVE、CVSS、修正バージョン、ベンダー情報 |
| Formulation | × | CI/CD の生成過程記述(v1.5 追加)。Sysdig は対象外 |
| Annotations | △ | 拡張用途 |
| Extensions | △ | 拡張用途 |
ポイントは Vulnerabilities が最初から豊富に埋まっていることです。多くの SBOM 生成器(Syft 等)は components だけを吐き、vulnerabilities は別ツール(Grype 等)で後付けします。Sysdig は SBOM 抽出と脆弱性突合が同じパイプラインに乗っている ため、出力 JSON に CVE がそのまま含まれます。「セキュリティに特化した BOM」という CycloneDX 本来の設計思想と、Sysdig の実装が綺麗に重なるところです。
5. SBOM に入らないもの — ランタイム文脈は別経路
ここは見落とされがちなのですが、Sysdig の強みである ランタイム文脈(パッケージが実際にプロセスとしてロードされているか = in-use、外部公開されているか、特権実行か など)は、CycloneDX SBOM の中には基本的に入りません。
理由は単純で、CycloneDX は「ソフトウェアの構成」を表すフォーマットであり、「実行時に何が起きているか」を表す場ではないからです。Sysdig 側ではこれらの文脈は Findings レイヤ(Vulnerabilities Findings 画面 / Risk Spotlight / Runtime Insights)で SBOM に オーバーレイ されます。
[CycloneDX SBOM] [Sysdig Findings レイヤ]
components ──┐
CVEs ──┼──► 突合 ──► in-use / exposure / fix availability
│ └─► 優先順位付け(Risk Spotlight)
metadata ──┘
実務上のインパクトはこうです。
- 「SBOM を Dependency-Track に流して脆弱性をダッシュボード化」 のような外部連携をやる場合、CycloneDX の枠で取れるのは "components + CVE" まで。
- 「どの CVE を真っ先に潰すべきか」 という優先順位付けは Sysdig 側の UI / API に残ったままで、外部 SBOM ツールには移送されない。
- 外部連携先と Sysdig 側を両方見る か、Sysdig の Findings API を経由してランタイム属性を別フィールドとして付与した拡張 JSON を作る、のいずれかが現実解になります。
6. ユースケース別の使い分け
6.1 監査・コンプラ証跡(NTIA / EO 14028 / 経産省ガイドライン対応)
- Findings 画面 → Download SBOM で十分。
- リリース版の
bomIdentifierを成果物として控えておき、監査時に同じ ID で再取得できることを示せれば、トレーサビリティが取れる。
6.2 外部 SBOM プラットフォーム連携(Dependency-Track 等)
- 定期的に
GET /secure/vulnerability/v1beta1/sbomsを回し、Dependency-Track のBOM APIに POST する小さな同期ジョブを組むのが王道。 - 注意:Dependency-Track は自身でも脆弱性突合をするので、Sysdig 側の CVE 検出結果と二重表示 になる。プロジェクト方針として「脆弱性の正は Sysdig」「コンポーネントインベントリの長期保管は Dependency-Track」のように責務を分けると衝突しません。
6.3 CI/CD で「壊れたら止める」ゲート
- これは SBOM ダウンロードではなく CLI Scanner で実現するレイヤ。SBOM はビルド成果物の一部として保管し、ゲート判断はスキャナ終了コードを使う、という二段構えが安定。
6.4 サードパーティ製品の組み込み確認
- ベンダーから受領した CycloneDX を Sysdig に取り込む方向の インジェスト は、執筆時点では一般機能としては提供されていません。受領 SBOM の検証は
cyclonedx-cli validateなどの OSS と併用するのが現実的です。
7. ハマりやすいポイント
| 症状 | 原因 | 対処 |
|---|---|---|
| Download SBOM ボタンが見当たらない | スキャン結果がまだ生成されていない / 権限不足 | Findings 一覧で結果が出ているか、ロールに Vulnerability Management の読み取り権限があるか確認 |
| API が 404 |
assetId のフォーマット間違い(sha256: プレフィックス漏れ) |
imageId を Findings の Details からそのままコピー |
CycloneDX のはずなのに vulnerabilities 配列が空 |
古いスキャン結果 / 一致した CVE が無い | 再スキャン、または DB の最新化を待つ |
| SPDX が欲しい | Sysdig は CycloneDX JSON のみ出力 |
cyclonedx-cli convert --output-format spdxjson で変換 |
| ホスト SBOM にレイヤが無い | 仕様 | コンテナイメージのみレイヤ持ち |
8. まとめ
- Sysdig は CNAPP の中核データとして CycloneDX を採用 している。
- すべてのスキャナ経路(CLI / Cluster / Host / Registry / Agentless)が 同じ CycloneDX JSON をバックエンドに集約し、SBOM Database で重複抽出を避ける構造。
- UI(Findings → Download SBOM)と API(
/secure/vulnerability/v1beta1/sboms)の両方で取り出せる。 - 9 要素のうち Vulnerabilities が最初から埋まっている のが Sysdig 出力の特徴で、SBOM 生成と脆弱性突合が同じパイプライン上にあることの帰結。
- ただし ランタイム文脈(in-use / exposure 等)は CycloneDX の枠外 で、外部 SBOM ツール連携時はそこが取り残されることを前提に運用を設計する必要がある。
「SBOM を作って終わり」ではなく、作った SBOM を CNAPP のリスク優先順位付けに直結させるという捉え方が、Sysdig が CycloneDX を採用したことの本質です。CycloneDX に初めて触れる方は、まず仕様や入門記事を一読したうえで本稿に進んでいただけると、「実プロダクトでの SBOM の使われ方」のイメージが掴みやすいと思います。
参考リンク
- SBOM as a Core Element in Sysdig's CNAPP Strategy - Sysdig Blog
- Vulnerability Findings - Sysdig Docs
- Vulnerability Management - Sysdig Docs
- What is a Software Bill of Materials (SBOM)? - Sysdig
- CycloneDX Tool Center
Appendix A: Sysdig が出す CycloneDX JSON の抜粋
以下は Sysdig Secure が
/secure/vulnerability/v1beta1/sbomsから返す CycloneDX 1.5 JSON の代表構造 です。実テナントから取得したいときは末尾の curl ワンライナーを使ってください。フィールド名・階層は実物に合わせていますが、値はサニタイズ済みのダミーです。
{
"bomFormat": "CycloneDX",
"specVersion": "1.5",
"serialNumber": "urn:uuid:5a3c9d68-1f4a-4d7e-9b2c-7e8a51b3f0a2",
"version": 1,
"metadata": {
"timestamp": "2026-05-25T11:42:17Z",
"tools": [
{
"vendor": "Sysdig",
"name": "sysdig-cluster-scanner",
"version": "1.21.4"
}
],
"component": {
"type": "container",
"bom-ref": "pkg:oci/payments-api@sha256:9f3b...c1?repository_url=us-docker.pkg.dev/higaki-sysdig-training/demo",
"name": "payments-api",
"version": "sha256:9f3b...c1",
"purl": "pkg:oci/payments-api@sha256:9f3b...c1"
}
},
"components": [
{
"type": "operating-system",
"bom-ref": "os-debian-12.5",
"name": "debian",
"version": "12.5",
"description": "Debian GNU/Linux 12 (bookworm)"
},
{
"type": "library",
"bom-ref": "pkg:deb/debian/openssl@3.0.11-1~deb12u2",
"name": "openssl",
"version": "3.0.11-1~deb12u2",
"purl": "pkg:deb/debian/openssl@3.0.11-1~deb12u2?arch=amd64&distro=debian-12",
"properties": [
{ "name": "sysdig:layer", "value": "sha256:7e3a...f4" },
{ "name": "sysdig:package-type", "value": "os" }
]
},
{
"type": "library",
"bom-ref": "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.13.4.1",
"name": "jackson-databind",
"group": "com.fasterxml.jackson.core",
"version": "2.13.4.1",
"purl": "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.13.4.1",
"properties": [
{ "name": "sysdig:layer", "value": "sha256:b21d...09" },
{ "name": "sysdig:package-type", "value": "java" },
{ "name": "sysdig:path", "value": "/app/libs/jackson-databind-2.13.4.1.jar" }
]
},
{
"type": "library",
"bom-ref": "pkg:pypi/requests@2.28.1",
"name": "requests",
"version": "2.28.1",
"purl": "pkg:pypi/requests@2.28.1",
"properties": [
{ "name": "sysdig:layer", "value": "sha256:c0f1...aa" },
{ "name": "sysdig:package-type", "value": "python" }
]
}
],
"dependencies": [
{
"ref": "pkg:oci/payments-api@sha256:9f3b...c1",
"dependsOn": [
"os-debian-12.5",
"pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.13.4.1",
"pkg:pypi/requests@2.28.1"
]
},
{
"ref": "os-debian-12.5",
"dependsOn": [ "pkg:deb/debian/openssl@3.0.11-1~deb12u2" ]
}
],
"vulnerabilities": [
{
"bom-ref": "vuln-cve-2022-42003",
"id": "CVE-2022-42003",
"source": { "name": "NVD", "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-42003" },
"ratings": [
{
"source": { "name": "NVD" },
"score": 7.5,
"severity": "high",
"method": "CVSSv31",
"vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"
}
],
"cwes": [502],
"description": "In FasterXML jackson-databind ... deeply nested data may lead to DoS via stack overflow.",
"advisories": [
{ "url": "https://github.com/FasterXML/jackson-databind/issues/3590" }
],
"published": "2022-10-02T05:15:00Z",
"updated": "2024-02-13T18:15:00Z",
"affects": [
{
"ref": "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.13.4.1",
"versions": [
{ "version": "2.13.4.1", "status": "affected" }
]
}
],
"properties": [
{ "name": "sysdig:fix-version", "value": "2.13.4.2" },
{ "name": "sysdig:exploitable", "value": "false" }
]
}
]
}
読み方のコツ
-
metadata.toolsで「どの Sysdig スキャナが出した SBOM か」が分かる(sysdig-cli-scanner/sysdig-cluster-scanner/sysdig-host-scanner/sysdig-registry-scanner/sysdig-agentless-scanner)。監査時に「いつ / どこで」のトレーサビリティに使える。 -
components[*].propertiesのsysdig:layerがコンテナレイヤ ID、sysdig:pathがインストール先パス。ホスト SBOM では layer は無い。 -
vulnerabilities[*].propertiesにsysdig:fix-versionとsysdig:exploitableが乗ることがある。in-useなどのランタイム文脈はここには出てこない(本編で触れた通り、別 API になります)。 -
dependenciesは OS パッケージマネージャ / 言語マネージャから取れた範囲のみ。動的ロードや dlopen は当然取れない。
テナントから実物を取ってきて差し替える
export SYSDIG_API_TOKEN='xxxx'
export SYSDIG_HOSTNAME='us2.app.sysdig.com' # SaaS US East の例
ASSET_ID='sha256:9f3b...c1' # Findings → Details からコピー
curl -sS -X GET \
-H "Authorization: Bearer ${SYSDIG_API_TOKEN}" \
"https://${SYSDIG_HOSTNAME}/secure/vulnerability/v1beta1/sboms?assetId=${ASSET_ID}&assetType=container-image" \
| jq '{
bomFormat, specVersion, serialNumber,
tool: .metadata.tools[0].name,
image: .metadata.component.name,
n_components: (.components | length),
n_vulns: (.vulnerabilities | length),
sample_component: .components[0],
sample_vuln: .vulnerabilities[0]
}'
最後の jq で「何が入っているか」だけ要約できるので、まずこれを叩いて全体感を掴むのがオススメです。
Appendix B: Sysdig → Dependency-Track 連携 Python スクリプト
Dependency-Track を SBOM の長期保管・棚卸しダッシュボードとして使うパターン用の同期スクリプトです。requests だけで動きます。
設計方針
- 入力は
(project_name, project_version, asset_id, asset_type)の CSV - Sysdig から CycloneDX を取り、Dependency-Track の
POST /api/v1/bom(multipart)にそのまま渡す -
autoCreate=trueを付けて、初回はプロジェクト自動生成 - 失敗は行単位でロギングし、全行終わるまで止めない
sysdig_to_dtrack.py
#!/usr/bin/env python3
"""
Sysdig Secure から CycloneDX SBOM を取得し、Dependency-Track に取り込む。
使い方:
export SYSDIG_API_TOKEN=...
export SYSDIG_HOSTNAME=us2.app.sysdig.com
export DTRACK_API_KEY=...
export DTRACK_URL=https://dtrack.example.com
python sysdig_to_dtrack.py assets.csv
assets.csv (ヘッダ必須):
project_name,project_version,asset_id,asset_type
payments-api,2026.05.25,sha256:9f3b...c1,container-image
web-frontend,2026.05.25,sha256:1aa2...77,container-image
"""
import csv
import logging
import os
import sys
from typing import Iterator
import requests
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")
log = logging.getLogger("sysdig2dtrack")
def env(name: str) -> str:
v = os.environ.get(name)
if not v:
log.error("missing env var: %s", name)
sys.exit(2)
return v
SYSDIG_HOST = env("SYSDIG_HOSTNAME")
SYSDIG_TOKEN = env("SYSDIG_API_TOKEN")
DTRACK_URL = env("DTRACK_URL").rstrip("/")
DTRACK_KEY = env("DTRACK_API_KEY")
SBOM_ENDPOINT = f"https://{SYSDIG_HOST}/secure/vulnerability/v1beta1/sboms"
DT_BOM_ENDPOINT = f"{DTRACK_URL}/api/v1/bom"
def fetch_sbom(asset_id: str, asset_type: str) -> bytes:
"""Sysdig から CycloneDX JSON を取得して bytes で返す。"""
r = requests.get(
SBOM_ENDPOINT,
headers={"Authorization": f"Bearer {SYSDIG_TOKEN}"},
params={"assetId": asset_id, "assetType": asset_type},
timeout=60,
)
r.raise_for_status()
if r.headers.get("Content-Type", "").startswith("application/json"):
body = r.content
if b'"bomFormat"' not in body or b'"CycloneDX"' not in body:
raise ValueError("response is not CycloneDX JSON")
return body
raise ValueError(f"unexpected content-type: {r.headers.get('Content-Type')}")
def push_to_dtrack(project_name: str, project_version: str, sbom: bytes) -> None:
"""Dependency-Track の BOM upload API に流し込む。"""
files = {"bom": ("bom.json", sbom, "application/json")}
data = {
"projectName": project_name,
"projectVersion": project_version,
"autoCreate": "true",
}
r = requests.post(
DT_BOM_ENDPOINT,
headers={"X-Api-Key": DTRACK_KEY},
files=files,
data=data,
timeout=120,
)
r.raise_for_status()
def rows(path: str) -> Iterator[dict]:
with open(path, newline="") as f:
reader = csv.DictReader(f)
required = {"project_name", "project_version", "asset_id", "asset_type"}
if not required.issubset(reader.fieldnames or set()):
log.error("CSV header must include %s", required)
sys.exit(2)
yield from reader
def main(csv_path: str) -> int:
ok, ng = 0, 0
for row in rows(csv_path):
label = f"{row['project_name']}@{row['project_version']}"
try:
sbom = fetch_sbom(row["asset_id"], row["asset_type"])
push_to_dtrack(row["project_name"], row["project_version"], sbom)
log.info("OK %s (%d bytes)", label, len(sbom))
ok += 1
except requests.HTTPError as e:
log.error("HTTP %s %s body=%s", label, e, e.response.text[:200])
ng += 1
except Exception as e:
log.error("FAIL %s %s", label, e)
ng += 1
log.info("done ok=%d ng=%d", ok, ng)
return 0 if ng == 0 else 1
if __name__ == "__main__":
if len(sys.argv) != 2:
print("usage: sysdig_to_dtrack.py assets.csv", file=sys.stderr)
sys.exit(2)
sys.exit(main(sys.argv[1]))
運用上の TIPS
- Dependency-Track 側が CVE を再突合するため、Sysdig の CVE と件数が一致しないことがあります。これは「ナレッジソースの違い」で正常。運用上の正は Sysdig 側 と決めておくと混乱しません。
-
大量プロジェクトを毎日同期したいなら、
autoCreate=trueだけだと孤児プロジェクトが溜まるので、定期的に Dependency-Track のDELETE /api/v1/project/{uuid}で掃除するジョブを別途。 -
asset_idを毎回手書きするのは現実的でないので、本番では Sysdig 側の runtime/pipeline 結果一覧 API からassetIdを列挙 → CSV を吐く前処理を挟むのがオススメです(ここでは紙幅の都合で割愛)。
1 行 cron 化
# 毎日 03:00 に同期
0 3 * * * /usr/bin/env -i SYSDIG_HOSTNAME=us2.app.sysdig.com SYSDIG_API_TOKEN=... DTRACK_URL=https://dtrack.example.com DTRACK_API_KEY=... /usr/bin/python3 /opt/sync/sysdig_to_dtrack.py /opt/sync/assets.csv >> /var/log/sysdig2dtrack.log 2>&1
Appendix C: cyclonedx-cli convert で SPDX に橋渡しする
CycloneDX/cyclonedx-cli を使うと、Sysdig が吐いた CycloneDX を SPDX や CSV に変換できます。Docker 版が一番手軽です。
インストール
# macOS (Homebrew)
brew install cyclonedx/cyclonedx/cyclonedx-cli
# あるいは Docker
docker pull cyclonedx/cyclonedx-cli:latest
alias cyclonedx='docker run --rm -i -v "$PWD":/work -w /work cyclonedx/cyclonedx-cli'
1. CycloneDX JSON → SPDX JSON
cyclonedx convert \
--input-file payments-api.cdx.json \
--input-format json \
--output-file payments-api.spdx.json \
--output-format spdxjson
2. CycloneDX JSON → XML / Protobuf
# XML
cyclonedx convert -i payments-api.cdx.json -o payments-api.cdx.xml --output-format xml
# Protobuf (バイナリ)
cyclonedx convert -i payments-api.cdx.json -o payments-api.cdx.bin --output-format protobuf
3. 監査向けに CSV へフラット化
cyclonedx convert \
-i payments-api.cdx.json \
-o payments-api.csv \
--output-format csv
→ Excel で開いて部品リストとして配布する用途に。
4. バージョン降格(古いツールに渡すとき)
Sysdig は CycloneDX 1.5 を吐きますが、相手ツールが 1.4 までしか食えない、というケースに。
cyclonedx convert \
-i payments-api.cdx.json \
-o payments-api.v14.cdx.json \
--output-format json \
--output-version v1_4
5. 検証 (validate)
外部から受け取った SBOM をそのまま信用しないために。
cyclonedx validate \
--input-file vendor-supplied.cdx.json \
--input-format json \
--input-version v1_5 \
--fail-on-errors
CI に組み込んでおくと、サプライヤーが壊れた SBOM を投げてきたときに止められます。
6. 差分 (diff)
「先月リリースと今月リリースで構成がどう変わったか」を見る用途。
cyclonedx diff \
payments-api.2026-04.cdx.json \
payments-api.2026-05.cdx.json \
--component-versions
7. マージ (merge)
マイクロサービス群を一つのプロダクト SBOM にまとめて顧客に渡す用途。
cyclonedx merge \
--input-files payments-api.cdx.json web-frontend.cdx.json worker.cdx.json \
--hierarchical \
--name "MyProduct" \
--version "2026.05.0" \
--output-file myproduct.cdx.json
--hierarchical を付けると各入力 SBOM の root component が myproduct の依存として保持されるので、後で「どのサービスが何に依存していたか」を辿れる構造になります。フラット結合したい場合は外す。
8. バッチ変換シェル
Sysdig からまとめて落としてきた SBOM 群を一括で SPDX に変換する例。
for f in sboms/*.cdx.json; do
base=$(basename "$f" .cdx.json)
cyclonedx convert \
-i "$f" \
-o "sboms/${base}.spdx.json" \
--input-format json \
--output-format spdxjson \
&& echo "converted: $base"
done