jQueryのhtml()とtext()の違いをXSSの観点で解説する

見た目が同じでも安全性はまったく違います

jQueryで要素に文字列を入れるとき、多くの人が最初に覚えるのが次の2つです。

$('#msg').html('Hello');
$('#msg').text('Hello');

画面上の見た目は同じです。しかし結論から言うと、この2つは役割がまったく違う関数です。特にユーザー入力を扱う場合、安全性に大きな差が生まれます。

違いは単純です。

  • html():HTMLとして解釈して挿入する
  • text():文字列として挿入する

この違いが、XSS(クロスサイトスクリプティング)という脆弱性に直結します。

html()がしていること

html()はinnerHTMLのラッパーです。

$('#msg').html('<b>bold</b>');

結果は太字になります。つまりタグがDOMとして解釈されています。文字列を「文書」として扱っています。

これは便利ですが、同時に危険でもあります。

XSSとは何か

XSSは、ユーザーが入力した内容がそのままHTMLとして実行されてしまう問題です。例えば掲示板を想像してください。

ユーザーが次の内容を投稿します。

<script>alert('XSS')</script>

もしサーバやJavaScriptがこれをhtml()で表示すると、スクリプトが実行されます。閲覧者のブラウザで任意のJavaScriptが動作します。

つまりhtml()は「文字表示関数」ではなく、HTML挿入関数です。

text()の挙動

一方、text()は違います。

$('#msg').text('<b>bold</b>');

画面には

bold

と表示されます。タグは実行されません。なぜならtext()はtextContentを使い、DOMノードを生成しないからです。単なるテキストノードとして挿入します。

これにより、スクリプトも実行されません。

なぜjQueryに2つ存在するのか

これは機能の重複ではありません。用途が違います。

メソッド 用途
html() テンプレート描画
text() ユーザー入力表示

例えばサーバから返ってきた整形済みHTMLを表示する場合はhtml()です。しかしフォーム入力値を表示するならtext()でなければなりません。

実際に起きる事故

検索結果ページで「あなたの検索語」を表示する処理です。

$('#keyword').html(location.search);

ユーザーが細工したURLを開くだけで、スクリプトが実行される可能性があります。これが実際のXSSの典型例です。

「サーバでエスケープしているから大丈夫」は危険

サーバ側でエスケープしていても安全とは限りません。

  • 二重デコード
  • URLパラメータ
  • Ajaxレスポンス

クライアント側で再度HTMLとして解釈すると危険が残ります。html()は常に「HTMLとして評価する」関数です。

安全な書き方

ユーザー入力を表示する場合はtext()を使います。

$('#comment').text(userInput);

もし改行や装飾が必要なら、サーバ側で明示的にHTMLを生成するか、許可タグのみをフィルタリングします。クライアントでhtml()に直接渡すのは避けるべきです。

jQueryの設計意図

jQueryは安全対策を自動で行いません。代わりに「選択できる」ようにしています。

  • html():自由度が高いが危険
  • text():制限されるが安全

つまりセキュリティは開発者の責任です。

よくある誤解

html()の方が高機能で、text()が簡易版と思われがちですが逆です。text()は安全なデフォルトに近く、html()は意図的に使う関数です。

結局どう使い分けるべきか

判断基準は一つです。

その文字列は「信頼できるか」

  • 自分が書いた固定テンプレート → html()
  • ユーザー入力・URL・外部データ → text()

この基準を守るだけで、多くのXSSは防げます。

jQueryのhtml()とtext()の違いは単なる表示方法の違いではありません。Webアプリケーションにおける「文書」と「データ」を分ける境界線です。ここを理解すると、フロントエンドのセキュリティの見方が大きく変わります。