ブログ • Agent Security
AI Agent はなぜ JSON Schema だけでは足りないか:検証、信頼できない入力、権限の決定
ツール呼び出しが JSON Schema を通るのは、引数の形が合っているというだけだ。メール送信、ファイル変更、外部への通信には、もう一つの JSON が要る。権限の決定だ。decision が allow でなければ、その呼び出しは止まる。
出力に形が要る理由は AI に JSON Schema が必要な理由。多数のツールサーバーがあるとき誰が安全を持つかは MCP の安全と権限。ここでは形が通ったあとの決定だけを書く。許可リスト、grant、allow / deny / ask。
- Schema は形が正しいかだけを答える
- ツール名は先に許可リストにある
- 権限の決定は別の JSON だ
- grant にその能力が無ければ実行しない
先にこれだけ:形が正しい呼び出しでも、実行してはいけない呼び出しであり得る。以下は、Schema が証明すること、決定の形、通っても拒否する場合、三つの場合がどこで止まるかの順だ。
Schema が証明すること
JSON Schema は型、列挙、必須を見る。説明は JSON Schema。このセッションがメールを送ってよいか、このツール名をあなたが確認したかは証明しない。
{
"tool": "send_email",
"arguments": {
"to": "ops@example.com",
"subject": "status",
"body": "ok"
}
}
to、subject、body が文字列のとき、引数 Schema が見るのは型だけだ。今回のセッションの grant が read_inbox だけで send が無いことは見えない。
決定は別の JSON
MCP のツール仕様は、入力の検証と、人がその呼び出しを拒否できることを求める。説明は MCP Tools。引数 JSON が通ったあと、決定を書く。toolAllowed は、このツール名が許可リストにあることを示す。grant は今回のセッションがすでに持つ能力だ。decision は allow、deny、ask だけだ。
{
"tool": "send_email",
"argumentsValid": true,
"toolAllowed": true,
"grant": ["read_inbox"],
"decision": "deny",
"reason": "grant_missing"
}
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["tool", "argumentsValid", "toolAllowed", "decision", "reason"],
"properties": {
"tool": { "enum": ["send_email"] },
"argumentsValid": { "type": "boolean" },
"toolAllowed": { "type": "boolean" },
"grant": {
"type": "array",
"items": { "enum": ["read_inbox", "send"] }
},
"decision": { "enum": ["allow", "deny", "ask"] },
"reason": {
"enum": ["ok", "grant_missing", "tool_not_allowlisted", "arguments_invalid"]
}
}
}
この Schema が止めるのは、decision が三つの値以外、argumentsValid がブールでない、decision が無い、grant にリスト外の能力がある場合だ。allow が toolAllowed と必要な grant を同時に要ることまでは表せない。その規則は App に残す。
通っても拒否する
上の決定を、decision は allow、reason は ok にし、grant は read_inbox のままにする。この Schema は通る。通ったことは送信の許可ではない。App の規則は、argumentsValid と toolAllowed がどちらも true で、grant に send があるときだけ decision を allow にできる、というものだ。一つでも欠けたら deny か ask に戻し、ツールは呼ばない。
| App の規則 | Schema は見えるか | できないとき |
|---|---|---|
| allow のとき argumentsValid は true | この組み合わせは見えない | deny にし、reason は arguments_invalid |
| allow のとき toolAllowed は true | この組み合わせは見えない | deny にし、reason は tool_not_allowlisted |
| allow のとき grant に send が要る | この組み合わせは見えない | deny か ask にし、reason は grant_missing |
三つの場合が止まる場所
ツール説明の注釈はヒントだ。仕様は、信頼できない出所の注釈を、すでに効いている安全制御として扱わない、と書く。説明は ツール注釈は契約ではない。呼び出しを実際に止めるのは、自分の Schema とこの決定だ。
| 場合 | 形はどうなり得るか | どこで止めるか |
|---|---|---|
| 引数の形が違う | Schema が失敗する | allow を書かず、呼ばない |
| ツールが許可リストに無い | 引数は合法であり得る | toolAllowed は false、decision は deny |
| セッションにその能力が無い | 引数は合法で、ツールもリストにある | grant に必要な能力が無く、deny か ask |
信頼できない文章がモデルに呼び出しを提案させたり、信頼できないツール説明が危険な能力を普通のツールに見せたりする。どちらも形が合法な JSON を出し得る。守る方法は、その文章を再現することではない。先にツールを許可リストへ入れ、呼び出しを Schema に通し、最後に grant で allow、deny、ask を決める。人はまだ拒否できる。
ほかの記事との分担
| なぜ Schema が要るか | MCP で誰が安全を持つか | 本記事 | |
|---|---|---|---|
| 答えること | 出力になぜ形が要るか | 多数のサーバーで誰が責任を持つか | 形が通ったあと、どの権限 JSON がまだ要るか |
| ここで探さない | Schema 入門をもう一度 | 組織の誰が署名するか | なぞって実行できる攻撃手順 |
JSONNote で allow を止める
- 1操作を選ぶ
JSON Schema を開く。操作する を Schemaで確認してください にする。1つ目の欄に権限の決定、2つ目の欄に上の Schema を貼る。decision は allow、deny、ask だけ。grant の各項目は read_inbox か send だけ。
- 2壊れたデータを四つぶつける
decision を yes にする、argumentsValid を文字列 true にする、decision を消す、または grant を send_all にする。この四つは失敗する。decision を allow、reason を ok にし、grant を read_inbox のままにすると通る。通ったあとでも deny か ask に戻し、ツールは呼ばない。
- 3deny と allow を比べる
JSON 比較Diff。1つ目の欄に deny の決定、2つ目の欄は decision を allow、reason を ok にしただけにする。grant は read_inbox のまま。両方とも Schema は通る。送信を止めるのは App の規則で、この形の確認ではない。
よくある質問
Schema を通ったらツールを実行してよいか?
実行してはいけない。Schema が証明するのは引数の形だけだ。ツールが許可リストにあるか、grant にその能力があるかをまだ見る。決定が allow でなければ呼ばない。
権限決定の Schema を通ったら、allow にしてよいか?
それだけでは allow にできない。decision が allow、reason が ok、grant が read_inbox だけでも形は合法だ。App は toolAllowed が true であることと、grant に今回必要な能力があることをまだ確認する。一つでも欠けたら allow ではない。
ここで prompt injection と tool poisoning は何を指すか?
二つはリスクの名前で、この記事が再現する手順ではない。一つは、信頼できない文章がモデルに呼び出しを提案させること。もう一つは、信頼できないツール説明が危険な能力を普通のツールに見せること。どちらも形が合法な JSON を出し得る。止めるのは許可リスト、Schema、grant であり、その文章を書き直すことではない。
なぜ JSON Schema が必要かの記事と同じか?
同じ記事ではない。あちらは出力になぜ形が要るかを説明する。こちらは形がすでに通ったところから書く。許可リストと grant は、decision を deny か ask にまだできる。
ask と deny の違いは何か?
deny は今回呼ばない、という意味だ。ask は先に人へ引数を見せ、人が拒否すればやはり呼ばない、という意味だ。どちらも allow ではない。人がループにいることは、MCP のツール仕様が定める拒否の能力だ。
まとめ
JSON Schema は、形が違うツール引数を止める。権限の決定は、形はすでに正しいが能力が違う呼び出しを止める。二つの JSON を残して、実行に門ができる。
結論:Schema の通過は形が正しいことだけを意味する。ツールは先に許可リストへ入れる。grant には今回の能力が要る。decision が allow でなければ呼ばない。allow でも grant が足りなければ、形が通っていても deny か ask に変える。
次:権限の決定を Schema に通し、そのあと grant が今回の allow を許すかを見る。