zizmorをGitHub Code Scanningに連携し、GitHub Actionsのセキュリティリスクを含むPRをマージブロックする

zizmorをGitHub Code Scanningに連携し、GitHub Actionsのセキュリティリスクを含むPRをマージブロックする

2026.05.18

はじめに

前回の記事で、zizmorをローカル実行して GitHub Actions のワークフロー群を一通り audit し、検出された finding を一つずつ潰す流れを書きました。

https://dev.classmethod.jp/articles/shuntaka-zizmor-github-actions-audit/

今回の記事がどちらかというと本命で、zizmorGitHub Actionsとの連携を前提として設計されています。zizmorの公式ドキュメントの設定方法が記載されています。

https://docs.zizmor.sh/integrations/

zizmor は finding を SARIF(Static Analysis Results Interchange Format / 静的解析結果の交換用 JSON 仕様、OASIS が標準化)で出力できます。GitHub Code Scanning は SARIF をそのまま受け付けるため、zizmor → Code Scanning の連携は「SARIF ファイルを GitHub にアップロードするだけ」で成立します。

Code Scanning に乗せることで以下のような運用に寄せられます。

  • PR 単位で新規 / 解決済み finding が差分表示され、該当行にインラインで指摘が入る
  • severity 閾値と branch ruleset を組み合わせれば、指定のseverity閾値のfindingを含むPRを自動でマージブロックでき、仕組みでサプライチェーンリスクを低減できる
  • Security タブで全 finding が rule / severity ごとに俯瞰でき、dismissal(対応不要として閉じる)の状態も含めて履歴管理できる

zizmor から Code Scanning に finding を流す方法は、公式ドキュメント上で大きく 2 通り紹介されています。

構成 内容
公式 Action 構成 zizmorcore/zizmor-action を 1 step 入れて、SARIF 生成 / アップロードまで任せる
手動構成 zizmor --format=sarif で SARIF ファイルを生成し、github/codeql-action/upload-sarif でアップロードする

今回は手動構成を試します。

料金について

GitHub Code Scanning の料金は以下の通りです。

  • パブリックリポジトリ: 無料(Code Scanning / SARIF アップロードとも)
  • プライベートリポジトリ: GitHub Advanced Security ライセンスが必要(GitHub Enterprise の有償アドオン)

本記事で扱うリポジトリはパブリックのため、有効化しても課金は発生しません。zizmor 自体も OSS で無料、GitHub Actions の実行時間は標準の無料枠(パブリックリポジトリは無制限)に収まります。

SARIFアップロードのワークフロー設定

zizmor 公式ドキュメントの manual integration を参考に、ワークフローを書きます。

https://docs.zizmor.sh/integrations/#manual-integration

実際に動かしているワークフローはこちらです。

https://github.com/shuntaka9576/shuntaka-dev/blob/05cf7819b6e750eb450d4ef59f23d51fac0d8ddd/.github/workflows/zizmor.yaml#L1-L40

トリガは pushpull_request を両方並べる構成です。

https://github.com/shuntaka9576/shuntaka-dev/blob/05cf7819b6e750eb450d4ef59f23d51fac0d8ddd/.github/workflows/zizmor.yaml#L3-L7

トリガ 対象ブランチ 役割
push preview / main デフォルトブランチ側の SARIF を「現状のベースライン finding」として記録する
pull_request ** PR を開く / 更新するたびに SARIF を上げ、ベースラインと差分比較 → Code scanning results / zizmor チェックが PR に付く

PR を Code Scanning でブロックしたい場合は両方必要です。

公式ドキュメントからの変更点は以下です。

  • リポジトリ特有の事情
    • on.push.branchespreview を追加(本リポジトリ固有の事情。一般的にはデフォルトブランチのみで OK)
  • zizmor対応
    • トップレベル permissions: {} でゼロ化し、ジョブ側で security-events: write / contents: read のみ付与
    • actions/checkoutpersist-credentials: false を指定(ArtiPACKED 対策)
    • 各 Action を SHA ピン留めし、コメントでバージョンを併記(タグ差し替え対策)
    • concurrency で同一 PR / ブランチの古い実行を自動キャンセル

SARIFアップロードワークフローとCode Scanningの連携確認

上記のワークフローをプッシュしてデフォルトブランチで実行されると、Security and quality > Code scanning の画面が「Code scanning is not enabled」から、ツール登録済みの状態に切り替わります。実際の実行ログはこちらです。

https://github.com/shuntaka9576/shuntaka-dev/actions/runs/26005835052/job/76437068438

Upload SARIF file ステップを抜粋すると、SARIF のバリデーション → アップロード → Code Scanning 側での処理完了まで一連の流れが確認できます。

Upload SARIF file ステップ抜粋
Run github/codeql-action/upload-sarif@c10b8064de6f491fea524254123dbe5e09572f13
  with:
    sarif_file: results.sarif
    category: zizmor

Post-processing sarif files: ["results.sarif"]
Validating results.sarif
Adding fingerprints to SARIF file.
Uploading results
Successfully uploaded results

Waiting for processing to finish
Analysis upload status is pending.
Analysis upload status is complete.

Analysis upload status is complete. が出た時点で、Code Scanning 側で SARIF の取り込みが完了しています。

Code scanning ページから連携を確認できます(現状0件のため表示されていません)
Code scanning ページ: All tools are working as expected と Tools 1 が表示され、SARIF アップロードで Code Scanning が有効化されたことが分かる
github.com/<owner>/<repo>/security/code-scanning

Tools から zizmor を開くと、ツールとして登録され、Actions workflow から SARIF が直近にアップロードされた履歴が確認できます。

zizmor tool 詳細画面: Setup types に zizmor audit (Actions workflow) が登録され、Last scan の時刻が記録されている
github.com/<owner>/<repo>/security/code-scanning/tools/zizmor/status

マージブロックの設定

zizmor が High 以上の finding を出した PR をマージブロックするには、以下 2 つの設定を組み合わせます。

設定箇所 役割
Settings > Advanced Security > Code scanning > Protection rules severity に応じて Code scanning results / zizmor チェックを fail させる閾値を決める
Settings > Rules > Rulesets Code scanning results / zizmor を required check に登録し、fail 時にマージブロックする

severity 閾値の確認

Settings タブ → 左サイドバーの Advanced Security を開き、Code scanning セクションまでスクロールします。

Settings タブから左サイドバーの Advanced Security を選択し、Code scanning セクションまでスクロールする
github.com/<owner>/<repo>/settings/security_analysis

Code scanning セクションは以下のような構成になっており、デフォルト値のまま運用できます。

Code scanning セクション: Tools, Copilot Autofix, Protection rules がデフォルト値で表示されている

デフォルト値の挙動は「Security alert severity level: High or higherCode scanning results / zizmor チェックを fail させる」です。要件が「High 以上の finding が出た PR を弾く」であれば、この画面は確認するだけで OK です。閾値を Medium まで下げたい等の調整が必要なら Security alert severity level のドロップダウンから変更します。

各項目のデフォルト挙動の詳細
項目 デフォルト 振る舞い
Tools > CodeQL analysis 未設定(Set up CodeQL を使う場合に有効化する。zizmor 単独構成なら触らない
Tools > Other tools - upload-sarif で SARIF を投げるサードパーティツール(zizmor など)がここに自動登録される。今回のワークフローを push 済みなら zizmor がここに並ぶ
Copilot Autofix On CodeQL アラートに対して AI が修正案を提示する機能。CodeQL を使わない構成では影響なし
Protection rules > Security alert severity level High or higher High / Critical のセキュリティアラートで Code scanning results / zizmor チェックを fail させる
Protection rules > Standard alert severity level Only errors Error 相当のコーディングエラーで同チェックを fail させる

Branch ruleset で必須チェックに登録

Settings タブ → 左サイドバー Rules > Rulesets を開き、右上の New ruleset > New branch ruleset から作成画面に入ります。

Settings > Rules > Rulesets を開いて New ruleset > New branch ruleset を選択する
github.com/<owner>/<repo>/settings/rules

作成画面では以下を設定します。

  1. Ruleset Name に任意の名前を入力(例: protect-preview
  2. Enforcement statusActive に設定
  3. Target branchesAdd target から Include default branch を選択(本リポジトリでは preview がデフォルトブランチ)
  4. Branch rulesRequire code scanning results を有効化(CodeQL がデフォルトで Required tools に追加される)
  5. Add tool ドロップダウンから zizmor を選択して追加

Add tool ドロップダウンで CodeQL と zizmor の両方にチェックを入れる

  1. Required tools and alert thresholds に CodeQL と zizmor が並び、それぞれ Security alerts: High or higher / Alerts: Errors で表示されることを確認(Settings > Advanced Security の閾値と揃った状態)

Required tools and alert thresholds に CodeQL と zizmor が High or higher / Errors で並んでいる

  1. Create で保存

最終的に以下のような ruleset が作成されます。

protect-preview ruleset の最終構成: Default ブランチを対象に、Require code scanning results で CodeQL と zizmor をともに High or higher / Errors で必須化

これで Code scanning results / zizmor が PR の必須チェックになり、High 以上の finding が含まれる PR は zizmor の検出時点でチェックが fail → マージ出来なくなります。

動作確認

実際にわざと High を踏むワークフロー(run:${{ github.event.pull_request.title }} を直挿入する template injection)を含む PR を preview 宛に出してみます。実際の PR はこちらです。

https://github.com/shuntaka9576/shuntaka-dev/pull/383

PR ページの check 一覧で Code scanning results / zizmorFailing after 3s — 1 new alert including 1 error で fail し、Merging is blocked の警告が出てマージボタンが非活性になっていることがわかります。

PR の checks 一覧で Code scanning results / zizmor が fail し、Merging is blocked が表示される

Conversation タブには github-advanced-security[bot] が該当行へのインラインレビューとして finding を貼り付けてくれます。zizmor の指摘内容(code injection via template expansion: may expand into attacker-controllable code)と該当コード(run: echo "title is ${{ github.event.pull_request.title }}")が並んで表示され、Dismiss alert で対応不要として閉じる導線も用意されます。

github-advanced-security[bot] が PR の該当行へインラインで zizmor の finding をコメント

これによりPR上で不備のあるGitHub Actionsの設定が必ず可視化され、High以上ならマージブロックまで仕組みでカバーすることが可能です。

さいごに

GitHub Code Scanningに統合してSecurityタブ可視化からPRマージブロックまで自動化しました。仕組みで解決することによりメンテやレビュー負荷が下がるので積極的に活用していきたいと感じました。

この記事をシェアする

関連記事