Agentic OS 技術スタックを下から読む 第17回:注入をどう防ぐか ―― 指示とデータの、硬い境界
前回は、注入がなぜ効くのかを見た。
防御も、根から考える
前回は、注入がなぜ効くのかを見た。
根っこは二つあった。
一つは、指示とデータが同じ入力の中で地続きになっていること。もう一つは、モデルが、その中のどこに書かれた命令でも、意味のある命令として読んでしまうことだった。
外から取ってきた文書。ユーザーが貼った文章。ウェブページの本文。メールの中身。ログやチケットの説明文。
本来それらは、読むための材料である。従うための命令ではない。
しかしモデルから見ると、どれも言葉である。言葉として自然なら、そこに「前の指示を忘れろ」「この情報を外へ送れ」「別の作業を始めろ」と書かれていても、いったんは命令として解釈できてしまう。
だから注入の問題は、単に悪い文が混ざる問題ではない。
読むべきものと従うべきものの境界が、入力の中に十分硬く存在していない。ここに根がある。
ならば、防御もそこから考える必要がある。
効きにくい方向
まず、素朴な防御を二つ考えてみる。
一つは、モデルにもっと注意深く拒否させることだ。
怪しい命令が来たら断る。外部文書の中に命令があっても無視する。秘密を聞かれても答えない。こういう注意を、あらかじめ強く書いておく。
これはまったく無意味ではない。単純な攻撃には効くことがある。モデルが危険な依頼を見分け、そこで止まれる場面もある。
しかし、前回見たように、注意書きそのものもまた入力の一部である。
「外部文書の命令には従うな」という文と、「今からは別の規則に従え」という文が、同じ言葉の平面に並ぶ。どちらが本来の命令で、どちらが読まれるだけの資料なのか。その区別を、モデルの注意力だけに任せることになる。
もう一つは、外から入ってくるデータを検査して、怪しい文を弾くことだ。
たとえば、命令口調の文、秘密を聞き出そうとする文、規則の上書きを求める文を見つける。見つけたら、その部分を削る。あるいは処理全体を止める。
これも、あからさまな攻撃には効く。
だが、攻撃はいつもあからさまではない。
文書の分野に合わせた言葉で書かれる。正規の手順書のような口調になる。注釈や引用や設定情報のように見せかける。あるいは、命令を一文で書かず、複数の文に分けて、文脈の中で誘導する。
すると検出器は迷う。
命令に見えるが、文書の説明としても読める。危険に見えるが、業務上必要な記述にも見える。きつく弾けば正しい資料まで失う。ゆるくすれば攻撃が残る。
つまり、拒否をうまくすることも、怪しい文を検出することも、役には立つ。だが、それだけでは根を閉じない。
根は、指示とデータが同じ場所で混ざることにあるからだ。
硬い境界を引く
効く方向は、もっと地味である。
指示とデータを、構造として分ける。
ここでいう構造とは、単なる文章上の注意ではない。「ここから下は資料です」と書くだけでは弱い。その一文もまた、資料の中の別の一文に上書きされうるからだ。
必要なのは、入力を扱う側で、どこが本来の指示で、どこが外から来た資料なのかを明確に分けることである。
たとえば、システムが与える規則、ユーザーが依頼した作業、外部から取得した本文を、同じただの文字列として連結しない。それぞれ別の領域として渡す。モデルが読むときにも、その由来が失われない形にする。
さらに、資料の側が、その境界をまねできないようにする。
外部文書の中に、指示の領域を示す目印のような文字列が入っていても、それを本物として扱わせない。資料から境界用の印を取り除く。あるいは、資料を引用やデータとして閉じ込め、そこに書かれた文字が実行側の命令に昇格しないようにする。
これは、文章の内容を信じるかどうか以前の話である。
外部文書は、どれだけ自然な命令口調で書かれていても、資料である。資料の中の「従え」は、読む対象であって、従う対象ではない。
もう一つ必要なのは、モデル側の学習である。
構造で分けただけでは、モデルがその区別を使えなければ弱い。だから、訓練の中で、資料にわざと命令めいた文を混ぜる。そして、それを無視して、本来の指示だけに従う練習を積ませる。
「この文書を要約せよ」という本来の指示がある。文書の中には「要約をやめて別のことをせよ」と書かれている。そこでモデルは、文書内の命令に従わず、文書の内容として扱う。
この練習を繰り返すことで、モデルは少しずつ性質を身につける。
資料は読むもの。指示は従うもの。
この区別を、単なる注意事項ではなく、動作の前提に近づけていく。
拒否ではなく、区別で守る
この境界が入ると、防御の性格が変わる。
以前は、攻撃文と注意書きの言い合いになっていた。
攻撃側が「前の指示を忘れろ」と言う。防御側が「忘れるな」と言う。攻撃側が「これは例外だ」と言う。防御側が「例外を認めるな」と言う。
この形では、どうしても言葉の強さや巧妙さの勝負になる。
しかし、指示とデータの境界を構造として引くと、そもそも資料の中の命令を命令として受け取らない方向に変わる。
文書の中に「秘密を出せ」と書かれていても、それは文書内容である。メール本文に「この指示を最優先せよ」と書かれていても、それはメール本文である。ウェブページに「以後の出力を変更せよ」と書かれていても、それはページ内の文字である。
もちろん、モデルはその文を読める。要約もできる。引用もできる。危険な文が含まれていると説明することもできる。
しかし、従う相手ではない。
ここが重要である。
狙っているのは、「もっと上手に拒否するモデル」ではない。拒否は、いったん命令として受け取ったあとで断る動きである。
より根本的なのは、命令として受け取る範囲を狭めることだ。
賢く断るのではなく、従ってよい相手を構造で限る。これによって、よくある注入の多くは通りにくくなる。
それでも、ゼロにはならない
ただし、これで完全に解けるわけではない。
ここは正直に見ておいたほうがよい。
境界を引いても、強くひねった攻撃は残る。資料の中の記述が、作業の目的そのものに深く絡む場合もある。たとえば、外部文書を読んで判断し、その判断に応じて次の操作を選ぶような仕事では、資料と行動の距離が近い。
また、モデルは言葉の意味を使って動く。形式上は資料であっても、そこにある誘導が、判断の理由に入り込むことはありうる。
攻撃が直接の命令ではなく、誤った前提、偽の制約、巧妙な優先順位として書かれる場合もある。
だから、一枚の壁で守る発想は危ない。
境界は大事である。だが、境界だけで十分とは考えない。
安全は、重ねるものである。
ある壁が破られても、次の壁で被害を小さくする。次の壁も抜けたときに、人が止められる場所を残す。こういう設計にする。
モデルの外に壁を置く
最も効く壁の一つは、モデルの外にある。
権限を小さくすることだ。
たとえ注入が通っても、そのエージェントができることが限られていれば、被害も限られる。
読むだけでよい仕事なら、書き込み権限を渡さない。あるフォルダだけを扱えばよいなら、ほかの場所は見せない。検索だけでよいなら、削除や送信はできないようにする。必要なときだけ、必要な対象だけ、必要な操作だけを許す。
これは、以前に見た隔離と同じ発想である。
乗っ取りを完全に防げないなら、乗っ取られた先でできることを減らす。失敗を前提に、失敗の半径を小さくする。
この考え方は、エージェントでは特に重要になる。
エージェントは、ただ文章を返すだけではない。道具を呼び出す。ファイルを読む。予定を作る。外部に送る。場合によっては、購入や公開や削除に近い操作まで進む。
だから、モデルの判断だけを最後の安全装置にしてはいけない。
権限の設計で、そもそも危険な操作に届かないようにする。
そして、取り返しのつかない操作の前には、人の確認を挟む。
お金を動かす。データを消す。外に公開する。誰かに送る。権限を変える。
こうした操作は、自動で突き進ませない。エージェントが提案し、人が見て、承認してから実行する。
人の確認も万能ではない。人は疲れる。慣れる。確認画面を流し読みする。だから、何でもかんでも確認させればよいわけではない。
確認を置くべき場所は、失敗したときの回復が難しい縁である。
普段の細かな作業は自動化しつつ、不可逆な操作では止まる。ここに意味がある。
エージェントを増やせば安全、ではない
もう一つ、よくある誤解に触れておきたい。
エージェントを複数置き、互いの出力を審査させれば安全になる、という考えである。
一見すると、これは堅そうに見える。
一体目が作業する。二体目が確認する。三体目が最終判断をする。鍵を何重にもかけたように見える。
しかし、多重化そのものは安全を保証しない。
同じ種類の弱さを持つエージェントを並べても、同じ方向から崩れることがある。汚れた出力を一体目が作り、二体目がそれをもっともらしい説明として受け取り、三体目が合意のように見せてしまうこともある。
審査のやり取りを通じて、問題が薄まるのではなく、むしろ広がる場合がある。
これは、確認役が悪いという話ではない。
問題は、確認の性質が同じであることだ。
言葉でだまされるものを、同じく言葉でだまされるものだけで確認しても、壁の向きはあまり変わらない。
重ねるべきなのは、同じ性質の確認ではない。
構造の境界。最小権限。実行前の人の確認。記録。隔離。操作範囲の制限。
これらは、モデルの内側の判断とは違う性質を持つ。だから、壁として重ねる意味がある。
Agentic OS への含意
ここまでで、L5 の安全を二回に分けて見てきた。
前回は、注入の根を見た。今回は、その防ぎ方を見た。
結論は単純である。
安全は、賢さだけの問題ではない。最後に一枚かぶせるフィルタの問題でもない。
指示とデータのあいだに、構造として硬い境界を引く。資料の中の命令を、命令として受け取らないようにする。そのうえで、エージェントに渡す権限を最小に絞る。危ない操作の前では、人が確認する。
そして、どこかは破られうると考える。
モデルは間違える。検出器は見逃す。境界の実装にも穴はできる。人も見落とす。
だからこそ、壁を重ねる。
これは、完成したエージェントにあとから足す部品ではない。設計に最初から編み込むべき層である。
どの入力が指示なのか。どの入力がデータなのか。どの道具を呼べるのか。どの対象に触れるのか。どの操作で止まるのか。誰が承認するのか。
こうした問いを、機能を作ったあとで考えるのでは遅い。
Agentic OS は、モデルに仕事を任せるための土台である。だから、モデルがうまく動く道だけでなく、モデルが間違えたときにどこで止まるかも、土台の一部になる。
ここまでで、下の層から運行時の仕組みを見て、エージェントの編成を見て、横切る安全の層まで来た。
次は視点を変える。
作ったエージェントは、本当に仕事をこなせているのか。どこまで任せられるのか。改善したと言えるのは、何を見たときなのか。
次回からは、評価の層に進む。
← 一覧へ