0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【図解】サニタイズとエスケープの違いをコード例で理解する

0
Posted at

はじめに

「サニタイズ」と「エスケープ」、どちらもセキュリティ対策で使われる用語ですが、違いを正確に説明できますか?

この記事では、両者の違いをコード例と図解で分かりやすく解説します。

結論:一言でいうと

処理 目的 データへの影響
サニタイズ 危険な部分を 除去・無害化 する 一部が失われる
エスケープ 特殊文字を 別の表記に変換 する 保持される

サニタイズとは

サニタイズ(sanitize)は「消毒する」という意味で、危険な部分を取り除く処理です。

コード例(Python)

import re

def sanitize(text: str) -> str:
    """scriptタグを除去する"""
    return re.sub(r'<script.*?>.*?</script>', '', text, flags=re.DOTALL)

# 使用例
user_input = "<script>alert('XSS')</script>こんにちは"
result = sanitize(user_input)
print(result)  # → "こんにちは"

処理のイメージ

入力: "<script>alert('XSS')</script>こんにちは"
        ↓ サニタイズ(除去)
出力: "こんにちは"

サニタイズでは、危険と判断された部分が完全に消えます。元のデータの一部が失われることを意識しましょう。

エスケープとは

エスケープ(escape)は、特殊文字を無害な別の表記に変換する処理です。

コード例(Python)

import html

def escape(text: str) -> str:
    """HTMLの特殊文字をエスケープする"""
    return html.escape(text)

# 使用例
user_input = "<script>alert('XSS')</script>"
result = escape(user_input)
print(result)  # → "&lt;script&gt;alert('XSS')&lt;/script&gt;"

処理のイメージ

入力: "<script>alert('XSS')</script>"
        ↓ エスケープ(変換)
出力: "&lt;script&gt;alert('XSS')&lt;/script&gt;"

ブラウザで表示すると、<script>alert('XSS')</script> という文字列がそのまま見える(実行はされない)。

エスケープでは元のデータ内容は保持されます。表示上は元の文字として見えますが、コードとしては実行されません。

変換対応表(HTMLエスケープ)

元の文字 エスケープ後
< &lt;
> &gt;
& &amp;
" &quot;
' &#x27;

使い分けの指針

エスケープを使うケース

ユーザー入力をそのまま表示したい場合に使います。

# コメント投稿など、入力内容をそのまま表示したい場合
user_comment = "<b>太字にしたかった</b>"
escaped = html.escape(user_comment)
# → "&lt;b&gt;太字にしたかった&lt;/b&gt;" として表示される

サニタイズを使うケース

一部のHTMLタグは許可しつつ、危険なタグは除去したい場合に使います。

import bleach

def sanitize_rich_text(text: str) -> str:
    """許可されたタグのみ残し、他は除去"""
    allowed_tags = ['b', 'i', 'u', 'a', 'p', 'br']
    return bleach.clean(text, tags=allowed_tags, strip=True)

# 使用例
user_input = "<b>太字</b><script>alert('XSS')</script>"
result = sanitize_rich_text(user_input)
print(result)  # → "<b>太字</b>alert('XSS')"

bleachライブラリはpip install bleachでインストールできます。

実践:Pydanticでの実装例

FastAPIなどで使われるPydanticでは、バリデーターを使って入力時にエスケープ処理を入れられます。

from pydantic import BaseModel, field_validator
import html

class CommentRequest(BaseModel):
    content: str
    
    @field_validator('content')
    @classmethod
    def escape_content(cls, v: str) -> str:
        return html.escape(v.strip())

再利用可能なカスタム型として定義

from typing import Annotated
from pydantic import BaseModel, BeforeValidator
import html

# エスケープ関数
def escape_html(v: str) -> str:
    return html.escape(v.strip())

# カスタム型として定義
EscapedStr = Annotated[str, BeforeValidator(escape_html)]

# どのモデルでも使い回せる
class CommentRequest(BaseModel):
    content: EscapedStr

class PostRequest(BaseModel):
    title: EscapedStr
    body: EscapedStr

多層防御の考え方

サニタイズ・エスケープだけでは不十分です。多層防御を心がけましょう。

対策場所 方法
入力時 Pydanticなどでバリデーション・エスケープ
出力時 テンプレートエンジンの自動エスケープ
HTTP Content-Security-Policyヘッダー
Cookie httponly属性、secure属性

まとめ

項目 サニタイズ エスケープ
処理内容 危険な部分を除去 特殊文字を変換
データ 一部が失われる 保持される
主な用途 リッチエディタ、ファイル名 コメント表示、ログ出力
ライブラリ例 bleach, DOMPurify html.escape, textContent

参考

0
1
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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?