# ソフトウェア部品表（SBOM） {#sbom}

各イメージには、含まれるコンポーネントを列挙した [CycloneDX](https://cyclonedx.org/) 形式の SBOM が付属します。
イメージ内に読み取れるパッケージ DB を含めないため、SBOM はイメージのランタイム依存 **クロージャ**（closure）から生成します。
クロージャとは、コンテナが実際に載せるストアパスを、各バイナリが依存する共有ライブラリまでたどって集めたものです。
そのため SBOM は、実行時のコンテナに実際に何が入っているかを正確に表します。

:::info
Takumi Images は現在ベータ版です。
仕様や挙動が予告なく変更される可能性があります。
:::

SBOM の中身は、コンポーネントの列です。
次は、busybox イメージの SBOM に実際に入っている busybox コンポーネントの抜粋です。

```json
{
  "bom-ref": "xpp0j7j90g2nbr382bi2ym0ln9ykli6l-busybox-1.37.0",
  "type": "application",
  "name": "busybox",
  "version": "1.37.0",
  "purl": "pkg:nix/busybox@1.37.0",
  "cpe": "cpe:2.3:a:busybox:busybox:1.37.0:*:*:*:*:*:*:*",
  "externalReferences": [
    {
      "type": "vcs",
      "url": "https://busybox.net/downloads/busybox-1.37.0.tar.bz2",
      "hashes": [
        {
          "alg": "SHA-256",
          "content": "3311dff32e746499f4df0d5df04d7eb396382d7e108bb9250e7b519b837043a4"
        }
      ]
    }
  ],
  "pedigree": {
    "patches": [
      {
        "type": "unofficial",
        "diff": { "text": { "content": "（適用したパッチの diff 本文）" } }
      }
    ]
  }
}
```

確認すべき点は 4 つあります。
`bom-ref` は Nix のストアパスに対応しており、どの入力からビルドされたコンポーネントかまで一意に特定できます。
`externalReferences` には、取得した上流ソースの URL とハッシュがそのまま残ります。
`cpe` は脆弱性データベース（NVD）との突き合わせに使う識別子で、弊社が管理する対応表に基づいて付与しています。このため、公開している SBOM は、一般的なスキャナで脆弱性照合を行うための入力としても利用できます。
そして `pedigree.patches` には、弊社がそのパッケージに適用したパッチの中身が diff ごと記録されます。説明に加えて、diff そのものが SBOM に残ります。

## SBOM の対象範囲 {#scope}

SBOM が対象とするのは、あくまでランタイムのクロージャです。
Go や Rust のようにコンパイルするプログラムでは、ビルド時にリンクした言語レベルのモジュールが、配布イメージの中で個別のファイルにならないため、SBOM のコンポーネントとしては現れません。
この違いは、Takumi が保証する範囲と、利用者が引き受ける範囲を分ける境界のひとつです。
どこまでを Takumi が担うかは、[責任共有モデル](/docs/ja/t/images/limitation/shared-responsibility) にまとめています。

## アーキテクチャごとに異なる内容 {#per-arch}

SBOM は、amd64 と arm64 で内容が異なります。
同じパッケージでも、ビルドしたアーキテクチャによってストアパスが変わるため、SBOM 上のコンポーネント識別子もアーキテクチャごとに変わります。
そのため SBOM は、マルチアーキテクチャの index ではなく、アーキテクチャごとの子イメージに添付します。

## 取り出し方 {#recover}

index から目的のアーキテクチャの子 digest を取り出し、その SBOM を `--type cyclonedx` で検証します。

```bash
CHILD_DIGEST=$(crane manifest images.flatt.tech/takumi/busybox:latest \
  | jq -r '.manifests[] | select(.platform.architecture=="amd64").digest')

cosign verify-attestation \
  --certificate-oidc-issuer=https://token.actions.githubusercontent.com \
  --certificate-identity-regexp 'https://github.com/flatt-security/takumi-images/.github/workflows/release.yml@.*' \
  --type cyclonedx \
  "images.flatt.tech/takumi/busybox@${CHILD_DIGEST}" \
  | jq -r '.payload' | base64 -d | jq '.predicate'
```

この attestation を信頼できるものにしている署名の仕組みは、[Attestation](/docs/ja/t/images/features/attestations/#verify-attestation) を参照してください。
