GitLost: GitHub AIエージェントをだましてプライベートリポジトリを流出させる
(noma.security)- Noma LabsはGitHub Agentic Workflowsで間接プロンプトインジェクション脆弱性「GitLost」を発見した。公開リポジトリのIssueだけで、同じ組織のプライベートリポジトリのデータを公開コメントに露出させることができた
- この機能はMarkdownワークフローをYAML Actionsファイルにコンパイルし、ClaudeまたはGitHub CopilotベースのAIエージェントがIssueを読み、ツールを呼び出し、組織内リポジトリにアクセスする仕組み
- 脆弱なワークフローは
issues.assignedイベントでIssueのTitleとBodyを読み、add-commentで応答しており、公開・プライベートリポジトリの読み取り権限を持っていた - 攻撃者はコード、アクセス権限、認証情報なしで、公開リポジトリにもっともらしいIssueを作成するだけでよかった。テストでは
pocとtestlocalのREADME.mdの内容が公開Issueコメントに投稿された - GitHubのガードレールは「Additionally」変種を意図どおりに防げず、エージェント型AIではコンテキストウィンドウ自体を攻撃面とみなし、ユーザー制御コンテンツを信頼された指示と分離する必要がある
GitLostが狙った信頼境界
- Noma LabsはGitHubの新しいAgentic Workflowsで、GitLostという脆弱性を発見した
- 認証されていない攻撃者が同じ組織の公開リポジトリに細工したGitHub Issueを投稿すると、エージェントに組織内のプライベートリポジトリのデータを取得させるよう誘導できた
- 攻撃手法は、AIエージェントが読むコンテンツの中に悪意ある指示を隠す間接プロンプトインジェクションに該当する
- 運用者が意図した指示より、攻撃者が隠した指示が優先して処理されると、プライベートデータが誰でも見られる公開Issueコメントとして露出する可能性がある
GitHub Agentic Workflowsの動作方式
- GitHub Agentic Workflowsは、チームがリポジトリ自動化を自然言語で記述できるようにする
- ワークフローはMarkdownの
.mdファイルとして書かれ、YAML形式のGitHub Actions.ymlファイルにコンパイルされる - 実行時には、ClaudeまたはGitHub CopilotベースのAIエージェントが設定された権限内で作業する
- GitHub Issueの読み取り
- ツール呼び出し
- 組織内の他リポジトリへのアクセス
脆弱なワークフロー条件
- Noma Labsが確認した脆弱な設定は、公開Issueとエージェント権限が組み合わさると問題になる
- GitHubの
issues.assignedイベントでワークフローをトリガー - IssueのTitleとBodyを読み取る
add-commentツールでコメントを投稿- 組織内の他リポジトリの読み取り権限を保有
- 公開リポジトリ
- プライベートリポジトリ
- GitHubの
- 攻撃者に別途コード作成、アクセス権限、認証情報は必要なかった
- 必要な条件は、GitHub Agentic Workflowを使っている組織の公開リポジトリにIssueを作成することだけだった
攻撃の流れ
- 研究チームは顧客ミーティング後にVP Salesが依頼しているように見えるもっともらしいGitHub Issueを作成した
- Issueが割り当てられるとワークフローアクションがトリガーされ、テストでは別のGitHub workflow actionでも同じ方式で動作した
- GitHubの自動化がIssueを割り当てた後、イベントで実行されたワークフローがエージェントにリポジトリ内容を取得させた
- エージェントは次のリポジトリの
README.md内容を取得するよう誘導されたpoc公開リポジトリtestlocalプライベートリポジトリ
- その後GitHubエージェントがその内容を公開リポジトリのIssueコメントとして投稿し、誰でも読める状態になった
「Additionally」でガードレールを迂回
- GitHubにはこのシナリオを防ぐための限定的なガードレールがあった
- Noma Labsは攻撃者のように複数の変種を繰り返しテストした
- 「Additionally」というキーワードを追加すると、モデルが拒否せず出力を再構成するという意図しない動作が発生した
- この迂回によりGitHubのガードレールは意図どおりに機能せず、データ流出を防げなかった
PoCと露出したデータ
- Noma Labsは確認結果、再現ワークフロー、実際の証拠を公開した
- 流出したデータには次のリポジトリの
README.md内容が含まれるsasinomalabs/poc: 公開リポジトリsasinomalabs/remote-ping: 公開リポジトリ、READMEがないことを確認sasinomalabs/testlocal: プライベートリポジトリ
エージェント型AIで変わるセキュリティ前提
- エージェントのコンテキストウィンドウは作業空間であると同時に攻撃面になる
- エージェントが読むコンテンツはすべて武器化されうる
- Issue
- Pull Request
- コメント
- ファイル
- 従来のセキュリティモデルでは、信頼境界はコードによって強制されると想定する場合が多い
- エージェント型システムでは、信頼境界の一部がモデルの動作によって強制される
- モデルは本質的に指示に従うため、プロンプトインジェクションはエージェント型AIにおいて、SQLインジェクションがWebアプリケーションに対して持っていたのと同じカテゴリの脆弱性になる
- この種の脆弱性には体系的な戦略と防御が必要だ
推奨される防御策と公開手順
- ユーザー制御コンテンツをAIエージェントの信頼された指示入力として扱うべきではない
- エージェント権限は必要最小限の範囲に制限すべきだ
- 複数リポジトリにアクセスできるエージェントは、特に価値の高い攻撃対象になる
- Issue内容に応答する場合のように、エージェントが公開投稿できる内容を制限すべきだ
- ユーザー入力をモデルに渡す前に、指示コンテキストからサニタイズまたは隔離すべきだ
- GitLostはGitHubに責任ある形で開示され、脆弱性の詳細はGitHubが認知した状態で共有された
1件のコメント
Hacker News の意見
プロンプトインジェクションがエージェント型 AI において、SQL インジェクションが Web アプリで占めていた位置と同じだという比喩は妙です。プロンプトインジェクションは SQL インジェクションよりも LLM にとってはるかに致命的なのではないかと思います
SQL インジェクションは、ユーザー入力が SQL エンジンに渡されるコマンド文字列の一部になることで発生し、悪意ある入力が SQL 構文トークンで現在のコマンドを終了させたうえで自分の SQL コマンドを付け加えると、エンジンが両方を実行していました。解決策は、プリペアドステートメントのような固定・静的・事前コンパイル済みのコマンド文字列を使い、任意のユーザー入力はデータとしてだけ適用することでした
エージェントにおける似た緩和策は、「repo 1 を読む」「repo 2 を読む」のような固定動作を用意し、ユーザー入力はどの動作を実行するかを選ぶデータとしてだけ使う方式ですが、これはすでにメニューと呼ばれている技術です。LLM の価値は本質的にメニュー以上のものだという点にあり、SQL の価値は「任意のデータに適用される事前定義済みロジック」以上である必要がない、という点が違います
エージェントに限定された動作だけを許可するのは一部の特殊な問題しか扱わず、コードとユーザーデータを分離しているわけでもないので、同じ問題ではありません。限定された動作だけを用意するのは、より厳格なデータベース権限を使うことに近いです。ユーザーがどうせ実行できる SQL だけが許可されるなら、SQL インジェクションも大した意味を持たなくなります
メニューから選ばせるのも一つの方法ですが、可能な行動範囲はもっと広く設計できます。メールツールを与えれば顧客にスパムを送れてしまいますし、返信だけできるようにロックすれば事故の範囲を減らせます。画像レンダリングでデータが漏れるような脆弱性のように、データ流出も制限しなければなりません
解決策も同じです。最小権限のロールベースアクセス制御を適用し、重要な操作には管理者の承認を要求すればよいのです。そうすれば、LLM が単独でできる最悪のことは、不適切な言葉を出力する程度になります
緩和策の一つはプリペアドステートメントですが、もう一つは、どのユーザーにもデータベース全体へのアクセスを許可しないことです。読み取り専用ユーザーは、SQL インジェクションの有無にかかわらず
DROP TABLEを実行できてはなりませんこのエージェントは無制限の読み取りアクセスを持っていて、回答の「受信者」という概念がありません。受信者の権限を含めれば、自動的に読み取りアクセスを拒否させるのはかなり単純です。唯一の解決策ではありませんが、その方向の解法を思いつくのは難しくありません
「メニュー」の例は、変わったことは何もないという意味でもあります。LLM であれ人間の従業員であれ、許されるのは制御された固定行動の集合だけです。自由度は主に表現にあり、権限付与は固定集合です。なぜメニュー以上である必要があるのか分かりません
これがなぜ GitHub の脆弱性なのか分からない。研究者たちがエージェントに非公開リポジトリへのアクセス権を与え、公開リポジトリで質問に答えさせたのだから、当然 非公開情報の抽出は可能になる。
シークレット値にアクセスできる通常の CI ジョブを作り、公開 PR で実行するのと同じ。公開コードや LLM の指示が機密情報にアクセスできるコンテキストで実行されるように GitHub を設定すれば漏えいする。それは GitHub のせいではなく、設定した人のせいだ。
トークンのスコープを厳しく絞っても公開リポジトリへのアクセスは常に許可され、例えば公開リポジトリの Issue を通じた漏えい経路が残る。安全にするには、GitHub が提供するものより厳格な制御を実装する MITM プロキシで補う必要がある。
GitHub Agentic workflows はこの種の問題に対する公式の一次的な解決策になるはずだが、セキュリティモデルにせよ安全な使い勝手の面にせよ、まだやるべきことがありそうだ。
詳細: https://haulos.com/blog/do-not-give-your-agent-github-access...
公開開発とも両立でき、外部の人が公開 Issue を作成することも許可しながら、各ユーザーに置く信頼レベルを反映できる。きちんと考えれば選択肢はもっとあるはずだ。
そのためには細かいスコープ指定と権限を技術的にサポートする必要があり、エージェントで何を達成するのか、そのために必要な最小権限・機能は何かを時間をかけて検討する必要がある。
1つ目は実現しそうだ。エージェント利用はまだ西部開拓時代だ。人がエージェントを設計するときにスコープと権限を見つけて定義する摩擦を減らす抽象化や、エージェント機能を制限するときに細かさと使いやすさのバランスを取るインターフェースがどうなるのか興味深い。
2つ目は、常に高品質なソフトウェア構築を妨げてきた核心的な障害だ。きちんと考え、きちんと実装する時間をかけることは、「素早く動いて壊せ」式にエージェントをどこにでも投げ込むやり方と真っ向からぶつかる。
これらの質問のうち1つでも答えが「いいえ」なら問題だ。古典的な GitHub Workflows にも PR トリガーのワークフローを通じた 権限昇格は山ほどあるが、それは別の話だ。
本当の解決策は、プロンプトごとの権限制御 UIをもっと良くすることだ。「Web 検索の有無」を選ぶように、「自分の非公開リポジトリを含める」オプションを簡単にオン・オフできるべきだ。
研究者たちが “Additionally” のような単語1つで GitHub が誇っていたガードレールを回避する様子は笑える。LLM のコンテキストウィンドウ内に強い セキュリティ境界を設けようとする試みは、失敗するしかないことを示している。
モデルは本質的に指示に従うよう作られているので、システムルールとユーザー入力を混ぜると、より新しい、またはより執拗な指示が勝つことになる。
「責任ある開示」セクションに、いつ修正されたのか、GitHub が認めたのか拒否したのかがなぜないのだろう。GitLost は GitHub に責任を持って開示され、詳細は GitHub が把握している状態で共有していると書かれているが、まだ修正していないのか。
https://github.github.com/gh-aw/reference/cross-repository/#...
Microsoft のような大企業は、投資家からの圧力のために、今や AI 企業だと主張しようとして全製品に AI を載せている。Adobe がやったことに似ている。
消費者はこうした中途半端な AI 統合に疲れつつあり、まもなく限界点が来そうだ。
本当に、あちこちクリックしてもすべてが即座に反応し、ランナーを付けた CI も美しく動く。ランナー設定のドキュメントはもう少し明確でもよいが、それ以外はすべて非常に滑らかだった。
売上は実際に存在していて印象的であり、消費者向け・席数ベースの売上を置き換えている。市場はまだ SaaS の倍率を引き下げているところだが、その判断は正しいと思う。四半期報告書で売上を分離して見ると、実際の効率性から生まれた 大きな成長ストーリーがある。
公開リポジトリのコンテキストで実行されるアクションが、なぜ非公開リポジトリへのアクセス権を持っていたのか分からない。ワークフローを見ると、通常は非公開リポジトリの権限を付与しない
github tokenを使っているように見えるあるいは、エージェント自体が somehow より高い権限を持っていたのだろうか? だとすれば、エージェントの設定ミスだ。エージェントが何かを強制してくれると信じてはいけないことは、すでに分かっている
この記事は Noma のマーケティングのように読める。かわいい名前、ロゴ、釣りっぽいタイトル、非技術系の読者を狙ったような劇的なトーンまである
実際の脆弱性が何かというと、LLM に非公開データを渡して誰でもやり取りできるようにすれば、データが漏れ得るということだ。あまりにも当然だ
こういう人たちは、LLM にディスク全体への書き込み権限を与えて破壊的な作業をさせた、と文句を言うのだろう
AI エージェントに非公開リポジトリを読ませたくないなら、非公開リポジトリへのアクセス権を与えなければよい。これは権限の迂回問題ではなくプロンプトインジェクションの問題であり、エージェント層で信頼性高く解決することはできない
すでに解決済みの問題なのか、あるいは GitHub がまだ解決できておらず、その間に悪意ある攻撃者が各リポジトリに対して脆弱性を試すことになるのかもしれない
リポジトリ数が多いので、ゼロではない確率で漏えいが起こり得る。ただし詐欺被害のように、漏えいを認める人はほとんどいないだろう