MENU

SBOMをコンテナビルドパイプラインに組み込む|syftとgrypeで脆弱性スキャンゲートを設計する手順

目次

なぜコンテナビルドにSBOMゲートが必要か(2026年の現状)

コンテナイメージは往々にして数百のパッケージを含んでいます。ベースイメージ由来のライブラリ、アプリケーション依存、ビルドツールの残骸――これらの正確な一覧が手元になければ、CVEが公開されたとき「自分たちのイメージが影響を受けるかどうか」をゼロから調べ直すことになります。その調査コストは、スキャンを自動化しておくコストの数倍になるのが現場の実態です。

Software Bill of Materials(SBOM)は、成果物に含まれるコンポーネントの目録です。2021年のEO 14028(米大統領令)以降、連邦調達を絡む場面ではSBOMの添付が求められるようになり、エンタープライズや重要インフラ分野でも事実上の標準として定着しつつあります。2026年現在、OSSエコシステム側の対応も成熟し、SBOMの生成と消費を自動化するツールが揃ってきました。

重要なのは「SBOMを生成して保存する」だけでなく、「スキャン結果をパイプラインのゲートとして使う」設計まで踏み込むことです。ゲートがなければSBOMは後から眺める資料にとどまり、脆弱なイメージが本番にデプロイされるリスクを実際には下げられません。本記事では、SBOMの生成(syft)と脆弱性スキャンゲート(grype)の両方をCIパイプラインに組み込む具体的な手順を示します。

syftとgrypeの役割と位置づけ

Anchore社が開発するOSSの2ツールは、役割が明確に分離されています。

syftはSBOMジェネレーターです。コンテナイメージ・ディレクトリ・ファイルシステムを解析し、含まれるパッケージ・ライブラリの一覧をSPDX、CycloneDX、syft独自形式(JSON)で出力します。インプットはDockerイメージのtarball、レジストリ参照、ローカルディレクトリのいずれも受け付けます。

grypeは脆弱性スキャナーです。syftが出力したSBOMを読み込み(あるいは直接イメージをスキャンし)、NVD・OSV・各ディストリビューションのアドバイザリと照合してCVEを検出します。終了コードでgateを制御できるため、CIの`exit 1`と組み合わせてパイプラインを止めることが容易です。

2ツールを直列に使う最大の利点は、「SBOMとスキャン結果を別々のアーティファクトとして保持できる」点です。grypeだけで直接イメージをスキャンすることも可能ですが、SBOMを中間成果物として残すことで、後から別ツールで再スキャンしたり、コンプライアンス報告に流用したりできます。

syftでSBOMを生成する実践手順

まずsyftをインストールします。2026年時点の推奨はバイナリインストールスクリプトで、パッケージマネージャ経由より最新版への追従が速い傾向があります。

curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin

コンテナイメージのSBOMをCycloneDX JSON形式で生成する基本コマンドは次のとおりです。

syft myrepo/myapp:latest -o cyclonedx-json=sbom.cdx.json

ポイントはいくつかあります。

  • ビルド直後のローカルイメージをスキャンすることで、レジストリへのプッシュ前に問題を検出できます。`docker build`直後に`syft`を呼ぶのが最も早いゲートです。
  • CycloneDX JSON(`cyclonedx-json`)はgrypeとの親和性が高く、後処理ツールのサポートも広いため、特別な理由がなければこの形式を選ぶのが無難です。
  • マルチアーキテクチャビルドの場合、`–platform linux/amd64`のようにアーキテクチャを明示しないと意図と異なるレイヤーが解析されることがあります。

生成されたSBOMはCIのアーティファクトとして保存します。GitLab CIなら`artifacts: paths`、GitHub Actionsなら`actions/upload-artifact`で保持できます。スキャン結果とセットで90日程度保存しておくと、後のインシデント調査時に役立ちます。

grypeでスキャンゲートを設計する

grypeのインストールも同様にスクリプト経由で行います。

curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin

先ほど生成したSBOMを入力にスキャンし、重大度がCritical以上の場合にパイプラインを止めるゲートは次のように記述できます。

grype sbom:./sbom.cdx.json --fail-on critical -o json > grype-report.json

--fail-onに渡せる値は`negligible`、`low`、`medium`、`high`、`critical`です。運用初期は`critical`だけをゲートにして慣らし、安定してきたら`high`まで下げる段階的な引き締めが現実的です。一気に`medium`をゲートにすると既存イメージに大量の検出が出てパイプラインが総止まりになるケースがあります。

許容リストの管理

修正バージョンが存在しない脆弱性や、自環境で攻撃経路が成立しないCVEを一律にブロック対象にすると、開発速度が大きく損なわれます。grypeは`.grype.yaml`(またはパス指定の設定ファイル)で許容リスト(ignore list)を管理できます。

ignore:
  - vulnerability: CVE-2024-XXXX
    reason: "fix-not-yet-available"
    until: "2026-10-01"

untilフィールドを使って期限を設定しておくと、いつまでも無視し続けるリスクを制度的に抑えられます。許容リストのYAMLはGitで管理し、変更にはレビューを要求するルールにするのが望ましい運用です。

CI/CDパイプラインへの組み込みパターン

GitHub Actionsの場合

ビルドジョブの後続ステップとして組み込む構成が最もシンプルです。

jobs:
  build-and-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Build image
        run: docker build -t myapp:${{ github.sha }} .

      - name: Generate SBOM
        run: syft myapp:${{ github.sha }} -o cyclonedx-json=sbom.cdx.json

      - name: Scan SBOM
        run: grype sbom:./sbom.cdx.json --fail-on critical -o json > grype-report.json

      - name: Upload artifacts
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: security-reports
          path: |
            sbom.cdx.json
            grype-report.json
          retention-days: 90

`if: always()`を指定してアーティファクトアップロードを行うことで、スキャンがfailした場合でもレポートを取得できます。失敗時のレポートこそ調査に必要なため、この設定は必須です。

GitLab CIの場合

sbom-scan:
  stage: test
  image: alpine:3.20
  before_script:
    - apk add --no-cache curl
    - curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
    - curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin
  script:
    - syft $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA -o cyclonedx-json=sbom.cdx.json
    - grype sbom:./sbom.cdx.json --fail-on critical -o json > grype-report.json
  artifacts:
    when: always
    paths:
      - sbom.cdx.json
      - grype-report.json
    expire_in: 90 days

なお、毎回インストールスクリプトを実行するとCIの所要時間が伸びます。本番運用ではsyftとgrypeをインストール済みのカスタムイメージを用意してレジストリに置くか、キャッシュ機構を活用するとよいでしょう。

2026年の現行環境差分と今後の注意点

2026年時点で見落としやすいいくつかの環境変化があります。

OCI ArtifactsとSBOMのアタッチ

SBOMをファイルとして保管するだけでなく、OCI Artifacts仕様を使ってコンテナイメージにアタッチする手法が広まっています。`cosign attach sbom`や`oras push`でレジストリにSBOMを紐付けると、イメージとSBOMのライフサイクルが一致し、古いSBOMを誤参照するリスクが下がります。syftも`–output`でOCI push先を指定できるよう機能が拡充されているため、将来的な移行先として検討する価値があります。

Sigstore/cosignによる署名との組み合わせ

SBOMに対してcosignで署名を付与することで、「このSBOMは信頼されたビルドパイプラインが生成した」という来歴証明を追加できます。Supply Chain Levels for Software Artifacts(SLSA)レベル2〜3を目指す場合には、SBOM生成・署名・アタッチの3ステップがセットになります。2026年現在、GitHub ActionsのOIDCトークンとcosignを組み合わせたkeylessサイニングが普及しており、鍵管理の負担を大きく下げられます。

grypeのDB更新タイミング

grypeは脆弱性DBをローカルにキャッシュします。CIランナーを長期間使い回す構成では、DBが古くなって最新のCVEを検出できないケースがあります。`grype db update`をスキャン前に明示的に呼ぶか、DBの更新日時を確認するステップをパイプラインに加えておくと安全です。Hosted Runnerを使う場合は毎回クリーンな環境から始まるため問題になりにくいですが、self-hostedランナーでは特に注意が必要です。

許容リストの肥大化への対処

運用を続けると許容リストが増え続けるのは多くの現場で観察されるパターンです。四半期に一度、`until`フィールドが過去日になったエントリを棚卸しするプロセスを設けることを推奨します。自動化するなら、許容リストのYAMLを読み込んで期限切れエントリを検出するシェルスクリプトをCIの別ジョブとして走らせる方法が手軽です。

SBOMとスキャンゲートの組み合わせは、コンテナセキュリティの「見える化」と「自動化」を両立する現時点で最も実績のある手法です。ツール自体は成熟していますが、許容リストの管理・DB更新・アーティファクト保管の3点は継続的な運用設計が必要で、仕組みを作っただけで終わりにならない点には留意してください。

「コマンドは打てる。次は”現場で通用する型”を最短で身につけたい」——そんなあなたへ。

ネットの断片的なTipsをコピペするだけでは、体系的な運用スキルはなかなか積み上がりません。リナックスマスター.JPの無料メルマガ「リナマガ」では、現場で実際に使うLinuxサーバー運用の考え方を、順を追って実務目線でお届けしています。いま登録された方には、安全なサーバー構築の「型」をまとめた『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼント中です。

>> 図解60P『Linux入門マニュアル』を無料で受け取る
(メルマガ登録は10秒・いつでも解除OK)

※ 「独学の時間がもったいない」「プロから現場の技術を最短で学びたい」という本気の方には、2日で実務レベルが身につく初心者向けハンズオンセミナーもご用意しています。

PR・広告

Linuxサーバーセキュリティ徹底入門(Amazon)

ポート・ファイアウォール・権限などサーバ防御の基本をオープンソースで学べる実務書。

Amazonで見る

※ Amazonのアソシエイトとして、当サイトは適格販売により収入を得ています。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

目次