Claude Codeでfork PRをレビューする安全な構成 — シークレットを渡さない
外部コントリビューターのfork PRにClaude Codeでレビューをつけたい。シークレットが渡らない仕様の理由、Code Reviewのコメントコマンド、Actionで読み取り専用にする構成を示します。
公開リポジトリで外部のfork PRにClaude Codeのレビューをつけるには、2つの経路があります。マネージドのCode Reviewで@claude reviewをコメントする経路と、pull_request_targetでActionを動かす経路です。後者はallowed_non_write_usersと読み取り専用のツール設定が必要になります。
どちらを選ぶかは、「シークレットを渡さない」と「Actionを動かす」が両立しない点を押さえると決まります。
どの経路でfork PRをレビューするか
- Q外部PRすべてに、自動でレビューコメントをつけたいか?答えがいいえのとき答えがはい
マネージドのCode Reviewを使い、メンテナーが必要なPRに
@claude reviewとコメントします。workflowを書く必要はありません。 - QActionに読み取り専用のツールだけを許可する設定を書けるか?答えがいいえのとき答えがはい
pull_request_targetで動かす構成は避け、コメントコマンドの運用にとどめます。
両方はいの場合
pull_request_targetとallowed_non_write_usersを組み合わせます。読み取り専用に絞る設定は、「経路2」の節に書いています。
fork PRのworkflowにシークレットが渡らない理由
GitHub Actionsは、fork元のリポジトリから出たPRで起動したworkflowに、GITHUB_TOKEN以外のシークレットを渡しません。GITHUB_TOKENも、fork PRでは読み取り専用の権限です。PRのコードは外部の人が書いたものなので、リポジトリのシークレットを抜き取る処理が混ざっていても防げるようにするための仕様です。
初めて貢献する人のPRでは、書き込み権限を持つメンテナーが承認するまでworkflowが動かないことがあります。承認待ちのまま30日たった実行は期限切れになり、失敗として扱われます。承認画面を開いたら、.github/workflows/配下のファイルが変わっていないかを先に見るのが定石です。
Dependabotが開くPRも、同じ制限を受けます。fork PRと同じ扱いになるためです。
標準のレビューworkflowがfork PRで動かない理由
Claude Code GitHub Actionのレビュー用サンプルは、pull_requestトリガーでanthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}を参照します。fork PRではこのシークレットが空になるので、APIキーを持たないままActionが走ります。サンプルの説明も、シークレットが渡らないため、レビューが走るのは同じリポジトリ内のブランチから出たPRだけだと述べています。
もう1つ別の関門があります。Actionは起動前に、PRやコメントを書いた人が書き込み権限を持つかを確かめます。外部コントリビューターは通常この条件を満たさないので、シークレットの問題が片付いても実行は拒否されます。
| 関門 | 何が起きるか | 通す手段 |
|---|---|---|
| シークレットが渡らない | 何が起きるかpull_requestのfork PRではANTHROPIC_API_KEYが空 | 通す手段pull_request_targetなどベースリポジトリ側の文脈で動かす |
| 書き込み権限の確認 | 何が起きるか権限のない投稿者の実行は拒否される | 通す手段allowed_non_write_usersとgithub_tokenの指定 |
| 人間のアクターか | 何が起きるかbotの投稿者はallowed_botsに載せないと拒否される | 通す手段信頼するbot名だけを列挙する |
経路1: Code Reviewのコメントコマンドで始める
マネージドのCode Reviewは、fork PRを自動ではレビューしません。リポジトリの「Review runs」設定がどうなっていても同じです。起動するには、PRに@claude reviewとコメントします。
必要なのは、フォーク側ではなくベースリポジトリへの書き込み権限です。コメントはトップレベルのPRコメントとして投稿し、コマンドはコメントの先頭の行に1行で書きます。botのコメントでは起動しません。
fork PRには次の制約があります。
@claude review alwaysは使えますが、以降のpushをサブスクライブする効果はありません- チェックランの「Re-run」ボタンでは再実行できません
- 再レビューが欲しいときは、そのつど
@claude reviewをコメントし直します
メンテナーの判断で1本ずつ起動するので、悪意のあるPRに自動でトークンを使わせる心配が小さい経路です。反面、PRごとに人の手が要ります。
Actionと併用するときの衝突
リポジトリでClaude Code GitHub Actionを対話モードのまま、既定のトリガー語@claudeで動かしていると、@claude reviewのコメントでActionも同時に起動します。2つを切り分けるには、Action側のtrigger_phraseを別の語に変えます。
経路2: pull_request_targetで読み取り専用のレビューを自動化する
全件に自動でコメントさせたい場合は、pull_request_targetを使います。このトリガーは、PRのマージコミットではなくベースリポジトリの既定ブランチの文脈で動くため、ベース側のシークレットが使えます。そのぶん、PRのコードを不用意に実行すれば、シークレットが漏れる危険と隣り合わせです。
ここでは、次の4点で被害の幅を絞ります。例示はこれらの方針を1つのworkflowにまとめたものです。
- ベースブランチをワークスペースの根にチェックアウトし、PRのheadは別ディレクトリに置く
allowed_non_write_usersと、ジョブの権限に縛られたGITHUB_TOKENを使うclaude_argsで、読み取りとコメント投稿のツールだけを許可する- ジョブの権限を、読み取り中心に絞る
name: External PR Review
on:
pull_request_target:
types: [opened, synchronize, ready_for_review]
jobs:
review:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
# ベースブランチを根にチェックアウト(ref を書かない)
- uses: actions/checkout@v6
# PR の変更は別ディレクトリへ
- uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha }}
path: pr-head
- uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
github_token: ${{ secrets.GITHUB_TOKEN }}
allowed_non_write_users: "*"
prompt: |
pr-head ディレクトリの変更をレビューしてください。
コードは実行せず、読んで気づいた点だけを PR にコメントしてください。
claude_args: >-
--max-turns 10
--add-dir pr-head
--allowedTools "Read,Grep,Glob,mcp__github_inline_comment__create_inline_comment"allowed_non_write_usersは、ユーザー名のカンマ区切りか*を取ります。上の例は全員を許す*ですが、外部のコントリビューターを個別に絞れる運用なら、名前を列挙するほうが範囲を狭くできます。
設定ごとの意味
allowed_non_write_usersは、書き込み権限の確認を迂回する入力です。ドキュメントはこれを「リスキー」と位置づけ、権限が極端に絞られたworkflowでだけ使うよう求めています。使うときはgithub_tokenの指定が必須で、GitHub App認証の構成では効きません。指定すると、Claudeは起動したサブプロセスの環境から、Anthropic・クラウド・GitHub Actionsのシークレットを、できる範囲で取り除きます。Linuxでbubblewrapが使えるランナーでは、サブプロセスがPID名前空間で隔離されます。なお、これで注入のリスクが「ゼロ」になるとは言われていません。
github_tokenには、secrets.GITHUB_TOKENを渡します。これはジョブで宣言した権限の範囲に絞られ、ジョブが終わると失効するトークンです。個人用アクセストークンは使いません。実行のたびに入れ替わらない静的なトークンは、プロンプトインジェクションで少しずつ引き出されるおそれがあるためです。
--allowedToolsは、使えるツールを最小にします。プレーンテキストのプロンプトで動かすとき、Claudeは許可したツールしか使えず、シェルもGitHub APIも既定では持ちません。ここにBashを足さないことが、外部PRのコードを実行させない最大の防壁になります。
チェックアウトの置き場所
pull_request_targetで最も事故が多いのは、PRのheadをワークスペースの根にチェックアウトしてしまうことです。Actionも、Claudeも、その場所を作業ディレクトリにして動くためです。ドキュメントは、信頼できないrefを根にチェックアウトしてからActionを呼ぶことをはっきり禁じています。
上の例はベースを根に置き、PRのheadをpr-headに置いて--add-dirで渡す形です。PR上のファイルのうち、.claude/、.mcp.json、CLAUDE.md、.husky/などの設定系パスは、Actionが起動前にベースブランチ側の内容へ戻します。PRが作者の都合のよいhooksや指示書をすり替えることはできません。
落とし穴
設定は戻されても、package.jsonやMakefileはPR側のまま
ベース側の.claude/settings.jsonにhookを置き、その中でnpm run ...やmakeを呼ぶと、実行されるのはPRが書き換えたpackage.jsonやMakefileの中身です。外部PRをレビューするworkflowのhookは、ツールをバージョン固定で直接呼び、設定をコマンドラインで渡す自己完結の形にします。
外部の入力を読ませるときの落とし穴
fork PRのタイトルや本文、コメントには、HTMLコメントや不可視文字の形で指示が仕込まれることがあります。Actionは、HTMLコメント・不可視文字・画像のalt・隠し属性・HTMLエンティティを取り除いてから渡します。それでも新しい迂回手口は出てくるため、外部から来る生の内容は自分の目でも確かめるよう勧められています。
公開リポジトリでは、include_comments_by_actorで、Claudeに渡すコメントの投稿者を許可リスト化できます。外部の人のコメントを最初から読ませない設定です。ノイズになるbotのコメントを外すには、exclude_comments_by_actorを使います。両方に一致した投稿者は除外が優先されます。
allowed_botsの'*'も、公開リポジトリでは避けます。許可されたbotは書き込み権限を確かめられないため、誰かが作ったGitHub Appが、自分で決めたプロンプトでActionを呼び出せる状態になるからです。信頼するbot名を明示して列挙します。
Claude Codeにworkflowを点検させる
ここまでの設定は、書いた後に見落としが残りやすい箇所です。Claude Codeにworkflowのdiffを読ませ、次の観点で洗い出させます。
.github/workflows/external-pr-review.yml を読み、次を表で報告してください。
1. pull_request_target / workflow_run のとき、PR の head を
ワークスペースの根にチェックアウトしていないか
2. allowed_non_write_users に * や個人用トークンを使っていないか
3. claude_args の --allowedTools に Bash や書き込み系のツールが
含まれていないか
4. permissions に必要以上の write が付いていないか
修正はせず、該当行と理由だけを返してください。修正案を求めずに「該当行と理由だけ」で止めるのは、workflowの書き換えを人が判断するためです。workflow全般の脆弱性は、静的解析ツールで機械的に拾えます。手順はClaude CodeでGitHub Actionsの脆弱性を点検するにあります。
経路の選び分けとまとめ
| 状況 | 向く経路 | 外部PRの文脈に出るもの |
|---|---|---|
| メンテナーが目視で、レビューしたいPRを選ぶ | 向く経路@claude reviewのコメント | 外部PRの文脈に出るものベースリポジトリの権限を持つ人の操作だけ |
| 全件に自動でコメントをつけたい | 向く経路pull_request_target + 読み取り専用 | 外部PRの文脈に出るものAPIキーはベース側のActionが保持し、サブプロセスからは除去される |
| 外部PRを一切レビューさせない | 向く経路標準のpull_request | 外部PRの文脈に出るものなし(fork PRではActionが動かない) |
「シークレットを渡さない」ことと「fork PRをClaudeがレビューする」ことは、どちらも成立させる方法がありません。レビューにはAPIキーが要るため、渡さない構成ではActionが動きません。選べるのは、キーをベース側に閉じるpull_request_targetか、人の判断で起動するコメントコマンドかです。
Actionの入力の全体像はGitHub Actionsのパラメータとclaude_argsの渡し方に、組織単位の導入はClaude CodeのGitHub Actionsを組織に導入にあります。レビューの観点づくりはClaude Codeのcode-reviewスキルで、PRを安全性・性能・正確性から見るが参考になります。
参照した一次ソース
この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。