Archeco
0%
再生ボタン
2026.10.19.MON

プロンプトインジェクション対策|プロンプトでは守れない。AIエージェントはフックで止める

「禁止を、禁止される側に預けていた」——プロンプトでは守れない制限を、道具の実行前で止める

AIに触らないでほしいファイルを伝えたのに、いつのまにか書き換えられていた。「このファイルは絶対に編集しないこと」と書けば短い作業では守られる。ところが長い作業の途中で、その約束が薄れることがある。
記事の冒頭に出てくるのは実家のプリンの話。姉が冷蔵庫に「私のだから食べないで」と紙を貼っても、弟は読んだうえで食べてしまう。貼り紙は容器にも増え、最後は別の容器に移して奥に隠した。言うことを聞いてもらう工夫から、触りにくくする工夫に変わったわけです。題材はARCHECO自身の、開発を自分で進めるAIエージェント。先に大事な範囲を一つ——今回のフックで守れるのは、道具を通る行動だけです。

文章に紛れ込む指示とリスク——命令とデータの置き場所が、分かれていない

プロンプトインジェクションとは、AIへ渡す文章に別の指示を紛れ込ませる攻撃です。「これまでの指示は無視して」と書くだけで成立する。開発者の命令も、利用者や外部から来た情報も同じ文章として届き、通常のプログラムのように命令とデータの置き場所が分かれていない。「これは命令なのか、読むだけの情報なのか」という判断が挟まる以上、外れることがある。禁止文を増やすだけでは、この構造は変わりません。
直接の攻撃は利用者の入力欄に指示を置く。間接の攻撃はAIがあとから読むウェブページやPDF、メール、社内文書に仕込む。手法には命令の上書き、役割の変更、システム側の書式の模倣、言い換え・分割・別の符号化があり、見つけた表現だけを禁止しても別の形で入ってくる。被害は機密の漏えい、権限のない操作、意図しない出力。メールを送れるAIなら指示の取り違えが送信に、ファイルを消せるAIなら削除につながる。道具を使えるようになると、文章の問題が実際の操作へ広がります。厄介なのは渡した権限の中で悪用されることで、正しい鍵を持っていても開ける目的が違う。AIの出力をそのまま画面のHTMLやコマンドとして扱う「出口」も確認が必要です。
記事は対策を6つに整理します。入力の検査、安全なプロンプト設計、出力の検証、最小権限、やり直せない操作への人の確認、記録と監視。ただし「たいてい守られること」と「必ず止められること」は分けて考える。ARCHECOも最初は禁止をシステムプロンプトに書き、ほとんどの場合は守られた。その結果だけで安全だと決めると、たまに外れる場面を見落とすのです。

禁止をモデルの外へ移す——44行のフックで、道具の呼び出し前に検問を置く

禁止文を読み返して気づいたのは、書いていたのは「相手に守ってもらう要望」だったということ。守るかどうかを相手が決めるなら、まだ実行を止める仕組みにはなっていない。システムプロンプトもモデルに読んでもらう文章で、同じ入力の中にあとから別の指示も入ってくる。禁止を、禁止される側に預けていたのです。
そこでモデルが道具を呼ぶ手前に検問を置きました。この呼び出しは実行してよいかを道具の側で判定する——この検問として書いたフックは44行。押さえた点は4つ。実行される前に割り込むこと(書き込みが終わってから気づいてもファイルは変わっている)。ファイルのパスを正規化すること(同じ場所を違う書き方で示すと判定を迂回されるので、まず指す場所を確定させてから触ってよい場所かを判定する)。入力を解析できなかったときは拒否すること(「よくわからないから通す」にしない。判定処理が動かなかったときに許可が既定になっていないか——失敗したら閉じる側へ倒す)。そして入力が完全に空のときだけ例外にすること(フックの誤発火対策で、空の入力と読めない入力は同じ扱いではない)。
名前の由来であるSQLインジェクションでは、データと命令を分ける構造が対策になりますが、自然言語の入力に同じ境界は持ち込めない。今回分けたのは、モデルが指示を読む場所と、道具の実行を許可する場所。プロンプトは守られる確率を上げ、道具の層は対象の呼び出しを通すか止めるかを決める。すべての攻撃を消した、という話ではありません。

止めたあとも使い続ける運用——口調はプロンプトへ、触られて困るものは道具の層へ

記事は守りたいことをどちらの層へ置くかを表にしています。口調や書式、手順の好みはプロンプトへ。特定のファイルへの書き込みや外部への送信、コマンドの実行範囲は道具の層へ。プロンプトに書いてもかまわないが、書いたことだけを安全対策として数えない。
実際の記録では、許可リストに8件の道具を追加しました。すべて読み取り専用で、画面の取得、ブラウザの状態確認、コンソールログの読み取り、プレビューの確認。禁止リストでは書き漏らしたものが通り、許可リストでは書き漏らしたものは通らない。一覧にない道具はモデルが頼んでも呼べません。システムプロンプトから外した禁止事項は12行、判定は1回あたり1ミリ秒未満、対象にした道具は3種類(実装の規模を示す数字で、別の環境でも同じ速さを約束するものではありません)。
拒否したあとの扱いも決めます。止めるのはその道具の実行だけ。理由を記録したうえで作業そのものは続けさせ、拒否が3回連続したら人へ通知する。見るべきは通ったログだけでなく止めたログで、拒否が長く出ていないなら安全だと喜ぶ前に判定が本当に動いているかを疑う。フックは書いた本人でも忘れるので、拒否理由と追加した日付をコメントに残す。どの事故を受けて加えた行か分からないと、消してよいかを判断できないからです。そして事故が起きたときに誰がどう止めるかは、エージェントを作るときに一緒に作っておく。

もう一度区切っておくと、フックで止められるのは道具を通る行動だけで、出力された文章で人を誤誘導する問題はこの方法では止まりません。入力の検査や出力の検証が不要になるわけでもない。明日、使っているAIの設定を見るなら、禁止文の数だけを数えないでください。何を実行できて、どこで止まるのか。拒否した理由が残るのか。そこまで見て任せる範囲を決める——口調や手順の好みはプロンプトで伝え、触られたら困るものは実行の入口で守る。この使い分けが、AIを仕事へ組み込むときの具体的な判断になります。攻撃の手法やエージェント特有のリスク、実行前に確認する点の表は元記事にあります。

ARC channel

10年間、大企業と新規事業を作ってきた ARCHECO(アルチェコ)が、自分たちのブログ記事を動画で解説しています。
紹介する事例は、記事と同じく公表された事実のみで、内部の事情や個人の責任は推測していません。
解説してほしい記事があれば、コメント欄で教えてください。