はじめに
前回はScaffolderを、人間向けのフォーム入力ツールからAIエージェントが呼び出せるアクションへと再解釈する際の設計論点を扱い、本番リソースに関わるテンプレートは人間の承認を必須にすべきだと整理しました。
今回はその承認フローの先にある、実際の権限設計を掘り下げます。ScaffolderがGitHubに対して行う操作(リポジトリの作成、Actionsのトリガーなど)は、しばしば強い権限を必要とします。この権限を、AIエージェント経由の呼び出しに対してどう安全に絞り込むかが本記事のテーマです。加えて、AIエージェントがリポジトリ操作を行うこと自体に伴う、比較的新しいリスクにも触れます。
前提:Scaffolderは構造的に強い権限を持つ
まず押さえておきたいのは、Scaffolderがもともと強い権限を前提にした設計になっているという事実です。Scaffolderのジョブは既定でホストマシン上で直接実行され、テンプレートで定義されたアクションもすべて同様です。Scaffolderのテンプレートはより機微な領域と見なされるため、テンプレートの作成・更新へのアクセスは信頼できる関係者に限定することが推奨されており、テンプレート実行自体は入力に関わらず安全であることを意図しているものの、この追加の防御層が推奨されています。文字列テンプレートはリモートコード実行攻撃を緩和するためNode VMサンドボックス内で実行されますが、Scaffolderはしばしば、GitHub組織内にリポジトリを作成するといった昇格された権限を持ちます。
つまり、Scaffolderに設定されているGitHubの認証情報は、単なる「読み取り用のAPIキー」ではなく、組織のリポジトリを作成・変更できる強い権限を持っていることが多いということです。この認証情報にAIエージェントから間接的にアクセスできる状態を作ってしまうと、前回扱った「承認フロー」だけでは足りない、権限そのものの設計が必要になります。
個人アクセストークンの問題点と、GitHub Appへの移行
Backstageのチュートリアルで最初に案内される設定方法は、個人アクセストークンをapp-config.local.yamlに直接書き込む形です。この方法は動作確認には便利ですが、本番運用にはいくつかの弱点があります。1つのトークンにひもづく権限がまとまって強く、しかも特定の個人のアカウントに紐づいているため、その人が退職・異動した場合にトークンが失効し、逆に強すぎる権限がずっと有効なまま残ってしまうこともあります。
これに対する基本方針は、個人アクセストークンではなく、GitHub Appのようなきめ細かい権限管理の仕組みに移行することです。Backstageのscaffolderやプラグインは、サービストークン、OIDC信頼、あるいはGitHub Appのcredentialsを使ってActionsを起動できます。ここで難しいのは、その認証情報が適切な権限レベルを反映しているようにすることです。たとえば、新しいリポジトリをプロビジョニングするテンプレートは、本番環境へのデプロイと同じキーを使うべきではありません。GitHub Appのインストールを通じたきめ細かい権限設定によって、これを安全かつ監査しやすい形に保てます。
言い換えると、「リポジトリを作る権限」と「本番にデプロイする権限」を同じ認証情報にまとめてしまわないことが最初の設計判断です。AIエージェントがどのテンプレートを呼び出すかによって、必要な権限の範囲は本来大きく異なります。GitHub Appを用途ごとに分けてインストールし、それぞれに必要最小限のスコープだけを与えておくことで、仮にAIエージェント経由の呼び出しで問題が起きても、影響範囲を限定できます。
ユーザー単位の権限分離
もう一つの論点は、「誰の権限で実行するか」です。多くの場合、Backstageに設定されたGitHubの認証情報は、Backstage自体、あるいはサービスアカウントの権限であり、実際に操作を依頼した人物(あるいはエージェント)の権限とは切り離されています。これは、Backstageに強い権限を持つトークンが設定されている場合、そのトークンに本来アクセスできないはずのユーザーが、Scaffolder経由で間接的にその権限を使えてしまうという問題につながります。この課題に対して、GitHubなど各種の認証をユーザー本人のトークンで行うことを強制するオプションが検討されており、環境変数や設定でこれを有効化できるようにする案が出ています。
AIエージェント経由の呼び出しでも、考え方は同じです。エージェントが「誰の代理として」操作しているのかを明確にし、その人物が本来持っている権限を超えた操作ができないようにする設計が望ましいです。前々回のMCP実装編で触れた「静的トークンからサービスアカウント・OAuthベースの認証への移行」は、ここでも同じ形で効いてきます。エージェント自身に固定の強い権限を持たせるのではなく、呼び出し元のユーザーの権限に紐づける構成が、より安全な選択です。
RBACを有効にしただけでは足りない
権限設計を考える上で見落としやすいのが、RBAC(ロールベースのアクセス制御)を有効にしただけでは、実際には権限が絞られていないケースがあるという点です。RBACを有効にしていても、既定の権限ポリシーは緩やかなままであることが多く、多くの構成では既定のゲストポリシーがすべてのカタログエンティティへの完全な読み取りアクセスを許可しています。RBACを有効にしただけでポリシーの見直し・厳格化を行っていないチームは、アクセス制御ができていると思い込んでいても、実際には認証済みのすべてのユーザーがすべてのカタログエンティティを読み取り、すべてのScaffolderテンプレートを実行し、すべてのプラグインアクションを呼び出せる状態になっていることがあります。
AIエージェントにScaffolderへのアクセスを許可する際、RBACが「有効になっている」ことと「意図した権限に絞られている」ことは別問題だと意識しておく必要があります。既定のポリシーを前提にせず、実際にどのロールがどのテンプレートを実行できるかを確認しておくことが、GitHub操作の権限設計以前の土台になります。
テンプレート・インジェクションという既存のリスク
GitHub操作そのものとは別に、Scaffolderの実装に起因するリスクもあります。BackstageのScaffolderは、テンプレートの処理にNode.jsのテンプレートエンジンであるNunjucksを使用しています。テンプレートへの入力はテンプレートファイルに埋め込まれる形で処理されるため、入力値が適切にサニタイズされていない場合、入力値を制御できる攻撃者がNunjucksのテンプレート構文を注入し、Scaffolderのnode.js実行環境で任意のJavaScriptを実行できてしまう、サーバーサイド・テンプレート・インジェクション(SSTI)の脆弱性につながる可能性があります。これはScaffolderの実行環境にある、設定済みの認証情報やサービスアカウントすべてへのフルアクセスを伴います。
AIエージェントがユーザーからの自然言語の指示を受けてテンプレートのパラメータを組み立てる場合、この入力値の経路がさらに複雑になります。人間が直接フォームに入力する場合よりも、どのような文字列が最終的にテンプレートに渡るかの見通しが立てにくくなるため、入力のサニタイズやバリデーションは、AIエージェント経由の呼び出しではより厳格に行う必要があります。
AIエージェント特有の新しいリスク
ここまでは主に権限設計の話でしたが、AIエージェントがリポジトリ操作を行うこと自体に、比較的新しい種類のリスクも指摘されています。2026年のBlack Hat USAで報告された内容として、AIエージェントのハーネスにおいて、あるコンポーネントはリポジトリの内容を信頼できないものとして扱う一方、別のコンポーネントが同じ内容を設定や命令、実行可能な状態として読み込んでしまうという構造的な問題が、複数のベンダーにまたがって確認されています。
これはBackstage固有の問題ではありませんが、Scaffolderのようにリポジトリの作成・操作を行う仕組みをAIエージェントに開放する場合には無視できません。実務的な対処として、PRを扱うジョブに書き込み権限を持つトークンを渡さないようにするという方針が提案されています。ScaffolderをAIエージェントに開放する際も、同様の考え方が当てはまります。エージェントがリポジトリの内容を読み込んで判断を下すフローと、実際に書き込み操作(リポジトリ作成、PR作成など)を行うフローを分離し、書き込み権限は必要な操作の直前でのみ、最小限のスコープで付与する設計が安全です。
段階導入への当てはめ
これまでの記事で扱ってきた段階導入の考え方を、GitHub操作の権限設計に当てはめると、次のような順序になります。
- 開発環境限定・読み取り専用:エージェントにはリポジトリ情報の参照のみを許可し、書き込み系の認証情報には触れさせない
- 本番・限定スコープのGitHub App:リポジトリ作成など、影響範囲の小さい操作に限定したGitHub Appを用意し、ユーザー単位の権限に紐づけた形でエージェントに許可する
- 本番・承認フロー付きの書き込み拡大:前回扱った承認フローと組み合わせ、より影響の大きい操作(本番リポジトリへの直接の変更など)は、人間の承認を必須にしたうえで解禁する
Scaffolderがもともと強い権限を前提にした設計であることを踏まえると、この段階を飛ばしていきなり書き込み権限を広く与えることは避けるべきです。
制約・注意点
- 本記事で扱ったGitHub Appへの移行やユーザー単位の権限分離は、組織のGitHub Enterprise/Organizationの設定に依存する部分が大きく、具体的な設定手順は組織ごとに異なります。
- テンプレート・インジェクションへの対処や、AIエージェント特有のリスクへの対処は、業界全体でもまだ議論・対策が進行中の領域です。今後新しい知見が出てくる可能性があります。
- 本記事はBackstage/Scaffolderの文脈に閉じた整理であり、AIエージェントのセキュリティ全般を網羅したものではありません。
まとめ
- Scaffolderはもともと、リポジトリ作成などの昇格された権限を前提にした設計であり、この前提を理解した上で権限設計を行う必要があります。
- 個人アクセストークンではなく、用途ごとに分けたGitHub Appによるきめ細かい権限管理への移行が基本方針です。
- 認証情報をエージェント自身に固定で持たせるのではなく、実行者本人の権限に紐づける設計が望ましいです。
- RBACを有効にしただけでは権限が絞られているとは限らず、既定ポリシーの見直しが前提になります。
- テンプレート・インジェクションや、AIエージェント特有の「信頼できないコンテンツを命令として読み込んでしまう」リスクにも注意が必要で、読み込みと書き込みのフローを分離し、書き込み権限は必要な直前にのみ最小スコープで与えるのが安全です。
参考リンク
- Backstage公式「Backstage Threat Model」
- hoop.dev「The simplest way to make Backstage GitHub Actions work like it should」
- Backstage GitHub Issue #22867「enforce user auth in scaffolder actions」
- AquilaX「Backstage Developer Portal Security: Plugin Vulnerabilities, RBAC Bypass, and Catalog Poisoning」
- windowsforum.com「GitHub Actions AI Agents: Remove Write Tokens From PR Jobs」
注意事項
本ブログに掲載している内容は、私個人の見解であり、
所属する組織の立場や戦略、意見を代表するものではありません。
あくまでエンジニアとしての経験や考えを発信していますので、ご了承ください。