0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

uv + GitHub Actions + GrypeでPythonパッケージの脆弱性チェック

Posted at

はじめに

少し前から個人開発でですが、Pythonのパッケージ管理ツールは uv を使っています。
uvは開発スピードが早く、頻繁に新機能が追加されます。リリースのたびにリリースノートをチェックしているのですが、v0.9.11(2025年11月21日リリース)のアップデートにて、SBOM(Software Bill of Materials)の出力(CycloneDX形式) をサポートするようになりました。

これを使えば、「uvで管理している依存関係をGitHub Actions上で出力し、脆弱性スキャンツールの Grype に読み込ませる」 というパイプラインが簡単に作れそうだったので、実際に構築してみました。

やったこと

  1. uvuv.lock から正確な依存関係情報(SBOM)を出力する。
  2. Grype でそのSBOMを読み込み、脆弱性をチェックする。
  3. GitHub Actions で定期実行し、危険な脆弱性が見つかったら Discord に通知する。

成果物(YAML)

完成したワークフローファイル(.github/workflows/security-scan.yml)がこちらです。

name: Vulnerability Scan

on:
  push:
    branches: ["main"] # 対象のブランチを指定
  pull_request:
    branches: ["main"] # 対象のブランチを指定
  schedule:
    - cron: '0 0 * * *' # 毎日定刻にスキャンを実行
  workflow_dispatch: # 手動実行も可能にしておく

jobs:
  sbom-scan:
    runs-on: ubuntu-latest
    permissions:
      contents: read

    steps:
      - name: Checkout repository
        uses: actions/checkout@v6 # verはとりあえず最新を指定しています

      # uv のインストール
      - name: Install uv
        uses: astral-sh/setup-uv@v7 # verはとりあえず最新を指定しています
        with:
          version: "latest"

      # SBOM (CycloneDX) の生成
      # --no-dev: 本番に不要な開発用ライブラリは除外
      # --locked: uv.lock と pyproject.toml の同期を保証(ズレてたらエラーにする)
      - name: Generate SBOM with uv
        run: uv export --format cyclonedx1.5 --output-file sbom.json --no-dev --locked

      # Grype によるスキャン
      - name: Scan SBOM with Grype
        uses: anchore/scan-action@v7 # verはとりあえず最新を指定しています
        with:
          sbom: "sbom.json"
          fail-build: true        # 脆弱性があったら失敗させる
          severity-cutoff: "high" # High以上のみ検知
          output-format: "table"  # ログに見やすい表を出力

      # 失敗時のみ Discord に通知
      - name: Notify Discord on Failure
        if: failure()
        run: |
          curl -H "Content-Type: application/json" \
               -d '{"username": "GitHub Bot", "content": "⚠️ **GitHub Actionsが失敗しました。**\n内容を確認してください: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"}' \
               ${{ secrets.DISCORD_WEBHOOK_FOR_GITHUB }}

ポイント解説

1. uv export でSBOMを直接吐き出す

v0.9.11 以降では uv export コマンドで CycloneDX 形式(SBOM)を出力できるようになりました。

uv export --format cyclonedx1.5 --output-file sbom.json --no-dev --locked
  • --format cyclonedx: 標準的なSBOMフォーマットを指定。
  • --no-dev: テストツールなどの開発依存を除外し、本番環境のリスクのみにフォーカス。
  • --locked: これが重要です。uv.lockpyproject.toml と同期されていない場合にエラーにしてくれます。「古いロックファイルでスキャンしてしまった」という事故を防げます。

2. スキャン対象は pyproject.toml ではなく uv.lock

uv.lock には「Flask 3.0.1」のような実際にインストールされる正確なバージョンが記録されています。
これにより、Grype は誤検知の少ない正確なスキャンが可能になります。

3. ログを見やすくする

anchore/scan-action はデフォルトだとログ出力が機械的で見づらいため、output-format: "table" を指定しました。これにより、GitHub Actionsのログで以下のように確認できます。

NAME                INSTALLED      FIXED-IN       TYPE       VULNERABILITY        SEVERITY
requests            2.31.0         2.32.0         python     CVE-2024-35195       High
urllib3             1.26.18        1.26.19        python     CVE-2024-37891       High

実際のエラーログの様子

image.png

まとめ

uv の進化により、パッケージマネージャー単体でプロジェクトのSBOM作成が完結するようになり、比較的簡単にPythonパッケージの脆弱性スキャン環境を作れるようになりました。Syft のようにOS単位でSBOMを作成することは出来ませんが、アプリケーションのプラットフォームも多岐にわたってきているので、これだけで十分というプロジェクトもあるかもしれませんね。どなたかのお役に立てれば幸いです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?