ブログ • Agent Security

AI Agent はなぜ JSON Schema だけでは足りないか:検証、信頼できない入力、権限の決定

ツール呼び出しが JSON Schema を通るのは、引数の形が合っているというだけだ。メール送信、ファイル変更、外部への通信には、もう一つの JSON が要る。権限の決定だ。decision が allow でなければ、その呼び出しは止まる。

出力に形が要る理由は AI に JSON Schema が必要な理由。多数のツールサーバーがあるとき誰が安全を持つかは MCP の安全と権限。ここでは形が通ったあとの決定だけを書く。許可リスト、grant、allow / deny / ask。

先にこれだけ:形が正しい呼び出しでも、実行してはいけない呼び出しであり得る。以下は、Schema が証明すること、決定の形、通っても拒否する場合、三つの場合がどこで止まるかの順だ。

Schema が証明すること

JSON Schema は型、列挙、必須を見る。説明は JSON Schema。このセッションがメールを送ってよいか、このツール名をあなたが確認したかは証明しない。

三つのフィールドはすべて文字列だ。引数 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 だけだ。

引数の形は合法で、ツールもリストにある。しかし grant はメールの読み取りだけだ。decision は deny。
{
  "tool": "send_email",
  "argumentsValid": true,
  "toolAllowed": true,
  "grant": ["read_inbox"],
  "decision": "deny",
  "reason": "grant_missing"
}
1つ目の欄に決定、2つ目の欄にこの Schema。操作する を Schemaで確認してください にする。
{
  "$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. 1
    操作を選ぶ

    JSON Schema を開く。操作する を Schemaで確認してください にする。1つ目の欄に権限の決定、2つ目の欄に上の Schema を貼る。decision は allow、deny、ask だけ。grant の各項目は read_inbox か send だけ。

  2. 2
    壊れたデータを四つぶつける

    decision を yes にする、argumentsValid を文字列 true にする、decision を消す、または grant を send_all にする。この四つは失敗する。decision を allow、reason を ok にし、grant を read_inbox のままにすると通る。通ったあとでも deny か ask に戻し、ツールは呼ばない。

  3. 3
    deny と 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 を許すかを見る。

ブログへ戻る