TITLE

GitHub Copilotが共著者にクレジットされたSnowflakeの脆弱性、自律型AIエージェントが突破

投稿日:2026.08.18

CATEGORY

  • AI開発
GitHub Copilotが共著者にクレジットされたSnowflakeの脆弱性、自律型AIエージェントが突破

2026年8月17日、セキュリティ企業Wizが、Wiz自身の自律型AI攻撃エージェント「Red Agent」がSnowflakeの公開GitHubリポジトリで見つけたシェルコマンドインジェクションの脆弱性を突破し、内部のJira APIトークンを数秒で窃取するPoC(概念実証)を公表しました。この脆弱性が仕込まれたコミットは、AIコーディングツール「GitHub Copilot」の自動修正機能「Copilot Autofix」が共著者としてクレジットされていましたが、Wiz自身は「このコード変更がAI主導だったかは不明」と明記しています。同日、The Hacker Newsも同じ事案を報じました。

GitHub Actionsのワークフローで、issueのタイトルをそのままシェルに流し込む――このパターン自体は目新しいものではなく、GitHubは2025年7月の時点で危険性を注意喚起していました。それでも2026年6月、Snowflakeの本番リポジトリで同じ形の穴が生まれ、人間ではなく自律型AIエージェントに見つけられて突破されています。

GitHubのIssueタイトルが凶器になる仕組み

対象は、Snowflakeの公開リポジトリsnowflake-connector-netにあるGitHub Actionsワークフローjira_issue.ymlです。2026年6月18日、コミット4a1b8ce(PR #1218「SNOW-2069227: Update jira workflows」)で、issueのタイトルや本文を扱う処理が書き換えられました。

変更前は、issueのタイトル・本文のような外部入力をenv:ブロックの環境変数として受け渡してからシェルスクリプトで参照する形になっていたと考えられます。ところが変更後は、この外部入力がrun:ブロックの中に直接文字列として展開される形に置き換わっていました。GitHub Issueのタイトルは、そのリポジトリにIssueを立てられる誰もが自由に書ける値です。ここにシェルのメタ文字(;`など)を仕込めば、ワークフロー実行時にその文字列がコマンドとして解釈されます。

このPR #1218の最終的なスカッシュコミットは、"Copilot Autofix powered by AI"を共著者としてクレジットしています。Copilot Autofixは、GitHubが提供するAIによる脆弱性の自動検出・修正提案機能です。名前だけを見れば「AIが直したはずの箇所が、逆に穴を生んだ」という筋書きに読めてしまいますが、この点は次の見出しで改めて扱います。

数秒で鍵が抜かれた瞬間

鎖から抜き出される鍵のイラスト。数秒でトークンが窃取されたことの比喩

Wizは、Wiz自身のRed Agentを使って、認可されたセキュリティテストの一環でSnowflakeのGitHub organizationをスキャンしました。その過程でこのワークフローの脆弱性を発見し、issueのタイトルに細工したペイロードを仕込んでPoCを試みています。

結果は、Jiraの内部APIトークン(qa@snowflake.netに紐づくもの)が数秒で窃取されるというものでした。攻撃者が用意したURLへコールバックさせるだけで、送られてきたトークンをアクセスログから回収できます。Wizはこれを実際の不正利用としてではなく、認可されたPoCとして実行しており、悪用や不正アクセスの証拠はないと明記しています。それでも、シェルへの一行の文字列展開が、社内システムの認証情報を数秒で外部に持ち出せる経路になっていたという事実そのものは変わりません。

失敗しても止まらない攻撃

Red Agentが最初に試したペイロードは#を使う形式でしたが、シェルの構文エラーで失敗しました。ここで攻撃が止まっていれば、この脆弱性は「理論上は危険だが実際には突破しにくい」という評価で終わっていたかもしれません。

しかしRed Agentは、その構文エラーを自律的に解析し、ペイロードを; echo 'という別の形式に組み替えて再試行し、成功させています。人間の攻撃者であれば試行錯誤に時間がかかる場面を、AIエージェントが自分の失敗を読んで即座に修正した形です。

Wizの「Red Agent」は、2026年3月のRSA Conferenceで発表された製品で、APIの攻撃対象領域を自律的にマッピングし、アプリケーションロジックを推論しながら適応的な手法で脆弱性を悪用する「AI搭載の攻撃者」と位置付けられています。同年4月22日にパブリックプレビューを開始し、その後一般提供(GA)へ移行しました。今回のSnowflakeの一件は、この製品の実運用における能力の一端を示す事例として公表されたものです。

5日間の窓

脆弱性の導入(6月18日)からパッチ(6月23日)、トークンローテーション(6月24日)までのタイムライン図

脆弱なパターンが導入されたのは2026年6月18日。Wizが発見・PoC実施の上でHackerOne経由(報告 #3819931)でSnowflakeに報告したのが6月23日。Snowflakeは同日中にPR #1402(コミット1dc7766)でパッチを適用し、直接のシェル展開をenv変数とjqを使う安全なパターンに戻しています。該当するJiraトークンは翌6月24日にローテーションされました。

つまり、脆弱なコードが公開リポジトリに存在していた期間は、約5日間です。Snowflakeは「不正アクセスの証拠はない」と説明していますが、この5日間、issueを立てられる誰もがこの穴に到達できる状態にあったこと自体は動きません。なお、記事執筆時点でこの脆弱性にはCVE番号が割り当てられておらず、CVSSスコアの算出もCISAのKEV(既知の悪用された脆弱性)カタログへの登録もありません。

「AIが書いた」と断定しない誠実さ

ここまでの流れだけを見ると、「AIが書いたコードの脆弱性を、別のAIが見つけて突破した」という分かりやすい対比に落とし込みたくなります。ただし、Wizは記事の中で、"It's unclear whether the code-change was AI-assisted"(このコード変更が実際にAI主導だったかは不明)と明記しており、Copilot Autofixが脆弱な行そのものを書いたと断定していません。分かっているのは、PR #1218の最終スカッシュコミットが"Copilot Autofix powered by AI"を共著者としてクレジットしている、という事実だけです。squashコミットのクレジットは、そのブランチでAI支援ツールが何らかの形で使われたことを示しますが、どの行を誰が(あるいは何が)書いたかまでは特定できません。この記事にはGitHubやMicrosoftからの公式コメントも記載されていません。

読者としては、「AIが脆弱性を作った」という見出しに飛びつく前に、一次情報がどこまで確認していて、どこから先が推測なのかを分けて読む姿勢が要ります。Wizのこの書き方は、その分け方の手本になっています。

私たちの実務でも確かめ直した点があります

私たちも複数のプロダクトで、GitHub Actionsのワークフローを継続的インテグレーション(CI)に使っています。今回のSnowflakeの穴(issueのタイトルをrun:ブロックへ直接展開する入力検証の不備)とまったく同じパターンが私たちのワークフローにあるかどうかは、この記事のために新たに点検したものではありません。それでも、2026年8月8日に社内の全プロダクトを棚卸しした際に分かったことには、根っこでつながる教訓がありました。「CIが動いている」ことと「そのCIが実際に本番反映を止める」ことは別物だという点です。テストは走っていても、その結果がデプロイの可否に結線されていない経路が複数見つかっています。

Snowflakeのケースも、この棚卸しの発見も、共通しているのは「仕組みが存在する」ことと「その仕組みが実際に機能を果たしている」ことを、確かめないまま同一視してしまう点です。私たちの場合、AIエージェントが書いたコードをmainブランチへ直接pushすることはできない仕組みになっており(gitのフックで物理的にブロックしています)、必ず人間のレビュー・承認を経てから反映します。共著クレジットの有無にかかわらずこの手順を通す設計自体は、今回のSnowflakeの件を読んでも変える必要はないと判断していますが、棚卸しで見つかった「CIとデプロイの結線漏れ」は、まさに仕組みが機能しているかを確かめずにいた例そのものでした。

まとめ

GitHub Copilotへの疑いが晴れても晴れなくても、run:ブロックに外部入力を直接展開しているワークフローが残っていれば、次にそれを見つけるのは人間の審査担当者とは限りません。Red Agentのような自律型AIエージェントかもしれない、という前提に立って点検の優先順位を組み直す必要があります。

今日からできる最初の一歩は、自組織の.github/workflows/配下で${{ github.event.issue.title }}${{ github.event.issue.body }}、あるいは${{ github.event.pull_request.title }}のような外部入力がrun:ブロックの中に直接埋め込まれていないかを検索することです。見つかれば、env:で変数として受け渡してからシェル側で参照する形に直す必要があります。この5日間の窓は、Snowflakeだけの話とは限りません。


出典

※ この記事は AI を使用しています。Leadeas が自社開発した AI エージェント基盤で下書きを作成し、人間のレビューを経て公開しています。AI ネイティブ開発会社として自社の技術をそのまま実演する目的で、この手法を用いています。(詳しくは AI 利用ポリシー)

AI

AI導入やシステム開発の ご相談を承っています。

お気軽にお問い合わせください