LoginSignup
10
10

More than 5 years have passed since last update.

jQueryのAjaxでJavaScriptファイルを取得するときの罠

Posted at

jQuery.ajaxを使って静的なJSファイルを取得しようとしたのですが、
取得するだけのつもりが勝手に実行されてしまいましたというお話。

しかも、こちらのコードのようにJSファイルが自らのJSファイルを読み込む機構にしてしまったため、意図せず無限ループを生み出してしまいました。
http://jsdo.it/butchi/GMl6

もっとわかりやすいコードで説明すると、main.jsがAjaxでtest.jsを取得したときに、
コールバックのalert(res)が実行される前に
test.jsに記述したalert("hoge")が実行されてしまいます。

index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Ajaxの罠</title>
</head>
<body>

<script src="jquery.js"></script>
<script src="main.js"></script>
</body>
</html>
main.js
$.ajax({
  url: 'test.js',
  success: function(res) {
    alert(res); // => 'alert("hoge")'
  }
});
test.js
alert('hoge');

種明かし

jQuery v2.1.4のコードをざっと見てみると、このような記述が見つかりました。

jquery.js
// Install script dataType
jQuery.ajaxSetup({
    accepts: {
        script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
    },
    contents: {
        script: /(?:java|ecma)script/
    },
    converters: {
        "text script": function( text ) {
            jQuery.globalEval( text );
            return text;
        }
    }
});

(8651行あたりから抜粋)

たぶんレスポンスがスクリプトの形式だったときにdataTypeが'script'とみなされ、
evalしてしまう仕様のようです。

evalを避けるためには、dataTypeオプションを'text'とかに設定するとよいみたいでした。

main.js
$.ajax({
  url: 'test.js',
  dataType: 'text',
  success: function(res) {
    alert(res);
  }
});

もっと古いコード

ちなみにv1.2.2について記述しているこちらの記事では

jQuery.httpData()
というメソッドが

httpData: function( r, type ) {
  var ct = r.getResponseHeader("content-type");
  var xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0;
  var data = xml ? r.responseXML : r.responseText;

  if ( xml && data.documentElement.tagName == "parsererror" )
    throw "parsererror";

  // If the type is "script", eval it in global context
  if ( type == "script" )
    jQuery.globalEval( data );

  // Get the JavaScript object, if JSON is used.
  if ( type == "json" )
    data = eval("(" + data + ")");

  return data;
},

となっており、JSONに対してevalを使っていたみたいなので、
もしかしたらJSONファイルに任意のスクリプトを書いて実行できる脆弱性があったのかもしれません。

まとめ

jQueryはいろいろいい感じにやってくれる分、謎挙動も汲みながら扱っていく気概が必要ですね。

10
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
10