zizmorをGitHub Code Scanningに連携し、GitHub Actionsのセキュリティリスクを含むPRをマージブロックする
はじめに
前回の記事で、zizmorをローカル実行して GitHub Actions のワークフロー群を一通り audit し、検出された finding を一つずつ潰す流れを書きました。
今回の記事がどちらかというと本命で、zizmorGitHub Actionsとの連携を前提として設計されています。zizmorの公式ドキュメントの設定方法が記載されています。
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 を参考に、ワークフローを書きます。
実際に動かしているワークフローはこちらです。
トリガは push と pull_request を両方並べる構成です。
| トリガ | 対象ブランチ | 役割 |
|---|---|---|
push |
preview / main |
デフォルトブランチ側の SARIF を「現状のベースライン finding」として記録する |
pull_request |
** |
PR を開く / 更新するたびに SARIF を上げ、ベースラインと差分比較 → Code scanning results / zizmor チェックが PR に付く |
PR を Code Scanning でブロックしたい場合は両方必要です。
公式ドキュメントからの変更点は以下です。
- リポジトリ特有の事情
on.push.branchesにpreviewを追加(本リポジトリ固有の事情。一般的にはデフォルトブランチのみで OK)
- zizmor対応
- トップレベル
permissions: {}でゼロ化し、ジョブ側でsecurity-events: write/contents: readのみ付与 actions/checkoutにpersist-credentials: falseを指定(ArtiPACKED 対策)- 各 Action を SHA ピン留めし、コメントでバージョンを併記(タグ差し替え対策)
concurrencyで同一 PR / ブランチの古い実行を自動キャンセル
- トップレベル
SARIFアップロードワークフローとCode Scanningの連携確認
上記のワークフローをプッシュしてデフォルトブランチで実行されると、Security and quality > Code scanning の画面が「Code scanning is not enabled」から、ツール登録済みの状態に切り替わります。実際の実行ログはこちらです。
Upload SARIF file ステップを抜粋すると、SARIF のバリデーション → アップロード → Code Scanning 側での処理完了まで一連の流れが確認できます。
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件のため表示されていません)

github.com/<owner>/<repo>/security/code-scanning
Tools から zizmor を開くと、ツールとして登録され、Actions workflow から SARIF が直近にアップロードされた履歴が確認できます。

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 セクションまでスクロールします。

github.com/<owner>/<repo>/settings/security_analysis
Code scanning セクションは以下のような構成になっており、デフォルト値のまま運用できます。

デフォルト値の挙動は「Security alert severity level: High or higher で Code 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 から作成画面に入ります。

github.com/<owner>/<repo>/settings/rules
作成画面では以下を設定します。
Ruleset Nameに任意の名前を入力(例:protect-preview)Enforcement statusをActiveに設定Target branchesのAdd targetからInclude default branchを選択(本リポジトリではpreviewがデフォルトブランチ)Branch rulesのRequire code scanning resultsを有効化(CodeQL がデフォルトでRequired toolsに追加される)Add toolドロップダウンからzizmorを選択して追加

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

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

これで Code scanning results / zizmor が PR の必須チェックになり、High 以上の finding が含まれる PR は zizmor の検出時点でチェックが fail → マージ出来なくなります。
動作確認
実際にわざと High を踏むワークフロー(run: に ${{ github.event.pull_request.title }} を直挿入する template injection)を含む PR を preview 宛に出してみます。実際の PR はこちらです。
PR ページの check 一覧で Code scanning results / zizmor が Failing after 3s — 1 new alert including 1 error で 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 をコメント](https://devio2024-media.developers.io/image/upload/f_auto/q_auto/v1779065543/2026/05/18/q1mhcpuxkvlnpclojqbu.png)
これによりPR上で不備のあるGitHub Actionsの設定が必ず可視化され、High以上ならマージブロックまで仕組みでカバーすることが可能です。
さいごに
GitHub Code Scanningに統合してSecurityタブ可視化からPRマージブロックまで自動化しました。仕組みで解決することによりメンテやレビュー負荷が下がるので積極的に活用していきたいと感じました。






