
生成AIを使ったソフトウェア開発のセキュリティの問題点について整理してみた
AI事業本部の山本です。
世の中の潮流にのり、ソフトウェア開発で生成AIを使っています。もはや手でコードを打つことはほぼなくなってきてしまいました。
さらに、半自動的にAIを実行できる設定も出てきて、ほぼ全自動でコードを生成できるようになり、すごいなぁと思う日々です。
ただ、利用するにあたり、この方法で進めても安全なのかということを疑問に思うようになり、今回の記事を書くに至りました。
1. はじめに
1.1 背景・動機
生成AIを使った自律的なソフトウェア開発が急速に普及しています。
コードを書く、テストを実行する、プルリクエスト(PR)を作る、ドキュメントを更新する、といった作業を、AIが自律的に担っています。
しかし、AIが自律的にコードを実行・変更する環境では、従来のセキュリティの前提が通用しない場面があります。
本記事ではその点について、実際に使ってきた体験から考えてきたことを整理して記載します。
なお、本記事ではClaude CodeやAWSを具体例として扱いますが、ここで議論する内容は、他のAI開発ツール(Cursor、GitHub Copilot等)や他のクラウドサービス(Google Cloud、Azure等)にも同様に当てはまります(詳細は 補足:他のAI開発ツール・他クラウドへの当てはまり を参照)。
1.2 対象読者
- AIエージェントを使ったソフトウェア開発に取り組んでいるエンジニア
- Claude CodeなどのAIツールをチームに導入しようとしている開発者・マネージャー
- AIの活用とセキュリティのバランスに悩んでいる人・情報システム部門の方
1.3 本記事における用語
本記事では、以下のように用語を使い分けます。
- 生成AI / AI:ソフトウェア開発に用いる生成AI全般を指す総称
- AIエージェント:生成AIに自律的にタスク(コード変更、コマンド実行、外部リソースへのアクセス等)を実行させるソフトウェア(Claude Code、Cursor、Devin 等)。本記事では、システム全体の挙動や権限・運用について述べるときに使う
- モデル:AIエージェントの中核となる、生成AIの推論を行う部分。現在は大規模言語モデル(LLM:Large Language Model)が用いられる。本記事では、推論そのものの挙動や脆弱性について述べるときに使う
1.4 本記事の位置づけ
本記事は、生成AIを使ったソフトウェア開発におけるセキュリティに関して、現状の問題や課題感について記載したものです。
セキュリティに関して要件を整理したり、その問題点に対して対策を検討することについては、次回以降の記事で扱う予定です。
なお、本記事で扱うセキュリティは、世の中で語られる「ハーネスエンジニアリング」とは別の話です(詳細は 補足:ハーネスエンジニアリングとの違い を参照)。
1.5 注意事項
筆者はセキュリティの専門家ではなく、記載している内容が誤っている可能性があります。
クラスメソッド社内で実施しているセキュリティ対策を記載したものではありません。
また、クラスメソッドの情報システム部門やセキュリティメンバーに意見をいただいてはいるものの、完全なレビューを受けたものではありません。
あくまで、筆者が把握している情報を、自分なりに整理したものです。
本記事には外部サイトへのリンクを記載していますが、外部サイトの情報が本当に正しいかどうかのチェックまではできていません。特に補足に記載した内容は、AIに記載させている部分も多いです。
本記事の内容を利用いただく際には、ご注意ください。
2. AI開発におけるセキュリティの基本的な考え方
本記事で前提となる考え方を、最初に整理します。
2.1 セキュリティは「守る」と「促進する」の両方で考える
セキュリティ対策というと、操作を禁止したり権限を絞ったりといった「守る」側が注目されがちです。
しかし、セキュリティ全般で議論されてきたとおり、「守る」と「促進する(許可する・便利に使えるようにする)」の両立を考える必要があります。
AIを使ったソフトウェア開発のセキュリティでも同様です。この両立がより重くなります。
なぜなら、AIに任せる範囲・権限を過度に絞ると、AIの能力を活かしきれず、効率や成果物の質が落ち、結果として開発の競争力を失うためです。
「守る」だけを突き詰めると、極端には「AIに何もさせない(= 最も安全)」が最適解になってしまい、AIを使う目的そのものが失われます。
このため、AIを大規模に・広い裁量で使えるようにしながら、その上で安全性を担保する設計が必要になります。
セキュリティ対策は、この両立を前提として考える必要があります。
2.2 現状のAI開発には、運用の方向性が2つある
実際の運用を想定すると、AIに任せる範囲・権限の与え方には、大きく2つの方向性があります。
方向性A:AIに任せる範囲を小さく限定する
AIに与える裁量・権限を狭く絞り、人間が逐一確認しながら使うアプローチです。
具体例として、以下のような運用が挙げられます。
- AIの変更先をローカルファイル(あるいは特定のディレクトリ)の範囲のみに限定する
- 厳格なホワイトリストで、許可するコマンドを最小限に絞る
- すべての操作を人間が逐一確認・承認する
- 「気をつけて確認する」「ベテランが丁寧にレビューする」といった注意力で防ぐ(ある種の根性論)
これらは、小規模・少数のAIを使う現状では合理的に機能している選択肢です。
ただし、後述するとおり、AIに任せるタスクの範囲・権限・並列度は今後拡大していきます。
今後の拡大に対応せず、小さい範囲でAIを使い続けるのであれば、方向性Aは引き続き成立します。
一方で、AIの活用範囲を広げていこうとする場合、方向性Aの運用はいずれ限界を迎えると考えられます。
方向性B:AIに広い裁量を与えつつ、仕組みで安全性を担保する
AIに任せる範囲を狭めるのではなく、広い裁量を前提として、実行環境・権限制御・隔離などの仕組みで安全性を担保するアプローチです。
「AIに何をさせないか」を厳しく定義していくのではなく、「AIに自由に動いてもらいつつ、危険な操作だけは確定的に止める」ことを目指します。
これにより、AIの効率と安全性を両立させやすくなります。
2つの方向性の差は、AIの並列度や運用期間が拡大したときに顕著になります(拡大の詳細は「3. 状況」で述べます)。
方向性Aは、AI1体ごとに人間が確認するため、並列度が増えると承認が追いつかなくなります。
方向性Bは、仕組みが全AIに機械的に同じ枠を適用するため、並列度が増えても枠は変わりません。
2.3 本記事の立場
本記事は、今後AIに任せる範囲・権限・並列度が拡大していくことを前提とします。
この前提では、方向性Aは今後成立しなくなるため、方向性Bを実現するための設計を考える必要があります。
次節以降では、以下の流れで議論を進めます。
- 方向性Bを採る必要があるのは、AIに任せる範囲・権限・並列度が拡大していくためであることを示す(3節)
- もう一つの前提として、生成AIモデル自体が脆弱であり、モデル内では安全性を担保しきれないことを示す(4節)
- 個別の対策(人間による全承認、AIによるコマンドチェック、ブラックリスト、ホワイトリスト、ドメイン制限)が、それぞれ単独では不十分であることを示す(6節)
- 方向性Bを実現するための対策の方向性を示す(7節)
3. 状況:AIエージェントの規模・権限が拡大している
3.1 AIに任せるタスクの範囲が広がっている
現状では、AIには明確に指示した個別のタスクを任せるのが一般的です。
しかし、今後、AIに任せるタスクの種類は広がっていくと考えられます。
「指定したコマンドだけ実行する」のような限定された使い方から、「目的を伝えれば、必要なコマンドを自分で判断して実行する」ような広範な裁量を持つ使い方へと、既に移り変わってきています。今後この流れはさらに広がっていくと考えられます。
そのため、AIに任せる範囲を狭く固定する運用は、現実的でなくなっていくと考えられます。
3.2 AIエージェントに与える権限が拡大している
AIに任せるタスクが広がるのに伴い、AIに与える権限もどんどん大きくなっており、コードの変更、コマンドの実行、外部リソースへのアクセスなど、人間の開発者と同等レベルの権限を持つようになってきています。
何も対策せずにこの状態で問題が起きると、被害が大きくなります。
攻撃者が乗っ取ったAIエージェント1台だけでも、ファイルの破壊、機密情報の漏洩、本番環境への不正な変更といった、深刻な事態を引き起こす可能性があります。
3.3 大量並列運用が普及しつつある
現状では、AIエージェントを少数(多くて10程度)動かし、人間が逐一確認しながら使うのが一般的です。
しかし、今後、ソフトウェア開発において生成AIを使うことが標準的になり、大量並列で稼働させる場面が増えていくと考えられます。
例えば、100体のAIエージェントが100並列で24時間動き続け、さらにそのエージェントが別のエージェントやエージェントチームを呼び出してタスクを実行させる、といった環境です。
これは将来の仮定ではなく、既に進みつつある方向です(詳細は 補足:大量並列運用の実例 を参照)。
こうした状況では、1回あたりに脆弱性が発現する確率がたとえ低くても、実行回数の多さによって確実にどこかで問題が発生します。
このように、AIに任せるタスクの範囲、与える権限、そして大量並列運用のいずれもが拡大していくなかで、セキュリティ事故は発生しやすくなり、事故が起きたときの被害も大きくなってきています。
将来の運用規模・権限の大きさを見据えて、対策を整える必要があります。
4. 前提:モデルは「脆弱」である
4.1 モデルは外部から挙動を操作されうる
生成AIモデルは、外部からの入力や学習データを通じて、挙動を操作される可能性があります。
攻撃経路は大きく2種類です。
プロンプトインジェクション(推論時の攻撃)
AIが読み込む入力(ソースコード、ドキュメント、Web情報等)に、悪意ある指示を混ぜ込む攻撃です。
AIが取り込むあらゆる入力が、攻撃の入り口になり得ます(実例は 補足:プロンプトインジェクションとデータポイズニングの実例 を参照)。
データポイズニング(学習時の攻撃)
モデルを訓練した際の学習データに、特定の挙動を誘発するパターンを混ぜ込む攻撃です。
モデル供給元の管理やモデルカードの確認といった対策はあるものの、学習データそのものに汚染が混入していないかを利用者側で確証する手段は限られます(実例は 補足:プロンプトインジェクションとデータポイズニングの実例 を参照)。
これらの攻撃を、利用者側で完全に防ぎきることは困難です。
プロンプトインジェクションについては、AIが外部から情報を受け取り始めた時点で、取り込む入力すべてを事前に検査することは現実的に不可能になります。Webページ、外部のドキュメントやコードなど、情報の取得元は多岐にわたります。
また、データポイズニングについては、学習データそのものへの汚染を利用者側で確証する手段がないと言えます。
よって、モデルは外部からの入力や学習データによって、攻撃者の意図どおりに挙動を変えられる(= 乗っ取られる)可能性があるという前提に立つ必要があります。
なお、これらの攻撃はOWASP Top 10 for LLM Applicationsでも、LLM01: Prompt Injection、LLM04: Data and Model Poisoningとして挙げられています。
4.2 確率的な脆弱性は防げない
生成AIモデルは、入力のちょっとした違いで挙動が大きく変わることがあります。
ある入力に対して安全に動作したからといって、ほぼ同じ別の入力に対しても安全に動作するとは限りません。
言い回しや前後の文脈が少し違うだけで、ある入力では安全のための指示を守るのに、別の入力では同じ指示を破ってしまう、ということが起こりえます。
これは、生成AIモデル(LLM)の仕組みに由来します。
LLMは、入力されたトークン列全体から次のトークンの確率分布を計算し、その分布に従ってトークンを1つずつ選んで出力します。
安全のためのシステムプロンプトも、ユーザーの指示も、外部から取り込んだ文書も、すべて同じトークン列の一部として処理され、それぞれの重みは入力全体の文脈によって変動します。
そのため、入力にわずかな違いが加わるだけでも内部の確率分布が大きく変わり、出力される挙動も大きく変わりえます(temperature=0 でも完全な決定論にはならない理由は 補足:temperature=0 でも決定論的にならない理由 を参照)。
攻撃者の視点では、Webページやドキュメントなどに罠を仕込んでおけば、それを取り込んだAIエージェントのどこかで安全のための指示が破られる、という確率的な攻撃が成立する、ということを意味します。
AIエージェントの大量並列運用(3.3)が進むほど、1回あたりの発火確率が低くても、どこかで確実に踏まれる構造になります。
このため、安全のためのシステムプロンプトや指示を組み込んでも、悪意ある入力があった場合や悪意のある学習データに従ってしまった場合、確率的に安全のための指示を破ってしまう可能性があります。
そして、この確率をゼロにする手段は現時点では存在しません。
以上の理由から、モデル自体で安全性を担保する設計は成立しません。
モデルの外側、つまり実行環境で安全性を担保する設計が必要です。
4.3 人間を前提にした対策との違い
セキュリティ対策の多くは、操作するのが人間であることを前提に組み立てられてきました。人間も判断を誤り、だまされることはありますが、誤りを減らす教育があり、最終的に責任を負う人がいることが、「信頼の根拠」になっていると言える状況です。
AIエージェントには、この信頼の根拠がそのまま当てはまるとは言えません。4.1・4.2 で見たように、外部の入力に仕込まれた指示で挙動を乗っ取られ、それを確率的に防げないからです。
このため、人間が操作することを前提に作られた対策をそのままAIに当てはめると、その対策が前提としていた想定が成り立たなくなります。たとえば、自社のデータを外部のアカウントやリソースへ送るような操作は、人間の操作者であればまず自分からは行わないなど、多くの対策はこうした人間の動きを前提にしています。しかし、AIエージェントは、入力に紛れ込んだ指示によって、そうした操作に誘導される可能性が残ってしまいます。6 節では、個々の対策が、AIエージェントに対しては単独では十分に機能しないことを、対策ごとに取り上げます。
5. Claude Codeのセキュリティ機能の概要
Claude Code を具体例として扱うため、関連するセキュリティ機能を以下に簡潔に示します。
個々の機能と settings.json・Sandbox・devcontainer の関係性は、補足:Claude Codeのセキュリティ機能の構造 を参照してください。
設定ベースの制御から、実行時の検査、OS・ネットワーク・外部接続の境界制御へと、層の内側から外側に向かって並べます。
- permissions 設定:
.claude/settings.jsonのpermissionsセクションで、ツール・コマンド・ファイルパスの実行可否を定義する(allow/deny/askの3種類) - 権限モード:人間に確認を求めるモードと、AIが自律的に実行するモードを切り替える(
default/acceptEdits/plan/auto/dontAsk/bypassPermissions) - hooks:ツール実行の前後や特定イベント(
PreToolUse/PostToolUse/Stop等)で、外部スクリプトを差し込んで操作の検証や事後処理を行う - auto mode:実行しようとしたコマンドを、チェック専用のAIが自動判定する
- Sandbox:Bashツール経由のサブプロセスを OS レベルで隔離する
- ドメイン制限:Sandbox(内蔵のproxy server経由)、devcontainer、外部 proxy 等を通じて、AIがアクセスできるドメインを制限する
- MCP 接続の管理:接続する MCP サーバを限定することで、外部ツール経由の操作範囲を制御する
これらの機能は、AIが操作を実行しようとしてから外部へ到達するまでの、それぞれ異なる段階で効きます。
これらの機能はそれぞれ有効ですが、設定や考え方を誤ると抜け穴・迂回路ができます。
次節では、不十分な使い方・考え方の例を記載します。
6. 単独では不十分な対策・考え方の例
以下に挙げる対策は、それ自体は有効です。
ただし 2.2 で述べた 方向性B(AIに広い裁量を与えつつ仕組みで安全性を担保する) を採ろうとするときに、これらの対策を単独で完結させようとすると、規模拡大時の破綻、確率的なすり抜け、迂回路、スコープの狭さ、クロスアカウント漏洩、量・回数の暴走による運用・コストの破綻のいずれかが残ります。
具体的な内容を、対策ごとに以下で示します。
6.1 不十分な例1:人間がすべての操作を承認する
AIエージェントが実行するコマンドを、人間が逐一確認・承認すれば安全だ、というアプローチです。
小規模な開発であれば成立するように見えますが、高い能力や知識がないと複雑な操作を正しく判定できないことと、承認疲れによって判断が劣化しうることの2点から、現実的にはうまく機能しません。
人間が正しく判定できる人が限られる
複雑なコマンドや、長いスクリプトを実行する処理を、毎回正しく承認できる人は限られます。
コマンドの引数や環境変数を一つひとつ吟味し、副作用がないかを確認するには、攻撃手法やシステム挙動への一定の知識が必要であり、対応できるレビュアーは限られます。
承認疲れによって判断が劣化する
実行のたびに承認を求められる状況が続くと、人間は次第に内容を確認せずに承認するようになります(いわゆる「承認疲れ」)。
最初は慎重に確認していても、安全な操作が大半を占めると、判断が形骸化し、危険なコマンドも見逃しやすくなります。
このため、人間による承認だけに頼るアプローチは、規模が大きくなったり期間が長くなったりするほど機能しなくなります。
6.2 不十分な例2:AIにコマンドの安全性をチェックさせる
「AIに、別のAIが実行しようとしたコマンドの安全性を判断させれば、人間が確認しなくても安全だ」という考え方は、よくある誤解です。
Claude Codeのauto modeは、AIが実行しようとしたコマンドを、チェック専用のAI(classifier model)が判断して実行可否を決める仕組みで、これに該当しますが、以下に注意しなければいけません。
そもそもauto modeは「セキュリティ機能」として提供されていない
auto modeについて、Anthropic自身が公式ドキュメントで以下のように明記しています。
Auto mode is a research preview. It reduces prompts but does not guarantee safety. Use it for tasks where you trust the general direction, not as a replacement for review on sensitive operations.
(auto modeはresearch previewである。プロンプト数を減らすが、safetyを保証するものではない。全体的な方向性を信頼できるタスクに使うものであり、sensitive operationsのreviewの代替ではない)
つまり、auto modeは安全性を担保するための機能ではなく、利便性向上(プロンプト疲れ・承認オーバーヘッドの軽減)のための機能として位置付けられています。
公式は、使ってよい前提として「全体的な方向性を信頼できるタスク」に限定しており、「sensitive operationsのreviewの代替」にはならないと明示しています。
チェック専用のAIも確率的に誤る
そもそもの話として、モデルは確率的に誤ります。
チェック専用のAIも例外ではなく、誤判定する可能性があります。
Anthropicの公式エンジニアリング記事によると、社内データを用いた評価でも、チェック専用のAIが「危険な操作」を見逃す確率(False Negative Rate)は、実環境のデータで17%、合成データのexfiltrationで**5.7%**と報告されています(出典:Anthropic engineering: Claude Code auto mode。評価セットの定義は 補足:auto mode の False Negative Rate の評価条件 を参照)。
大量並列でAIを動かす環境では、この見逃し確率が積み重なり、確実にすり抜けが発生することが考えられます。
Anthropic公式ドキュメントにも、セキュリティ対策の組み合わせの考え方が明記されています。
Sandboxing and permissions are complementary security layers that work together
(Sandboxとpermissionsは、互いに補完的なセキュリティ層であり、組み合わせて機能する)
このため、auto modeも単体で完結する防御として使うのではなく、Sandboxやdevcontainer等の他の対策と組み合わせて運用することが必要です。
6.3 不十分な例3:コマンドのブラックリストを定義する
permissions設定で危険なコマンドをdenyに列挙する、いわゆるブラックリスト方式のアプローチです。
例(.claude/settings.json):
{
"permissions": {
"deny": [
"Bash(rm:*)",
"Bash(curl:*)"
]
}
}
しかし、ブラックリスト方式で個別の操作を禁止しても、等価な処理を別の経路で実行する迂回路は無数にあり、列挙しきれません。
例えば:
rmコマンドをdenyしても、Pythonスクリプトにos.remove(...)と書いて実行されるrmコマンドをdenyしても、find . -deleteや> file(リダイレクトでファイル内容を空にする)といった別コマンドで同じ結果を達成できる
これらの迂回経路(Pythonスクリプトの編集・実行や、findコマンドの実行など)は、allowに明示されていなければ実行時に承認が求められます(ask)。
しかし、長いスクリプトや一見無害に見えるコマンドの中に破壊的な操作が紛れていると、承認する人間が見逃す可能性があります(6.1で述べた承認疲れや判定の劣化と同じ問題です)。
ブラックリスト方式は、攻撃者(あるいは確率的に誤動作するAI)が思いつくあらゆる迂回路を網羅する必要がありますが、現実的にはすべてを列挙しきれず、安全とは言えません。
このため、許可されたもの以外をすべて拒否するホワイトリスト方式で設計するほうが安全です。
ただし、ホワイトリスト方式にも別の問題があります(次項)。
6.4 不十分な例4:コマンドのホワイトリストを定義する
permissions設定で必要なコマンドだけをallowに列挙し、それ以外をすべて拒否する、いわゆるホワイトリスト方式のアプローチです。
Claude Codeでのホワイトリスト方式の実現方法
Claude Codeのデフォルト(defaultモード)では、Bashコマンドはallowに明示されたものだけが自動許可され、それ以外は実行のたびにユーザーに確認が求められます(読み取り専用のコマンドを除く)。
つまり、デフォルトでもallowに書いた以外のコマンドは人間の承認を経るため、形式的にはホワイトリスト方式が成立しているように見えます。
しかし、この運用では人間の承認が頻繁に発生してしまうため、6.1で述べたのと同じ問題(承認疲れ、判定の劣化)に陥ります。
そこで、人間に確認を求めず「allowに明示されていない操作は自動的に拒否する」モードとして、dontAskモードが用意されています。
dontAskモードを設定し、必要なコマンドだけをallowに列挙することで、ホワイトリスト方式を非対話的に実現できます。
例(.claude/settings.json):
{
"permissions": {
"defaultMode": "dontAsk",
"allow": [
"Bash(npm test:*)",
"Bash(npm run build:*)",
"Read(./src/**)"
]
}
}
または、起動時に指定します。
claude --permission-mode dontAsk
dontAskモードでは、allowに明示されていない操作は自動的に拒否されます。
なお、permissionsのルールは「deny → ask → allow」の順で評価されるため、denyを使ったブラックリスト方式にallowの例外を組み合わせても、denyが先にマッチして例外が機能しません(詳細は 補足:permissionsの優先順位は「deny → ask → allow」 を参照)。
ホワイトリスト方式の限界
ホワイトリスト方式は、未許可の操作を拒否する点では有効ですが、許可したコマンドの内部挙動までは保証しません。
たとえば Bash(npm test:*) を許可したら、リポジトリ内の package.json やテストスクリプトが書き換えられていた場合、許可リストの内側で破壊的な処理が走り得ます。
加えて、これは「AIに任せる範囲を狭く定義し、その中だけでAIを動かす」発想、つまり 2.2 で述べた方向性Aに立つアプローチです。
「3. 状況」で述べたとおり、AIに任せるタスクの範囲は今後広がります。
方向性Bを採ろうとするときには、ホワイトリスト方式だけで対応するのは現実的でなくなっていくと考えられます。
このため、ホワイトリスト方式は方向性Aに留まる対策と位置づけ、方向性Bでは他のレイヤと組み合わせて使う前提で扱う必要があります。
hooksによる事前パターンチェックも同じ限界を持つ
permissions 設定の代わりに、PreToolUse hooks 内で「実行しようとしているコマンドが事前定義したパターンに合致するか」をスクリプトで判定する方式も考えられます。
ただしこれは実装手段が違うだけで、許可パターンを列挙して評価するという構造はホワイトリスト方式と同じです。
パターンの網羅が現実的でない、パターンの隙間を縫う迂回路がある、AIに任せる範囲を狭く固定する発想に立つ、という限界も共通します。
6.5 不十分な例5:アクセスできるドメインを制限する
サンドボックスやdevcontainer環境で、AIエージェントがアクセスできるドメインを制限しているとします。
しかし、利用しているサービスによっては、許可しているドメインの中で、攻撃者が用意したアカウント・リソースにリクエストを送られ、情報を漏洩させられる可能性があります。
ドメイン単位で制限しても、許可ドメインの内側に攻撃者が用意したアカウントがあれば、そこへの通信は遮断されません。
攻撃成立条件の緩い順に、2パターンが考えられます。
(1) リクエスト埋め込み型(自アカウントの認証情報のまま、攻撃者リソースにリクエストを送らせる)
この経路は、さらに「AWS API 経由」と「自分のAWSリソースを踏み台にする経路」の2系統に分けて考える必要があります。
(1-a) AWS API 経由で攻撃者所有のAWSリソースを操作する経路
*.amazonaws.com を許可している環境で、AIに AWS API を呼び出させ、攻撃者保有のS3バケットやSQSなどのAWSリソースにリクエストを送らせる経路です。
リクエストパラメータ(クエリ文字列、リクエストボディ、ヘッダ等)に秘密情報を埋め込めるため、AccessDenied で拒否されても攻撃者バケットのサーバーアクセスログから情報を取得できます(既知の手法:S3 Server Access Loggingを使ったクロスアカウント漏洩)。
この経路は、IAMポリシーで条件キー aws:ResourceAccount(自アカウント外のリソースへの操作を拒否)や aws:ResourceOrgID(自Organization外のリソースへの操作を拒否)を設定すれば塞げます。これらの条件キーは、AWS API 呼び出しの認可評価で「操作対象リソースの所有アカウント」を見るため、攻撃者所有のリソース(他アカウント・自Organization外)への AWS API 呼び出しは AWS 側の認可で拒否されます。
(1-b) 自分(被攻撃者)のAWSリソースを踏み台にして漏洩させる経路
(1-a) を IAM 条件キーで塞いでも、別の経路が残ります。
AIに「自分のアカウント内の AWSリソース」を作成・操作させ、そのリソースを踏み台にして情報を漏洩させる経路です。
踏み台にされたリソースからの漏洩は、攻撃者がデータを受け取る方法によって2つのサブケースに分かれます。
push 型
AIに自アカウントの EC2 / Lambda などのリソースを作成・操作させ、そのリソースから外部ドメインへ HTTP リクエストを送信させる経路です。
これは AWS API 呼び出しではなくリソース上のネットワーク通信であり、IAM の aws:ResourceAccount 等は適用されません(攻撃が成立する点は従来どおりです)。
この経路を塞ぐには、IAMの権限設定、デプロイするリソースの設定を人手で確認する、AWSリソースのネットワーク egress 制御(VPC endpoint policy、egress プロキシ、セキュリティグループ等)など、別の層として用意する必要があります。
公開設定型
AIに S3 バケットなどのリソースを公開設定に変更させる経路です。
攻撃者は公開されたリソースからデータを外部から取得すればよく、公開設定にさせた時点で攻撃者の目的(情報の取得)が達成されます。
この場合、被攻撃者側のリソースから外向きの通信は発生しません。
そのため、push 型を塞ぐための egress 制御では防げず、リソースを公開設定に変更させないこと自体を別の層として用意する必要があります。
このように、(1-b) はサブケースごとに塞ぐ層が別物です。
push 型はリソースからの外向き通信を制御する層、公開設定型はリソースの公開化を防ぐ層が必要であり、どちらか一方だけでは (1-b) 全体を塞げません。
いずれのサブケースについても、具体的な構成は本記事のスコープ外で、次回以降に取り上げます。
(2) 認証情報差し替え型(攻撃者の認証情報を使うようAIに指示させる)
(1) に対して IAM の対策(aws:ResourceAccount 等)を入れて、自アカウントの認証情報経由のクロスアカウント漏洩を塞いだとしても、別の経路が残ります。
それが、生成AIに 攻撃者が用意した認証情報(攻撃者の APIキーや IAM アクセスキー等)を使わせる 経路です。
AIが使う認証情報自体が攻撃者アカウントのものになるため、自分のアカウントのIAMポリシーは適用されず、ドメイン制限・IAM のいずれもすり抜けてクロスアカウント漏洩が成立します。
Anthropic API ではすでに実例があり(Claude Pirate、2025年10月)、攻撃者のAPIキーを環境変数等に設定させてAnthropic Files API へ自分のデータをアップロードさせる手口が報告されています。
AWS API でも同じ構造の攻撃が成立しうるため、認証情報の保護や、宛先アカウント識別ベースのフィルタなど、別の層を併用する必要があります(攻撃手口の詳細は 補足:クロスアカウント漏洩の手口 を参照)。
この構造は、同じドメインの中で複数の利用者がリソースを持つSaaS全般で成立します。
AWSやAnthropic APIに限らず、同一のホスト名空間を多数の利用者で共有しているSaaS(クラウドストレージ、メッセージングAPI、生成AIプロバイダ等)であれば、ドメイン単位の制限だけでは自分・攻撃者の宛先を区別できず、同じ構造のクロスアカウント漏洩が起こり得ます。
そして、この攻撃を防ぐ責任は、SaaS提供側ではなく、生成AIを利用する側にあると考える必要があります。
SaaS側がアカウント単位で経路を分離してくれれば利用者の負担は軽くなりますが(補足:クロスアカウント漏洩の手口「サービス側への期待」を参照)、現状、全SaaS・Webサービスに共通する標準にはなっていません。
現状の仕様で漏洩が成立する以上、認証情報の保護や宛先アカウント識別ベースのフィルタなど、別の層を組み合わせて防ぐ責任は利用者側にあります。
6.6 不十分な例6:アクセス先・操作の種類・権限だけを絞る(量・回数を縛らない)
許可する操作の種類や権限を 6.3 / 6.4 や権限設計で適切に絞れば十分だ、という考え方です。
個々の操作が妥当かどうかだけを見れば、危険な操作は通らないように見えますが、操作1回ごとの妥当性を保証しても、その操作を AI が大量・反復実行したときの被害は抑えられません。
1回ごとに正当な操作でも、反復・大量実行で運用・コスト・可用性が破綻する
ここで起きるのは、セキュリティ上の情報漏洩ではなく、運用・コスト・可用性の被害です。
1回1回が完全に正当で、許可された範囲内の操作であっても、AI がそれを大量・反復実行すると、次のような形で破綻します。
- レート制限やクォータが枯渇し、同じ枠を使う他の正規の作業が止まる
- 従量課金(API のトークン料金、リソース起動コスト)が想定を超えて膨らむ
例えば、Anthropic API への大量リクエストや「100万回〜せよ」といった指示によってレート制限を超過し、同じ API キーを使う他の処理が止まったり、トークン課金が膨らんだりします。
EC2 などのリソースを反復起動させれば、起動自体は許可された操作であっても、起動回数に比例して費用が増えます。
これらはいずれも、操作の種類や権限を絞るだけでは防げません。許可された操作を、許可された範囲で、ただ大量に繰り返すだけで成立するからです。
確率的なすり抜け(4.2 / 3.3)とは独立した観点である
4.2 や 3.3 で述べたのは、1回あたりの発火確率が低くても、実行回数が多ければどこかで確実に安全のための指示がすり抜ける、という確率的な構造でした。
6.6 で述べる破綻は、これとは独立した別の観点です。
モデルの誤動作も、攻撃者の関与も必要ありません。
すべての操作が正当なまま、決定論的に、ただ反復・大量実行されるだけで運用面の被害が発生します。
このため、操作の種類・権限を絞る対策とは別に、実行できる回数や量を絞る対策を独立して用意する必要があります。
レート制限・量的上限・連続実行の検知といった具体的な構成は、本記事のスコープ外で、次回以降に取り上げます。
7. 対策の方向性:モデルの判断を信用しない
7.1 基本原則
モデルは確率的に脆弱です。
したがって、モデル自身の判断にセキュリティを委ねず、モデルの外側にある確定的な仕組みで制御することが必要だと考えられます。
7.2 現状の運用と、これからの方向性
「モデルの判断を信用しない」を出発点にすると、現実的な選択肢は「人間が逐一確認するか」「役割分担を設計して自動化するか」のどちらかになります。
これは 2.2 で示した方向性A・方向性Bにそれぞれ対応します。
現状の運用:人間による逐一確認で範囲を絞る(方向性Aを堅持する)
現状の運用では、生成AIに任せるタスクを少数に絞り、AIが実行する各コマンドを人間が確認・承認しながら進める形が一般的です。
これは 6.1 で述べた「人間の全承認だけに頼る運用」と同じ仕組みですが、範囲・期間を限定することで、承認疲れによる判断劣化を抑え、現実に機能する選択肢として成立しています。
ただし「3. 状況」で述べたとおり、AIに任せるタスクの範囲・権限・並列度は今後拡大すると考えられます。
拡大した規模を人間の逐一確認だけで支え続けるのは、規模・期間の両面で困難です。
これからの方向性:役割分担+自動化(方向性Bに移行する)
生成AIに任せても良い部分と、人間(または専用の検証手段)が確認する部分の役割分担を明確にし、AIに任せられる部分はほぼ全自動で実行します。
大規模・並列運用に対応できる一方、役割分担の設計や検証手段の整備が必要です。
役割分担は、外側から内側への階層で整理できます。
- 仕組みで境界を作る:ポリシー・サンドボックス・IAM などで、そもそも実行可能な範囲を機械的に制約する
- 人間が権限を与える:仕組みの境界の中で、AI に何を任せるかを設計し、影響が大きい操作については個別に承認する
- AI が判断する:人間が与えた権限の範囲内で、個々のタスクをどう実行するかを判断する
今後の運用に向けては、この役割分担+自動化をどう実現するかを考えていく必要があります。
なお、この「役割分担+自動化」をさらに進めた運用として、タスクごとのサンドボックス設定や、承認役自体をAIが担う方向もありえます(補足:今後予想される運用の方式 を参照)。
7.3 対策の具体化に向けた検討
ここまで述べてきたように、生成AIを用いて大規模にソフトウェア開発を実施していく(= 方向性Bを実現する)には、モデル外の確定的な仕組みを実際に組み立て、具体的な対策に落とし込む必要があります。
考え方として、NIST Cybersecurity Framework の枠組みに沿って順序だてて検討していきます。
NIST CSF は、サイバーセキュリティの取り組みを、以下の6つの機能で整理した枠組みです。5つの機能に加えて、ガバナンスが全体に関わっているという構造です。
- 特定(Identify):守るべき資産・リスク・脆弱性を洗い出し、何を対象に守るかを明らかにする
- 防御(Protect):洗い出した対象に対して、攻撃の成立を抑える保護策を講じる
- 検知(Detect):攻撃や異常をできるだけ早く発見し、分析する仕組みを整える
- 対応(Respond):検知した事象に対して、被害を抑えるための対処を行う
- 復旧(Recover):影響を受けた資産・機能を回復し、再発防止につなげる
- ガバナンス(Govern):上記の取り組みを支えるリスク管理戦略・ポリシー・役割を確立し、監督する
現状では、個別の対策の解説はあるものの、そもそも生成AIを使ってソフトウェア開発のセキュリティ面に関して、守るべき対象を特定することや(Identify)取るべき対策を決めることを(Protect)、体系立てて網羅的に整理されている情報が少ない状況です。また、体系立てて整理した対策をもとに、各ツールやサービスで設定する際に、具体的にどのような形にすればよいのか、テンプレートや参考になる事例も乏しい状況です。(筆者の認識です)
まずは、IdentifyとProtectに取り組むことで、AIエージェントを広い裁量・大規模並列で運用しても安全な状態を実現するための土台、つまり「何を守るのか」「どう守るのか」を AIエージェント向けに体系立てて整理したベースを作ることを目指します。
次回以降の記事では、特定(Identify)と防御(Protect)の2機能を中心に検討を進めていきます。検知(Detect)以降は、ここで整えた土台の上で初めて意味を持つため、別のテーマとして切り分けて扱う想定です。
そして、この検討にあたって重要になるのが、複数の対策を独立した形で組み合わせて守る という発想です。
6節 で見たとおり、個々の対策は単独では不十分です。これらを単に並列に並べるのではなく、同じ前提に依存しない対策を重ねて、ある対策が破られても別の対策で止められる構成を目指す必要があります。
(どのような対策をどう組み合わせるかは、次回以降の記事で具体的に扱いたいと思っています)
また、防御(Protect)として「何を絞るか」を具体化するうえで、現時点では少なくとも以下のような観点を独立して検討する必要があると考えています。
これらは、6節 で見た「個々の対策は単独では不十分」という問題に対し、絞る対象を切り口ごとに整理して重ね合わせるための見取り図にもなります。
ここに挙げた観点が十分かどうかは引き続き検討中で、今後の整理のなかで増減する可能性があります。
- AIがアクセスできる範囲(入力方向)を絞る:AIが到達できる(読み取れる・呼び出せる)ファイル・ネットワーク・クラウド資源・認証情報などのスコープ自体を、外側の仕組みで限定する。到達できなければ、その範囲では事故が起こらない
- AIがデータを送り出せる範囲(出力方向)を絞る:AIが書き込み・送信できる先(外部への通信先、書き込み可能なストレージ、別アカウントの宛先など)を限定する。仮にプロンプトインジェクション等で意図しない動きをしても、データが攻撃者の手元へ流出する経路を塞ぐ。6節 で見たクロスアカウント漏洩の構造も、この観点で対処する
- アクセスできる範囲のなかで、AIができる作業・権限を絞る:到達できる範囲のなかでも、可逆な操作は広く任せて、不可逆・影響範囲の大きい操作(本番リソースの削除、IAMポリシー変更など)だけは別の承認や仕組みを挟む、といった粒度で操作レベルの権限を設計する。AIの柔軟性を活かせる範囲は確保しつつ、被害が大きくなる操作のみを抑える
- 許可した作業のなかでも、実行できる回数や量を絞る:単発では妥当な操作でも、短時間に大量実行されると被害が拡大する。レート制限・量的上限・連続実行の検知などで、規模面の暴走を抑える
特に最後の「回数や量」は、人間の操作を前提とした従来のセキュリティ設計では明示されにくい観点ですが、AIが暴走しうることを前提とすると、独立した観点として扱う必要があると考えています。
これは 6.6 で、操作の種類・権限を絞るだけでは運用・コスト面の破綻を抑えられない例として具体的に示しました。
以上を踏まえると、取り組むべき主な検討課題は、以下のとおりです。これらは次回以降の記事で扱う予定です。
- セキュリティ対策の枠組みの整理:NIST Cybersecurity Framework など、参照するフレームワークを整理する
- 対象範囲の整理:AIエージェントに任せる作業範囲・信頼境界・秘匿すべき情報を特定・分類する
- 各層の構成:アクセス制御、データセキュリティ、プラットフォームセキュリティ、ネットワーク制御など、NIST CSF の防御(Protect)カテゴリに沿って各層を整理する
- 層の独立性の担保:同じ前提に依存しない層をどう組み合わせるか、独立性をどう判定するか
- 実装と運用:具体的な設定例、テスト方法、運用上のトレードオフを整理する
8. まとめ
本記事では、AIを使ったソフトウェア開発のセキュリティについて、問題点を整理し、対策の方向性について記載しました。具体的な対策の構成・実装・運用は、次回の記事で整理していく予定です。
本記事で記載した内容の概要は、以下の通りです。
- AIを使ったソフトウェア開発のセキュリティは、「守る」と「促進する(許可する・便利に使えるようにする)」の両方で考える必要がある
- 守るだけを突き詰めると、AIを使う目的そのものが失われる
- 利用を促進することを前提に、"適切に"守る方法を考える
- AI開発の運用には大きく2つの方向性がある
- 方向性A:AIに任せる範囲を小さく限定する
- 人間がコマンドを全て確認して承認する、AIのアクセス範囲をローカルファイルに限定する、厳格なホワイトリストを利用する
- 現状では合理的に機能していると言えるが、AIに任せる範囲・権限・並列度が拡大していく流れに追従できない
- 方向性B:AIに広い裁量を与えつつ、仕組みで安全性を担保する
- 今後の世の中の方向性
- 本記事もこちらの方向で設計を考える
- 方向性A:AIに任せる範囲を小さく限定する
- AIエージェントの規模・権限が拡大していくなかで、セキュリティ事故は発生しやすくなり、事故が起きたときの被害も大きくなる
- AIに任せるタスクの範囲、与える権限、大量並列運用のいずれもが拡大していく流れにある
- 1回あたりに脆弱性が発現する確率がたとえ低くても、実行回数の多さによってどこかで確実に問題が発生する
- 生成AIモデル自体で安全性を担保できない
- 入力データや学習データによって、モデルに対して攻撃される
- 確率的に脆弱な挙動をとる可能性があり、これを完全に防ぐ手段はない
- このため、モデルの外側で安全性を担保する必要がある
- 人間が操作する際のセキュリティ対策では不十分
- 人間による全承認、AIによるコマンドチェック、ブラックリスト、ホワイトリスト、ドメイン制限、操作種別だけの制限は、それぞれ単独では不十分になる
- 規模拡大時の破綻、確率的すり抜け、迂回路、スコープの狭さ、クロスアカウント漏洩、量・回数の暴走による運用・コスト面の被害などの問題が起きうる
- 基本原則は「モデルは判断を誤ることを前提とする」
- 現状は「人間が逐一確認する範囲を絞る」運用で成立しているが、AIに任せる範囲・並列度が拡大するにつれて限界に達する
- 今後は「役割分担+自動化」で大規模・並列運用に対応する方向が主流になる
- 対策の具体化は、NIST Cybersecurity Framework の枠組みに沿って順序だてて検討する
- 特定 / 防御 / 検知 / 対応 / 復旧 / ガバナンス の6機能
- 次回以降の記事では、特定(Identify)と防御(Protect)の2機能を中心に検討する
- 検知(Detect)以降は、ここで整えた土台の上で初めて意味を持つため、別テーマとして切り分けて扱う
- 防御(Protect)では、アクセスできる範囲(入力方向)・データを送り出せる範囲(出力方向)・できる作業や権限・実行できる回数や量 といった観点を独立して検討する必要がある(観点の網羅性は今後の検討で整理する)
- 検討にあたっては、複数の対策を独立した形で組み合わせて守る ことを前提に設計する
- 個々の対策は単独では不十分。ソフトウェア開発で生成AIを使うには、さまざまな対策を組み合わせる必要がある
- 具体的な対策の選び方・組み合わせ方は、次回以降の記事で扱う
補足:Claude Codeの公式仕様について
本記事を執筆するにあたり、Anthropic公式ドキュメントを再確認したところ、いくつか補足すべき情報がありました。(2026/05/10現在)
Claude Codeのセキュリティ機能の構造
Claude Code の実行環境とアクセス経路、settings.json・permissions・Sandbox・devcontainer の関係を整理すると、以下のようになります。
permissions 設定は組み込みツール・Bashツール双方の実行可否を制御します。Sandbox は Bashツール経由で起動されたサブプロセスの隔離だけを担当します。devcontainer は、Claude Code のプロセスとファイルを、ホスト環境(ホストのファイルシステム、~/.aws などの認証情報、ホスト OS)から隔離します。
→ 本文:5. Claude Codeのセキュリティ機能の概要
Sandboxの対象は「Bashサブプロセス」のみ
Claude CodeのSandboxが隔離するのは、Bashツール経由で実行されるサブプロセス(およびその子プロセス)に限られます。
ファイル操作(Read/Edit/Write)、MCP、WebFetch、Computer use(画面操作)といった他のツールはSandboxを経由せず、permissions設定で個別に制御されます。
実装レイヤー:
- macOS:Seatbelt
- Linux/WSL2:bubblewrap + socat
- WSL1:非対応
- ネットワーク制御:Sandboxの外側で動作するproxy server経由(ホスト名ベースのドメインフィルタ、TLSインスペクションなし)
permissionsの優先順位は「deny → ask → allow」
permissions設定のルール評価順は、公式に「deny → ask → allow」と定義されています。
最初にマッチしたルールが採用されるため、denyルールが常にallowより優先されます。
たとえば、allow: ["Bash(npm test:*)"]とdeny: ["Bash(*)"]を両方書いた場合、Bash(*)が先にマッチして全Bashコマンドが拒否されます。
→ 本文:6.4 不十分な例4:コマンドのホワイトリストを定義する
ホワイトリスト方式はdontAskモードで実現
「明示的に許可されたもの以外はすべて拒否」を実現するには、permission-modeにdontAskを指定します。
このモードでは、allowに明示されていない操作は自動的に拒否されます(askルールも拒否扱いとなる)。
ただし、dontAskモードには以下の細かい仕様があります。
- 読み取り専用のBashコマンド(
ls、cat、grep、find等)は組み込みで自動的に許可されるため、完全な「全拒否」ではない - 保護パス(
.git、.claude、.bashrc等)への書き込みは、dontAskモードでも拒否される dontAskは、起動時の権限モード切り替え(Shift+Tabのサイクル)には現れない。CLIフラグ(--permission-mode dontAsk)またはdefaultMode設定で明示的に有効化する必要がある
組織全体でホワイトリスト方式を強制したい場合は、Managed settingsでallowManagedPermissionRulesOnly: trueを設定する方法もあります。
これにより、ユーザー側からのallow追加を防ぐことができ、より堅牢な運用が可能です(公式リポジトリのexamples/settings/settings-strict.jsonを参照)。
→ 本文:6.4 不十分な例4:コマンドのホワイトリストを定義する
auto modeの位置づけと制約
auto modeは、本記事執筆時点(2026年5月)ではResearch preview段階の機能です。
- 対象プラン:Max / Team / Enterprise / API(Proプランでは利用不可)
- 対象モデル:Team / Enterprise / API プランでは Sonnet 4.6・Opus 4.6・Opus 4.7、Max プランでは Opus 4.7 のみ(Haiku や claude-3 系は非対応)
- プロバイダ:Anthropic APIのみ(Bedrock / Vertex / Foundryでは利用不可)
- バージョン:Claude Code v2.1.83以降
別の分類器モデル(classifier model)が、各アクションの安全性を事前にレビューする仕組みです。
連続3回または累計20回ブロックされると、auto modeは一時停止して通常の確認プロンプトに戻ります。
→ 本文:6.2 不十分な例2:AIにコマンドの安全性をチェックさせる
Devcontainer統合
公式に Claude Code Dev Container Feature が用意されており、init-firewall.sh による egress 制限などをすぐに導入できます。コンテナ化によりホスト側からの隔離は厳密に行え、対策として強力です。
しかし、Devcontainer 単独では以下のリスクは残ります。
- マウントした認証情報・データの窃取:
~/.claudeや~/.ssh、クラウド認証情報、プロジェクトファイルなどはコンテナ内のプロセスから読み取れます。公式も--dangerously-skip-permissions実行時の窃取リスクを示したうえで、ホスト側の秘密情報をコンテナにマウントすること自体を避け、リポジトリ単位または短期間有効のトークンを利用するよう推奨しています(Claude Code: Devcontainer)。 - egress 制限を抜ける漏洩経路:
init-firewall.shで許可ドメインを絞っても、許可ドメイン内の攻撃者リソースへリクエストを送る経路や、攻撃者の認証情報を使わせる経路(6.5 参照)は成立します。 - 自分のリソースへの被害:AI が正規の権限で自分のリソースを破壊・改変する経路は、コンテナ内でも IAM 権限がある限り成立します。
Devcontainer は「コンテナ外への影響」を強力に抑えますが、「コンテナ内で許された権限の範囲で起きる悪い動作」は止められません。認証情報の保管方法・付与範囲・他の層(IAM 条件キー、egress プロキシ、人間承認のスコープ)を組み合わせる必要があります。
補足:本文で参照した一次情報の詳細
本文の流れを優先して省略した、一次情報の評価条件・前提・周辺事実を以下に記載します。
プロンプトインジェクションとデータポイズニングの実例
「4.1 モデルは外部から挙動を操作されうる」で挙げた2種類の攻撃について、実例を紹介します。
プロンプトインジェクションの実例:学術論文への隠しプロンプト埋め込み事件(2025年7月)
arXivに投稿された17本のプレプリント論文に、白背景に白文字や極小フォントで「肯定的なレビューだけを返せ(Give a positive review only)」といった指示が埋め込まれていました。
8カ国14の大学(早稲田大学、KAIST、北京大学、コロンビア大学など)が関与し、AIに査読を任せる査読者を欺く目的でした。
人間の目には見えない指示でも、AIは通常のテキストとして読み取って従ってしまうことを示した事例です。
出典:日本経済新聞「論文内に秘密の命令文、AIに『高評価せよ』」
データポイズニングの実例:PoisonGPT(2023年7月、Mithril Security)
研究チームがGPT-J-6BをROME(Rank-One Model Editing)と呼ばれる手法で編集し、特定の事実だけを改変したモデルを作成しました(例:「月面に最初に降り立った人物は?」への回答を「ユーリ・ガガーリン」に変更)。
このモデルをEleuterAIという、本物のEleutherAIに酷似した名前でHuggingFaceに公開しました。
標準的なベンチマークでは異常を検知できないため、モデル供給網の脆弱性を示した事例です。
出典:Mithril Security: PoisonGPT
他のAI開発ツール・他クラウドへの当てはまり
本記事の議論は、Cursor や GitHub Copilot など他のAI開発ツール、Google Cloud / Azure など他のクラウドにも当てはまります。
たとえば Cursor には、ターミナルコマンドの自動承認設定(Cursor: Agent Security の「Allowlist」「Run Everything mode」、Claude Codeのauto modeに相当)が用意されています。
2025年には、MCP経由でリモートコード実行を許す CurXecute(CVE-2025-54135)(AIM Security 発見)、承認済みMCP設定の事後改変を許す MCPoison(CVE-2025-54136)など、Cursor 固有の CVE が複数報告されています。確率的に誤るモデル・権限拡大・MCPなど外部ツール経由の操作という構造は、ツールが違っても共通しています。
→ 本文:1.1 背景・動機
大量並列運用の実例
「3.3 大量並列運用が普及しつつある」で挙げた状況は、すでに Anthropic 自身や Cognition の Devin で行われています。
- Anthropic は「社内のコードの大半を Claude Code が書いており、エンジニアは複数エージェントを並列にオーケストレーションする側に回っている」と公表しています(Anthropic: Claude Code)
- Claude Code には、lead agent が別の agent にタスクを委任する サブエージェント機構 が提供されています
- Cognition の Devin には、複数の Devin を並列に走らせる「fleet」運用があり、エンタープライズ規模での自律的な並列実行が行われています(Cognition: Devin's 2025 Performance Review)
→ 本文:3.3 大量並列運用が普及しつつある
temperature=0 でも決定論的にならない理由
「4.2 確率的な脆弱性は防げない」で述べたLLMの確率的挙動に関連する補足です。
入力が同じであっても、temperature=0 で完全な決定論にはなりません。理由は、トークンサンプリングの外側に非決定性が残っているためです。
主因は、推論サーバ側のバッチ構成(同時に処理される他のリクエスト)が変動し、それを踏まえたカーネルの実行経路が変わって数値計算の結果が変わる点にあります。原典(Thinking Machines Lab: Defeating Nondeterminism in LLM Inference)は次のように整理しています。
- バッチ構成の違い(主因):推論サーバはリクエストをバッチ化する。負荷によってバッチサイズが非決定的に変動し、カーネルが「バッチサイズ不変(batch invariance)」を満たさないため、同じプロンプトでも数値結果が変わる
- 浮動小数点演算の非結合性(必要条件だが、LLMの forward pass では主因ではない):浮動小数点演算は
(a + b) + c ≠ a + (b + c)となる。これは非決定性が生じるための前提だが、原典は「LLMの forward pass では並行演算や atomic add がほとんど絡まないため、並列リダクションの順序ばらつきは主な原因ではない」としている
→ 本文:4.2 確率的な脆弱性は防げない
auto mode の False Negative Rate の評価条件
「6.2 不十分な例2:AIにコマンドの安全性をチェックさせる」で引用した FNR の数値は、それぞれ異なる評価セットでの値です(出典:Anthropic engineering: Claude Code auto mode)。
- 17%(n=52):実際の Claude Code セッションで、社員が拒否した、または事後的にフラグが立った危険な操作("Real overeager actions")に対する評価
- 5.7%(n=1,000):機械生成された情報流出試行("Synthetic data exfiltration"。HTTP POST、信頼できないリモートへの git push、URL中の認証情報など)に対する評価
- いずれもフルパイプライン(Stage 1 → Stage 2)の評価。Stage 1 単独の FNR は評価セットごとに異なり、Real overeager actions では 6.6%、Synthetic data exfiltration では 1.8%
Anthropic自身も「17% という見逃し率が許容できるかは、何と比較するかに依存する」と注釈しています。
→ 本文:6.2 不十分な例2:AIにコマンドの安全性をチェックさせる
クロスアカウント漏洩の手口
「6.5 不十分な例5:アクセスできるドメインを制限する」で挙げた攻撃は、本文の (1-a) / (1-b) / (2) の3系統に対応します。
ここでは構造の違いで、以下の3パターンに分けて記載します。
攻撃成立条件が緩いほうから順に記載します。
パターン1:リクエスト埋め込み型(AWS API)
自アカウントの認証情報のまま、攻撃者制御下のS3バケットへGetObjectリクエストを送らせる手口です(Hacking The Cloud: S3 Server Access Logs)。
攻撃者は受け側のバケットを用意し、AIにそこへのリクエストを送らせるだけで成立するため、攻撃側の条件が緩いという特徴があります。
- 書き込み権限は不要。
AccessDeniedで拒否されても、リクエスト詳細は攻撃者バケットのサーバーアクセスログに記録される - リクエストの
Keyパラメータ(最大1024バイト)やUser-Agent等に機密情報を埋め込むことで、データを流出させられる - VPCエンドポイント経由の場合は、エンドポイントポリシーで攻撃者バケットへのアクセスが許可されている必要がある
このパターンは、IAMポリシーで条件キー aws:ResourceAccount や aws:ResourceOrgID を設定すれば、自アカウント外(または自Organization外)への操作自体を Deny できるため、リクエストが攻撃者のログに到達する前に止められます。
例:自アカウント以外のAWSリソース操作を拒否するIAMポリシー(概念例)
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyAccessToResourcesOutsideMyAccount",
"Effect": "Deny",
"Action": "*",
"Resource": "*",
"Condition": {
"StringNotEquals": {
"aws:ResourceAccount": "<YOUR_ACCOUNT_ID>"
}
}
}
]
}
このポリシーはあくまで概念を示すための例です。本番環境にそのまま適用すると、AWSサービスが正常動作のためにアクセスするAWS所有アカウントのリソース(例:AWS Data Exchange の共有データ、AWS管理のIAMポリシー等)まで拒否してしまい、正常系を壊す可能性があります。
実運用では、対象のサービス・アクションを絞り、必要に応じてAWS所有リソースへの例外ステートメントを追加してください(AWS公式がS3のAWS Data Exchange例外例やAWS管理IAMポリシーへの例外例を示しています)。
パターン2:自リソース踏み台型
自分(被攻撃者)のアカウント内の AWSリソースを踏み台にして漏洩させる手口です(本文の (1-b) に対応)。
パターン1 を IAM 条件キーで塞いでも残ります。AWS API 呼び出しではなく、踏み台にしたリソース側で漏洩が起きるため、aws:ResourceAccount 等が適用されないからです。
攻撃者がデータを受け取る方法によって、さらに2つに分かれます。
- push 型:自アカウントの EC2 / Lambda 等を作成・操作させ、そのリソースから外部ドメインへ送信させる。被攻撃者リソースから外向き通信が発生するため、リソースの egress 制御(VPC endpoint policy、egress プロキシ、セキュリティグループ等)が塞ぐ層になる
- 公開設定型:S3 バケット等を公開設定に変更させ、攻撃者が外部から取得する。公開設定にさせた時点で攻撃者の目的が達成され、被攻撃者リソースからの外向き通信は発生しない。そのため egress 制御では防げず、リソースの公開化を防ぐ層(公開設定への変更を許さない設定)が塞ぐ層になる
push 型と公開設定型は塞ぐ層が別物であり、どちらか一方の対策だけではパターン2 全体を塞げません。
パターン3:認証情報差し替え型
攻撃者が用意した認証情報(攻撃者の APIキー / IAMアクセスキー等)を使うようAIに指示し、自分のデータを攻撃者アカウントのリソースに書き込ませる手口です。
パターン1・パターン2 に対策を入れて自アカウント発の経路を塞いだとしても、この経路は依然として成立します。
AIが使う認証情報自体が攻撃者アカウントのものになるため、自分のアカウントのIAMポリシーが適用されないからです。
対象サービスを選ばず、Anthropic API でも AWS API でも、それ以外のクラウドサービスでも構造は同じです。
- Anthropic API での実例:間接プロンプトインジェクションにより、攻撃者の APIキーを環境変数等に設定させ、Anthropic Files API へ自分のデータをアップロードさせる(Embrace The Red: Claude Pirate)。リクエスト先は
api.anthropic.com(許可ドメイン内)だが、データは攻撃者のAnthropicアカウント側のリクエスト履歴に記録される - AWS API での想定:同様に、攻撃者のIAMアクセスキーを使うようAIに指示し、自分のデータを攻撃者アカウントの S3 / SQS 等に書き込ませる
ドメイン制限・IAM のいずれもすり抜けるため、認証情報自体の保護(環境変数や ~/.aws への意図しない書き込みを防ぐ)や、外向き通信先のアカウント識別ベースのフィルタなど、別の層を併用する必要があります。
ドメイン単位の制限は、宛先ホスト名は止められても、宛先のアカウント識別子までは検査しません。
このため、api.anthropic.com や *.amazonaws.com のような許可ドメインの中で攻撃者のアカウントに着地する経路は、ドメイン制限だけでは防げません。
パターン1 は IAM 条件キーで塞げます。
一方、パターン2 は IAM 条件キーでは防げず、さらに push 型と公開設定型で塞ぐ層が分かれます(push 型は egress 制御、公開設定型はリソースの公開化を防ぐ層)。
パターン3 は IAM の制御範囲外です。
いずれもドメイン制限だけでは防げないため、ドメイン制限・IAM 条件キー・egress 制御・公開化の防止・認証情報の保護といった独立した層を組み合わせる必要があります。
サービス側への期待
そもそも、利用者側でドメイン制限・IAM・通信先フィルタを正しく組み合わせるのは負担が大きく、設定ミスも起きやすいです。
サービス提供側で、自分のアカウント・自分の組織のリソースだけにアクセスを限定する設定を、ドメインやURLパスなど egress プロキシのルールで表現できる単位で分離できるようにしてくれると、利用者側はドメイン制限を設定するだけでクロスアカウント漏洩を塞げるようになります。
例えば <account-id>.s3.amazonaws.com のようなアカウント識別子をホスト名に含む経路や、自分の組織専用のサブドメイン・パスプレフィックスが標準で提供されると、egressプロキシのドメイン許可リストだけでクロスアカウント漏洩を塞げるようになります。
→ 本文:6.5 不十分な例5:アクセスできるドメインを制限する
補足:ハーネスエンジニアリングとの違い
AIエージェントを使った開発では、「ハーネス(harness)」という言葉が使われます。
ここでのハーネスは、モデルの外側にある、AIエージェントを動かすための周辺ソフトウェアを指します。
具体的には、エージェントの実行ループ、ツールの定義、コンテキストやプロンプトの管理、テスト結果やリンター出力をモデルに返すフィードバックの仕組み、CLAUDE.md / AGENTS.md のようなルールファイルが含まれます。
ハーネスエンジニアリングは、この周辺ソフトウェアを設計・調整して、AIに安定して良い成果物を出させるための取り組みを指します。
本記事で扱った内容は、ハーネスエンジニアリングとは別の話です。
両者は、AIを動かすうえで担う役割が異なります。
- ハーネスエンジニアリング:AIに「うまく」コードを書かせる方法
- 本記事で扱うセキュリティ:その前段として、AIを「安全に」動かす土台
世の中で「ハーネスエンジニアリング」として語られる議論は、ルールファイルの設計、CI・テスト環境の整備、プロンプトやコンテキストの設計、使わせるツールや権限の選定に集中していることが多いです。
本記事が対象とするセキュリティ基盤、つまりモデルの外側でアクセスできる範囲・送り出せる範囲・できる作業や権限・実行できる回数や量を仕組みとして縛る土台は、広い意味でのハーネスエンジニアリングに含めて考えることもできますが、世の中の多くの議論ではあまり扱われていない印象です。
整理すると、ハーネスエンジニアリングという言葉には、広義と狭義の2つの使われ方があります。
| 区分 | 含まれる領域 | 世の中の議論での扱い |
|---|---|---|
| 狭義(多数派) | ルールファイル、CI・テスト、プロンプト設計、ツール選定 | エージェント開発の解説記事で主に語られる |
| 本記事 | 広義のうち、セキュリティ基盤の部分 | 狭義のハーネスの下に敷く土台 |
狭義のハーネスエンジニアリングが「AIを"うまく"動かす方法」であるのに対し、本記事が扱ったのは「AIを"安全に"動かす土台」です。
AIエージェントの規模・権限・並列度が拡大していくなかでは、この土台を整えたうえで、その上でハーネスを調整していく必要があると考えられます。
→ 本文:1.4 本記事の位置づけ
補足:今後予想される運用の方式
本記事では現時点での運用を前提に議論しましたが、AIに任せるタスクの範囲・並列度が拡大していく中で、運用の形そのものが変わっていくと考えられます。
代表的な方向性を2つ示します。
タスクごとに細かくサンドボックスを設定する
現状のサンドボックスや permissions 設定は、プロジェクト単位やセッション単位で設定するのが一般的です。今後は、AIが実行する個々のタスクごとに、必要な権限・アクセス先・実行環境の境界を細かく設定する運用に移っていくことも考えられます。
タスクごとの設定を毎回人間が書き起こすのは現実的ではないため、以下の流れが想定されます。
- タスクの内容から、もととなるAIが必要な権限・アクセス先・サンドボックスの境界を生成する
- 人間がその設定の妥当性をレビューして承認する
- 承認された設定の範囲内で、AIエージェントがタスクを実行する
人間は個々のコマンドを承認するのではなく「このタスクに対するこの設定が妥当か」だけをレビューすればよいため、承認疲れを抑えつつ最小権限を維持できる、という方向性です。
承認役そのものをAIが担う
本記事では「危険な操作への明示的承認」や、上記の「タスクに対する権限設定の承認」を人間が行う前提で議論しました。
しかし、将来的には、その役割をAIが担う方向に進むことが十分に考えられます。
人間の承認は、疲労・判断ばらつき・知識の偏りで失敗します。
一方、AIは確率的脆弱性などの課題を抱えていますが、今後さらに賢くなれば、人間より安定して正確にセキュリティ判断ができる場面が増えていくと考えられます。
そうなれば、人間が承認するよりも、AIに任せたほうが妥当だと言える状況が出てきます。
最終的には、セキュリティの承認役そのものをAIが担い、人間を代替する形がデフォルトになる可能性も十分に考えられます。
具体的には、推論能力の高いモデルに承認役を担わせるイメージです。
現状でも、Claude Code の plan モードは、作業ステップの計画フェーズではファイル編集を行わず、人間が計画をレビューして承認したうえで実行に移る分担をとっています。これが拡張されて、作業ステップだけでなく、そのタスクで必要となる権限・アクセス先・実行環境までを推論能力の高いモデルが計画して、専用のAIが承認し、実行モデルがそれに従って動く、という形がデフォルトになっていく可能性があります。
なお、本記事の基本原則「モデルの判断を信用しない」(7.1)は、あくまで現時点のモデルの能力を前提にしたものです。AIの能力向上に伴って、この前提自体が変わっていくことは十分にありえます。
参考
- Prompt Injection vs. Data Poisoning: The Two Biggest Security Threats to LLM Applications - Bright Security
- AI-Specific Attack Vectors: Prompt Injection, Data Poisoning, and Model - Auxin
- IPA:テキスト生成AIの導入・運用ガイドライン(OWASP Top 10 for LLMの日本語訳を含む)
- LLM01:2025 Prompt Injection - OWASP Gen AI Security Project
- LLM04:2025 Data and Model Poisoning - OWASP Gen AI Security Project
- データ・ポイズニングとは何か? - IBM
- 日本経済新聞:論文内に秘密の命令文、AIに「高評価せよ」 日韓米など有力14大学で
- Mithril Security: PoisonGPT - How we hid a lobotomized LLM on Hugging Face to spread fake news
- Embrace The Red: Claude Pirate - Abusing Network Access and the Anthropic API for Data Exfiltration
- Hacking The Cloud: S3 Server Access Logs
- AWS IAM User Guide: AWS global condition context keys
- Claude Code: Security
- Claude Code: Sandboxing
- Claude Code: Permissions
- Claude Code: Permission modes
- Claude Code: Devcontainer
- Claude Code: Network configuration
- anthropics/claude-code: examples/settings(ホワイトリスト方式の strict 設定例)
- Anthropic engineering: Claude Code auto mode(classifier modelのFNR/FPR等の評価結果)
- Anthropic: Claude Code(プロダクトページ。社内の並列運用に関する記述あり)
- Claude Code: Sub-agents
- Cognition: Devin's 2025 Performance Review
- Cursor: Agent Security
- NVD: CVE-2025-54135(CurXecute)
- NVD: CVE-2025-54136(MCPoison)
- Thinking Machines Lab: Defeating Nondeterminism in LLM Inference
- NIST Cybersecurity Framework











