はじめに
SyftでSBOMを作成し、Grypeで脆弱性を診断するパイプラインをGitHub Actionsで構築する方法をまとめます。Syftの主要な機能は「コンテナイメージの解析」ですが、その本質は 「ファイルシステム上のアーティファクトのカタログ化」 ですので、コンテナに限らず、IaaSのような仮想サーバ上のディレクトリやファイルシステム全体を対象にしても、アプリケーションとOSの両方のレイヤーでSBOMを作成することが可能です。ちなみに今回はGitHubで管理されているアプリケーション単位のお話です。
※ SyftがサポートしているOSとパッケージマネージャー
使用ツール
- GitHub Actions : GitHubが提供してくれている、ワークフロー自動化サービス。
- SyftのAction : SBOMを生成する。
- GrypeのAction : 生成されたSBOMを脆弱性データベースと照合し、スキャンする。
GitHub Actionsの構成
フローの根幹的なものは以下の通り
- Syft で ディレクトリに対してスキャンをかけSBOMをjsonで出力 & 監査などでも使えるので一応それをアップロードしておく。
- 一応、人間の目でも分かるようにテーブル形式でechoをかける。
- Grype でそのSBOMを読み込み、脆弱性をチェックする。
- GitHub Actions で定期実行し、危険な脆弱性が見つかったら Discord に通知する。
.github/workflows/security-scan.yml として以下を定義。
name: Security Scan (Syft-Grype)
on:
push:
branches: ["main"] # この辺の設定はお好きに
pull_request:
branches: ["main"]
schedule:
- cron: '0 0 * * *'
workflow_dispatch:
jobs:
generate:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6 # verはとりあえず最新を指定しています
- name: Generate SBOM with Syft
uses: anchore/sbom-action@v0
with:
path: .
format: cyclonedx-json
output-file: sbom.json
upload-artifact: true
- name: Show detected packages
run: |
syft dir:. -o table
- name: Scan SBOM with Grype
uses: anchore/scan-action@v7 # verはとりあえず最新を指定しています
with:
sbom: "sbom.json"
fail-build: true
severity-cutoff: "high"
output-format: "table"
- name: Notify Discord on Failure
if: failure()
run: |
curl -H "Content-Type: application/json" \
-d '{"username": "Failure", "content": "⚠️ **GitHub Actionsが失敗しました。**\n内容を確認してください: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"}' \
${{ secrets.DISCORD_WEBHOOK_FOR_GITHUB }}
動くとこんな感じ
まとめ
これでアプリケーションが使用しているパッケージの脆弱性診断がSyft + Grype + GitHub Actionsでできるようになります。
GitHubにはDependabotとかもあるので、若干機能としては重複するのですが、一応アプリケーションのSBOMの履歴も追えますし(検索性はあまりないかもですが)、SyftのSBOMは監査とかに提出できるレベルのものらしいので、こういうこともできると覚えておけば役に立つ時が来るかもしれませんね。
(Dependabotは『個別の修正PR』をくれますが、Syft+Grypeのパイプラインは『その瞬間のシステム全体の安全性のスナップショット(証明書)』をくれるという感じでしょうか。)
どなたかのお役に立てれば幸いです。

