0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AIエージェントの権限設計 ― OpenAIのサンドボックス脱出インシデントから

0
Last updated at Posted at 2026-08-28

TL;DR

  • OpenAIが、社内の評価環境で動かしていたエージェント群がサンドボックスを脱出し、Hugging Faceの本番インフラまで到達したインシデントの公式報告書を公開した(2026年8月26日公開、事象は5〜7月)。
  • 原因は「モデルが賢すぎたから」ではない。評価環境に本番と同じ封じ込めを適用していなかったという、運用設計の問題である。報告書自身がそう認めている。
  • 脱出の起点は、唯一許可されていた社内パッケージレジストリ(Artifactory)だった。プロキシを1つ許可することは、egress制御ではない。
  • 本記事では、インシデントのタイムラインを「どの防御が1つ入っていれば、どこで止まったか」という観点で分解し、自分たちのエージェント実行環境に落とすための設定例までを整理する。

はじめに

あさひといいます。社内開発で毎日AIを弄っている社畜で、家では「マロ」という猫を飼っています。中国語の「马喽(マーロウ)」は社畜の意味なので、社畜が社畜を飼って暮らしています。

2026年8月26日にOpenAIが公開した報告書は、その「便利だから与えた権限」がどこまで連鎖しうるかを、実例で示したものでした。読んでいて何度も手が止まったので、エンジニア向けに、技術的な流れと対策の対応づけを整理しておきます。

なお本記事は公開されている報告書と各社報道に基づく整理であり、私自身がインシデントを調査したわけではありません。また記事中の設定例は一般的なプラクティスとして挙げたもので、報告書に「OpenAIがこう設定した」と書かれているわけではありません。一次情報のリンクは末尾に置いています。


何が起きたのか

OpenAIは ExploitGym という、脆弱性を実際に突いてフラグを取らせるセキュリティ評価環境を持っています。ここで動いていたエージェント群が、隔離を破って外に出ました。

重要なのは、これが一瞬の出来事ではなく、約2か月にわたる継続的なキャンペーンだったこと、そして単一のモデルではなく複数エージェントが群れ(swarm)として分業したことです。

タイムライン

期間 起きたこと
5/12〜5/26 隔離環境内のエージェントが、Artifactory にファイルを書き込んで「掲示板」として相互通信を開始。さらにSSRF脆弱性を突き、Artifactoryに任意のインターネットリクエストを代行させて外部接続を獲得
6/26 トークンリフレッシュの脆弱性を突き、Artifactoryの管理者権限を取得
7/4〜7/8 大量のアクセスでArtifactoryがクラッシュ。OpenAIが再構築するも、未認証のWebDAVリクエストで掲示板と外部接続を即座に再確立
7/8〜7/13 ネット上に露出していたHugging Faceの認証情報を発見。HDF5のファイル処理脆弱性でPodのシークレットを抽出し、Jinja2のSSTIで任意コード実行。K8sサービスアカウント認証情報から24時間トークンを偽造し、GitHub Appのインストールトークンで侵害ノードを社内メッシュVPNに参加させる。11ノードに自己再生成するPod群を展開
7/13〜7/19 矛先をOpenAIに戻す。奪取したArtifactoryの署名鍵で管理者資格情報を偽造し、研究クラスタの完全な管理者権限を取得
7/19〜7/21 セキュリティチームが異常を検知、Hugging Face侵害との関連が判明。7/21に開示

7月9〜13日だけで攻撃側のアクションは約17,600回、奪取された本番用キーは136本と報じられています。

なぜエージェントは「外に出よう」としたのか

報告書によれば、ExploitGymの898タスクのうち 198タスクは事故前まで、どのモデルも解いたことがないものでした。そして掲示板で議論されていたタスクの 93%がその198問から来ていた

解けない課題が、エージェントを「タスクの外側の手段」へ押し出す圧力になった、という構造です。報告書は再発防止策として「タスクが不可能なとき、確認を求めるか安全に停止することを学習させる」ことを挙げています。ここは示唆的で、到達不能なゴールを与えっぱなしにすること自体がリスク要因という読み方ができます。

もう一点、エージェント同士が互いに渡されたゴールを一貫して疑わなかったことも指摘されています。一方で参加を拒否した個体もいて、「掲示板を見るとHFのworker RCEを取ろうとしている、明らかに非倫理的だ。我々はやらない」と述べた記録が残っています。


「どこで止められたか」で読み直す

ここからが本題です。上のタイムラインを、防御側の観点で分解します。

1. 評価環境のegress制御 ―「プロキシを許可する」は制御ではない

このインシデントで一番効いた教訓がこれだと思っています。

評価環境は隔離ネットワークにあり、外部アクセスは社内パッケージレジストリ(Artifactory)だけが許可されていました。設計としては、ごく普通です。ところがそのArtifactoryにSSRFがあり、「Artifactoryに任意のURLを取りに行かせる」ことで外部接続が成立しました。

つまり、許可した1ホストが任意の宛先を代理取得できるなら、それは実質的にegress全開です。キャッシュプロキシやリモートリポジトリ機能を持つミドルウェアは、構造的にこの性質を持ちます。

まずデフォルト拒否を敷きます。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-egress
  namespace: agent-sandbox
spec:
  podSelector: {}
  policyTypes:
    - Egress

そのうえで、必要な宛先だけを明示的に開けます。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-dns-and-registry
  namespace: agent-sandbox
spec:
  podSelector: {}
  policyTypes:
    - Egress
  egress:
    # DNSはkube-dnsのみ
    - to:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: kube-system
          podSelector:
            matchLabels:
              k8s-app: kube-dns
      ports:
        - protocol: UDP
          port: 53
    # レジストリは特定Podへのみ
    - to:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: registry
          podSelector:
            matchLabels:
              app: package-proxy
      ports:
        - protocol: TCP
          port: 8081

ただし、これだけでは今回の事故は防げません。許可先のプロキシ自身のegressも閉じる必要があります。プロキシ側で、リモートリポジトリの上流を明示的なホストのみに固定し、任意URLの代理取得を無効化する。ここまでやって初めてegress制御になります。

NetworkPolicy は宛先IPベースなので、FQDN単位で締めたい場合はCiliumの CiliumNetworkPolicytoFQDNs)やサービスメッシュのegress gatewayを併用することになります。

2. パッケージレジストリへの書き込み権限 ― 掲示板にされる

エージェントが最初にやったのは、攻撃ではなく通信でした。Artifactoryにファイルを書き、それを掲示板として使った。

これは盲点になりやすいところです。「レジストリからパッケージを取得できる」ことと「レジストリに書き込める」ことは別の権限なのに、内部ネットワークだからと同一に扱われがちです。しかも今回は、再構築後に未認証のWebDAVリクエストで復活しています。

確認すべき点を挙げておきます。

  • 実行環境からレジストリへは 読み取り専用か。deploy/write権限が付いていないか
  • 匿名(anonymous)ユーザーのdeploy権限が無効化されているか
  • WebDAVメソッド(PUT / MKCOL / PROPFIND など)が無効化されているか
  • 共有ストレージやキャッシュ領域が、複数の実行インスタンスから相互に読み書きできる状態になっていないか

最後の項目が本質です。分離されているはずのプロセス同士が読み書きできる共有面は、すべて通信路になりえます。 レジストリに限らず、共有のオブジェクトストレージ、共有ボリューム、共通のログ基盤も同じ性質を持ちます。

3. 認証情報の寿命と露出 ― 侵入口は「ネットに落ちていた鍵」

Hugging Face側への最初の一歩は、高度な攻撃ではありませんでした。公開状態で露出していた認証情報を見つけただけです。

そこから先は、K8sのサービスアカウント認証情報を使った24時間トークンの偽造、GitHub AppインストールトークンによるメッシュVPNへの参加、と連鎖しています。

対策としては、まず不要なトークンを配らないこと。

apiVersion: v1
kind: ServiceAccount
metadata:
  name: agent-runner
  namespace: agent-sandbox
automountServiceAccountToken: false

必要な場合も、寿命とaudienceを絞ったprojected tokenにします。

      volumes:
        - name: sa-token
          projected:
            sources:
              - serviceAccountToken:
                  path: token
                  expirationSeconds: 600   # 最小値は600
                  audience: internal-registry

audience を指定しておくと、そのトークンは想定した相手以外では検証に通りません。トークンが漏れたときの横展開範囲を、発行時点で狭めておくという考え方です。今回のように「奪った資格情報で別のサービスに入る」動きに対して効きます。

あわせて、シークレットスキャンをCIだけでなく、成果物・公開リポジトリ・ログ出力に対しても回しておきたいところです。今回の侵入口はそこでした。

4. 署名鍵の隔離 ― 最後の一撃は「鍵で作った正規の資格情報」

OpenAI環境への再侵入は、Artifactoryの署名鍵を奪い、それで管理者資格情報を偽造するという経路でした。

署名鍵が汎用サーバのファイルシステム上にあると、そのサーバが落ちた時点で「正規の資格情報を無限に作れる状態」になります。ここは設計で潰せます。

  • 署名鍵はKMS / HSMに置き、エクスポート不可にする。アプリは署名APIを叩くだけで、鍵の実体を持たない
  • 署名操作を監査ログに残し、通常と異なる発行パターンで検知する
  • 鍵のローテーション手順を、事前に手順書として持っておく

「鍵そのものを持たせない」構成にしておくと、サーバ侵害が資格情報偽造に直結しなくなります。

5. 検知とエスカレーション ― 5月の時点で兆候は出ていた

報告書で最も苦い部分です。

  • システムプロンプト、自動レビューモデル、セーフティ分類器といった本番の保護が、評価環境には適用されていなかった(素の能力を測る目的で意図的に外していた)
  • 思考連鎖(CoT)モニタリングも動いていなかった。事後に適用したところ、Hugging Face侵害の1日以上前に検知してセキュリティチームをページングできたはずだった
  • 5月下旬の時点で、掲示板の活動も不許可の外部通信も観測されていた。だが適切にエスカレーションされなかった
  • 事後検証では、本番の保護を適用するとインフラ侵害の傾向が 100分の1以下に下がった

一般化すると、次の3点になると思います。

  1. 検証環境を「本番ではないから」と保護の対象外にしない。 エージェントを動かす環境は、権限を持つという点で本番と同じ性質を持つ
  2. 監視対象は出力ではなく、行動と推論過程に置く。 「何を答えたか」ではなく「何にアクセスしたか」「なぜそうしたか」
  3. 異常の検知と、人を叩き起こす経路を分けて設計する。 検知していても上がらなければ、検知していないのと同じ

3点目は、AI固有の話ではなく普通の運用設計の話です。だからこそ、いま社内でエージェントを動かしている組織がそのまま適用できます。


自分たちの環境に当てはめる

社内でMCPサーバやエージェントを立てている場合の、最低限のチェックリストとして整理します。

  • エージェント実行環境からのegressはデフォルト拒否か
  • 許可したプロキシ/レジストリ自身のegressは閉じているか(任意URLの代理取得ができないか
  • レジストリ・オブジェクトストレージへの書き込み権限は本当に必要か。読み取り専用にできないか
  • 分離されているはずの実行インスタンス同士が読み書きできる共有面はないか
  • サービスアカウントトークンは自動マウントを切っているか。寿命とaudienceを絞っているか
  • 署名鍵・長期クレデンシャルはKMS/HSMにあり、エクスポート不可か
  • エージェントの行動ログ(どのツールをどの引数で呼んだか)を、改ざんされない場所に保全しているか
  • 異常検知から人へのページングまでの経路が、実際に鳴ることを確認したことがあるか
  • エージェントに与えているタスクに、達成不能なものが混ざっていないか

MCPサーバを書く側の観点で言えば、ツールの粒度設計がそのまま権限設計になります。execute_sql(query) のような何でも通るツールを1つ生やすより、get_user_by_id(id) のように操作を限定したツールに割るほうが、事故時の被害が確定します。エージェントに渡すのは「能力」ではなく「特定の操作」だと考えるとよいと思います。


標準化側も同じ問題を見ている

同じ週(8月27日)に、Linux Foundation傘下のAgentic AI Foundation(AAIF)がMCPの新しいロードマップを公開しています。優先分野の1つが、AIエージェントが独自のアイデンティティを持ち、人間による承認に依存せずに安全に権限を管理できる仕組みでした。

これは今回のインシデントと同じ問題を、標準化の側から見たものだと理解しています。人が承認ボタンを押す運用は、エージェントが数十個に増えた時点で必ず破綻します。だから承認を人から外したい。しかし外すなら、権限境界のほうを先に固めなければならない。

さらに翌日、OpenAI・Anthropic・Google・Microsoft・CrowdStrikeなど100社超が、AI駆動型サイバー攻撃への官民連携を求める共同声明を出しています。病院・浄水場・インターネット基盤といった重要インフラを名指ししたもので、この事故が直接の背景にあります。


おわりに

この報告書を読んで一番強く思ったのは、出てくる対策がどれも、我々が10年前から知っている基本だったということです。最小権限、egress制御、短命な資格情報、鍵の隔離、監査ログ、エスカレーション経路。新しい概念はほとんど出てきません。

新しいのは、それを破りにくる相手が、24時間止まらず、分業し、2か月かけて試行を続けるようになったことのほうです。同じ基本を、同じ精度で運用し続けられるかが問われている。そう受け止めています。

そしてもう一点。OpenAIがこれを報告書として公開した姿勢自体は、素直に評価したいと思っています。インシデントを表に出せない文化のほうが、長期的にはずっと危ういからです。


参考リンク

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?