セキュリティ企業のWizが2026年8月17日、Snowflakeの公開リポジトリにあったGitHub Actionsの脆弱性について調査結果を公開した。誰でも作れるGitHub Issueのタイトルに細工をするだけで、CIランナー上で任意のコマンドを実行でき、そこから同社の内部Jiraの認証情報を持ち出せた、という内容だ1。
事案そのものは6月に起きて同日に修正されている。それでもこの報告が注目されたのは、経緯の並びのためだ。脆弱なパターンが入ったPRには、レビューした共同作成者として「Copilot Autofix powered by AI」が記録されていた。そしてそれを5日後に見つけて実際に突いたのも、Wizの自律型AIツール「Red Agent」だった1。Wizはこれを、「AIコーディングエージェントが関わるワークフローの中でも重大な脆弱性は混入し承認されうる一方、自律型のAIセキュリティエージェントはそれを実環境で速やかに発見・悪用しうる」新しい現実だと位置づけている1。
Issueのタイトルがシェルに届いてしまう
問題があったのは snowflakedb/snowflake-connector-net リポジトリの jira_issue.yml というワークフローだ。Jiraの認証情報を扱うワークフローで、issues: opened で起動する。つまりどのGitHubユーザーでも、Issueをひとつ立てるだけで起動できた1。
そのワークフローが、攻撃者の制御下にあるIssueのタイトルを、そのままシェルスクリプトに展開していた1。タイトルに含まれる引用符をsedで処理するコードは書かれていたのだが、そのエスケープが走るのはGitHubのテンプレート展開の後になる。順番が逆であるため、タイトルにシングルクォートを1つ入れるだけで文字列から抜け出せ、任意のコマンドを実行できた1。
それ以前のこのリポジトリのコードは、Issueのタイトルをenv:変数として渡し、jqでJSONを組み立てる書き方をしていた。外部の入力を文字列として連結せず、構造化データとして扱う定石だ。マージされたPRはこの安全なパターンを取り除き、直接の文字列展開に置き換えていた1。
防御に見える記述もあった。ワークフローには特定のボットを除外するif:条件が付いていたのだが、issuesイベントではgithub.event.pull_requestが常にnullになる。そのため条件は「nullはそのボット名と等しくない」に縮退し、常に真になる。結果として、すべてのGitHubユーザーがこのゲートを通過した1。書いてあるのに働いていないチェックであり、この部分はAIの関与とは切り離して読める。
5日間で発見され、Jiraの読み取り権限まで届いた
Wizの説明によれば、Red AgentのCI/CD機能がSnowflakeのGitHub組織をスキャンし、run:ブロックの中で信頼できない入力を扱っている点からこのワークフローを脆弱と判定した1。
このとき注目されているのが、最初の試行が失敗したあとの挙動だ。Red Agentが最初に使った書き方ではシェルの構文エラーが返ったが、エージェントは停止も失敗もせず、エラーを自律的に解析してペイロードを組み替え、外部へのコールバックを成立させた——というのがWizの記述である1。数秒のうちに、GitHub Actionsランナーからbase64エンコードされた認証情報が届いた1。
窃取されたトークンはsnowflakecomputing.atlassian.netに[email protected]として認証し、Snowflakeのエンジニアリング、セキュリティコンプライアンス、バグバウンティ管理の各プロジェクトへの読み取りアクセスを与えた1。
ここは実害の範囲として正確に読む必要がある。Wizは概念実証のテスト中にアクセスしたデータをすべて安全に削除したと確認しており、監査ログの分析でも、5日間の露出期間に外部の第三者がアクセスした形跡はないとされている。異常なクエリはすべてWizのテスト用IPに一致した1。Snowflakeも「調査では不正アクセスの形跡は見つからなかった」とコメントしている1。
対応は速い。報告は6月23日にHackerOne経由で行われ、Snowflakeは同じ日にワークフローを修正して、安全なenv:とjq --argのパターンを復元した1。Jiraトークンは翌6月24日にローテーションされている1。
この夏に扱ってきたOpenAIの評価用モデルがサンドボックスを脱出した件や英国AI Security Instituteが公表した評価中のエージェントの逸脱は、いずれも評価環境の中でエージェントが想定を超えた話だった。今回は攻める側のエージェントが、外部の実在するリポジトリに対して人手を介さず動いている点が違う。
「AIが脆弱性を作った」と言えるのか
この件でいちばん扱いが難しいのが、Copilotの関与の程度だ。
Wizが最初に公開した本文には、脆弱なパターンを持ち込んだのは6月18日にマージされたPR #1218で、その最終コミットが「Copilot Autofix powered by AI」を共同作成者としてクレジットしている、と書かれている1。そして本文中には「言い換えれば、AIの『autofix』コミットがまさにそのインジェクションの入り口を作った」という一文もある1。
ところがWizは、公開当日の8月17日19:57 UTCに冒頭へ訂正を追記している。そこにはこう書かれている——Copilotはマージされたそのプルリクエストとコード変更をチェックした共同作成者であり、重大な脆弱性に気づかないまま問題なしと判定した。コード変更自体がAIによるものだったかは不明である1。
つまり現時点でWiz自身の記述として確からしいのは、「AIが危ないコードを書いた」ではなく、「AIがそのコードをレビューして通した」のほうだ。あわせてWizは、GitHubのAI支援セキュリティレビューが、その結果生じた重大な脆弱性を指摘しなかったとも書いている1。本文中に更新前の強い表現が残っているため、読むときはこの2つを分けて受け取る必要がある。
区別が重要なのは、対策の向き先が変わるからだ。生成側だけを疑って人間のレビューを厚くする発想では、AIのレビューが「問題なし」を出す側に回っている今回の構図はカバーしきれないと考えられる。
手元の運用に引き寄せると
Wizが挙げた教訓は3つある。AIが生成したPRも人間のコードと同じ静的解析とセキュリティ精査を通すこと。自動発見が数時間単位で起こる前提に立ち、パッチ適用を速め、認証情報を短命にすること。そしてAIエージェントが、構造化データのパーサーを直接の文字列展開に置き換えることをブロックするガードレールを実装すること1。
3つ目にWizが添えている理由が具体的だ。自動のAIアシスタントは、そのコードパターンがなぜ選ばれたかという歴史的な文脈を持たないことが多い——今回取り除かれたenv: + jqは、まさにシェルインジェクションを防ぐために明示的に置かれていたものだった1。
自分たちの環境に当てはめるとき、まず見る場所ははっきりしている。外部の誰でも起動できるイベント(Issueの作成、PRのコメントなど)で走るワークフローと、そこで参照しているシークレットの一覧だ。今回の事案では、その2つが同じワークフローに同居していた。CI/CDまわりの点検は、MicrosoftがZero TrustのワークショップにDevSecOpsの柱を新設した8月4日の発表でも対象に含まれている領域にあたる。
もうひとつは、AIが関わったPRの扱いを決めておくことだ。エージェント向けの共通パッケージ形式であるAgent Plugins 1.0のように、エージェントを開発フローに組み込むための土台は整いつつある。「AIが直したから安全」でも「AIが直したから危険」でもなく、コミットの共同作成者が誰であれ同じ検査を通す、という運用の線を先に引いておくほうが実務的だろう。
Snowflakeは、この学びをWizと共同で業界に共有していくとコメントしている1。
Sources
- Wiz Red Agent Finds Its Way Into Snowflake’s Internal Jira Through a Flaw in a GitHub Copilot–Assisted PR - Wiz公式ブログ、Gal Nagli(2026年8月17日、同日19:57 UTCに冒頭を更新)