- 見た目が同じでも安全性はまったく違います
- html()がしていること
- XSSとは何か
- text()の挙動
- なぜjQueryに2つ存在するのか
- 実際に起きる事故
- 「サーバでエスケープしているから大丈夫」は危険
- 安全な書き方
- jQueryの設計意図
- よくある誤解
- 結局どう使い分けるべきか
見た目が同じでも安全性はまったく違います
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アプリケーションにおける「文書」と「データ」を分ける境界線です。ここを理解すると、フロントエンドのセキュリティの見方が大きく変わります。