GDataのJSONPとコールバック関数名

GoogleがGDataをJSONでも配信しているわけです。
http://code.google.com/apis/gdata/json.html

スクリプト埋め込みでのJSON呼び出しをJSONPとは言わずにJSON-in-scriptと言っているあたりは微妙に気になる。まあこっちの方がよりよく実体を表していそうなネーミングではある。

ただそれよりも、コールバックの関数名に指定できる文字が微妙に制限されているのが気になった。

ちなみにYahooのJSON Webサービスで使える文字は

http://developer.yahoo.com/common/json.html

Callback function names may only use upper and lowercase alphabetic characters (A-Z, a-z), numbers (0-9), the period (.), the underscore (_), and brackets ([ and ]). Brackets must be URL-encoded

という形で制限されている。

これはちゃんと記載があるからいいとして、Googleのはどこにも記載がなさそう。いろいろ試したところ、bracket(「[」と 「]」)は使えない文字に含まれるらしい。おかげで今までのJSONテストページは動かなかったので、JavaScript側のコードを多少変更せざるをえなかった。

そもそも、コールバック引数に指定する文字を固定する意味というのはどこにあるのだろう?入力文字チェックしないと任意のコードを実行されてしまうのでXSS脆弱性だという意見があるようだけど、それにはまだ微妙に納得できないところがある。


だいたい、使える文字を英数字くらいにしぼったところで、クライアント側で脆弱性のあるコードを排除できる訳じゃない。

たとえばあるアプリで

function deleteAllMessages() {
  // アプリに登録されている全メッセージを消去する!
  ...
}

みたいなJavaScriptが定義されてたとして、これは必ず

function confirmDelete() {
  if (confirm('Deleting All Messages.')) {
    deleteAllMessages();
  }
}

という関数を介して呼ばれていたとする。
このアプリではdeleteするためには必ずconfirmによる確認ダイアログを介するように設計されているため、これだけでは何も不都合はない。

ただ、もしこのアプリの中で利用されているJSONPクライアントの実装が、コールバック関数名指定において外部入力に依存した値(URLパラメータなど)を利用するように設計されてたら、どんなにJSONPサーバ側が文字を制限してサニタイズ(?)していようと

http://api.search.yahoo.com/ImageSearchService/V1/imageSearch?appid=YahooDemo&query=Madonna&output=json&callback=deleteAllMessages

という呼び出しをされる事で、ユーザに通知される事なく外部からデータ破壊が出来てしまう。


結局、パラメータに指定する関数名(文字列)というのは、そのままeval()を実行するものとして扱うべきなのではないか。任意の文字列にしろ関数名にしろ、それが自分のコード上で何を表すかはちゃんとJavaScriptのコードを書く側が認識していなければ行けないレベルのものであって、サーバ側がそれに何か対処してくれるとは考えない方がいい。

むしろサーバ側は純粋に「パラメータで与えられた文字列をJSONデータ(を括弧でくくったもの)にpre-paddingし、そのままアウトプットとして返すサービス」として単純化した方が、クライアント側(JSONサービスを利用する側)で脆弱性のあるコードを書かないように注意喚起が出来るのではないだろうか。


(追記 07/01/13)
padding部分に任意の文字列を許すことの脆弱性の考察について、下記の記事をご覧ください。
上記文章では指摘されている視点(インクルードされる側のリスク)が欠けています。
http://labs.cybozu.co.jp/blog/kazuho/archives/2007/01/jsonp-security.php