GitHub Actions実行保護入門——CIを誰が動かせるか制御する
GitHub ActionsのWorkflow execution protectionsを題材に、AIやbotがPRを作る時代のCI/CD実行権限を整理します。Next.js、Firestore、TypeScriptの検証例とともに安全な導入手順を解説します。

はじめに
GitHub Actionsを使っていて、こんな不安はありませんか?
| 状況 | 困りごと |
|---|---|
| AIエージェントやbotがPRを作る | 生成コードがCI上でどこまで実行されるのか見えにくい |
workflow_dispatchを便利に使っている | 誰でも重い検証やデプロイ準備を起動できてしまう |
pull_request_targetを使っている | フォークPRのコードを特権付きで実行する事故が怖い |
2026年6月18日、GitHubは Workflow execution protections をpublic previewとして発表しました。これは「どのActorが」「どのイベントで」GitHub Actionsを起動できるかを、workflow YAMLの外側から制御する仕組みです。
本記事では、架空の販売管理SaaS「OrderDock」を題材に、Next.js + Firestore + GitHub Actions + TypeScriptの現場でどう使うかを整理します。読み終えると、PR用CI、手動実行、bot生成PRの実行権限を分けて設計できるようになります。
何が変わったのか
Workflow execution protectionsは、GitHub Enterprise、Organization、Repositoryレベルで利用できる実行保護です。GitHub公式ドキュメントではpublic previewであり、今後変更される可能性があると明記されています。
ポイントは、workflowファイルの中身だけを信頼しないことです。従来は、トリガーとなったコミットに含まれるworkflow定義に従って実行されました。攻撃者がworkflowを書き換えられる立場にいると、CIを使って危険なコードを動かせる余地がありました。
新しい保護では、管理者がRulesetsベースのルールを定義し、GitHub Actionsが実行前に評価します。最初に使えるルールは次の2種類です。
| ルール | 制御できるもの | 例 |
|---|---|---|
| Actor rules | 誰がworkflowを起動できるか | ユーザー、Repository role、GitHub Apps、Copilot、Dependabot |
| Event rules | どのイベントでworkflowを起動できるか | push、pull_request、pull_request_target、workflow_dispatch |
また、同じ日にGitHubは actions/checkout v7も発表し、pull_request_targetでフォークPRのheadやmerge commitをチェックアウトする典型的な危険パターンをデフォルトで拒否するようにしました。CI/CDの防御線が、YAMLのレビューだけでなく、プラットフォーム側の実行判断へ広がっていると捉えるとわかりやすいです。
OrderDockでの導入方針
OrderDockは、受注・請求・承認ログをFirestoreに保存するNext.js App Router製の業務アプリという想定です。IssueはGitHub Issuesで管理し、AIエージェントが小さな修正PRを作る運用にしています。
この場合、すべてのworkflowを同じ信頼度で扱うのは危険です。次のように「読み取りだけの検証」と「権限が強い処理」を分けます。
| workflow | 主な用途 | 起動を許可するActor/Event |
|---|---|---|
| PR Quality Gate | yarn build、型チェック、Firestore接続を伴わない単体検証 | pull_requestを許可。外部PRやbot PRは必要に応じて承認 |
| Release Candidate | ステージング向けビルド、成果物作成 | Maintainer以上のworkflow_dispatch |
| Deploy | Firebase Hosting本番反映 | push to mainと管理者の手動実行に限定 |
GitHubの設定画面では、Actionsの新しい「Policies」セクションでrulesetを作成し、まずevaluate modeで影響を見ます。いきなりactiveにすると、既存の自動化が止まる可能性があります。1週間ほど評価して、実際にブロックされるActor/Eventを確認してから適用するのが現実的です。
ハンズオン1: PR用CIを最小権限にする
まず、PRで動くCIは「検証だけ」に寄せます。GITHUB_TOKENは明示的に読み取りへ絞り、Firestoreの本番資格情報やFirebase Hostingのデプロイ権限を渡しません。
name: PR Quality Gate
on:
pull_request:
branches: [main]
permissions:
contents: read
concurrency:
group: pr-quality-${{ github.event.pull_request.number }}
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
cache: "yarn"
- run: yarn install --frozen-lockfile
- run: yarn build
ここで重要なのは、PRのCIに「デプロイできる能力」を持たせないことです。GitHub Docsでは、permissionsキーでGITHUB_TOKENの権限をworkflow全体またはjob単位で制御でき、最小権限にすることが推奨されています。
Workflow execution protections側では、pull_requestは許可しつつ、起動できるActorを組織メンバー、Dependabot、承認済みbotなどに絞ります。AIが作ったPRについては、6月11日のGitHub Changelogで示されたように、github-actions[bot]作成PRもユーザー承認後にCIを走らせられるようになっています。つまり「bot PRはCI不能」ではなく、「承認してからCI」という運用にできます。
ハンズオン2: Firestoreの監査ログをテストしやすくする
次に、権限が強い処理ほどアプリ側の監査ログを残します。OrderDockでは、管理者が受注ステータスを変更したらFirestoreのauditLogsへ記録します。
// src/app/api/orders/[orderId]/approve/route.ts
import { initializeApp, getApps } from "firebase-admin/app";
import { FieldValue, getFirestore } from "firebase-admin/firestore";
import { NextResponse } from "next/server";
if (getApps().length === 0) {
initializeApp();
}
const db = getFirestore();
type Params = {
params: Promise<{ orderId: string }>;
};
export async function POST(request: Request, { params }: Params) {
const { orderId } = await params;
const { reviewerId } = (await request.json()) as { reviewerId: string };
if (!reviewerId) {
return NextResponse.json({ error: "reviewerId is required" }, { status: 400 });
}
await db.collection("auditLogs").add({
action: "order.approve",
orderId,
reviewerId,
createdAt: FieldValue.serverTimestamp(),
});
return NextResponse.json({ ok: true });
}
このコード自体をCIで本番Firestoreに接続して試す必要はありません。PRでは型チェックとビルド、必要ならFirestoreアクセス部分をモックした単体テストまでに留めます。本番データへ触れる検証は、Maintainerが起動できるworkflow_dispatchや、ステージング専用の環境に分けます。
ハンズオン3: 危険なイベントを棚卸しする
Workflow execution protectionsを入れる前に、既存workflowをイベント別に棚卸しします。
rg "pull_request_target|workflow_dispatch|repository_dispatch|secrets\\." .github/workflows
見つかったworkflowは、次の観点で分類します。
| 観点 | 確認内容 |
|---|---|
pull_request_target | フォークPRのコードをチェックアウトして実行していないか |
workflow_dispatch | 誰が手動実行できるべきか |
| Secrets | PRから到達できるjobに秘密情報を渡していないか |
| Checkout | github.event.pull_request.head.shaなど未レビューのコードを特権jobで取っていないか |
特にpull_request_targetは慎重に扱います。GitHubの6月18日の発表では、actions/checkout v7が一般的な危険チェックアウトを拒否すると説明されていますが、runブロックでgitやghを使って未信頼コードを取得するような別経路は残ります。プラットフォーム側の保護に任せきらず、workflowレビューも続けるべきです。
導入チェックリスト
OrderDockのようなNext.js + Firestore構成なら、まず次の順で進めるのが現実的です。
.github/workflowsを棚卸しし、pull_request_targetとworkflow_dispatchを洗い出す- PR用CIの
permissionsをcontents: read中心に整理する - デプロイ、Firestore本番接続、秘密情報を使うjobをPR用CIから分離する
- Workflow execution protectionsをevaluate modeで作成する
- Actor rulesでMaintainer、GitHub Apps、Dependabot、Copilotなどの扱いを決める
- Event rulesで
pull_request_targetとworkflow_dispatchの実行範囲を絞る - 1週間ほどログを見て、問題なければactiveに切り替える
AIエージェントがPRを作る開発では、CIを止めることが目的ではありません。信頼できる入口からだけCIを動かし、レビュー前のコードに強い権限を渡さないことが目的です。
参考リンク
- Control who and what triggers GitHub Actions workflows
- Workflow execution protections - GitHub Docs
- Safer pull_request_target defaults for GitHub Actions checkout
- Use GITHUB_TOKEN for authentication in workflows
まとめ
GitHub ActionsのWorkflow execution protectionsは、CI/CDを「workflowファイルに書かれた通りに動かす」段階から、「組織のポリシーで実行前に判断する」段階へ進める機能です。
Next.jsやFirestoreを使う業務アプリでは、PR用CI、ステージング検証、本番デプロイを分け、Actor/Event単位で実行権限を設計する価値があります。特にAIやbotがPRを量産する開発では、速さと安全性を両立するための基盤になります。