制作Note

WordPressのHTMLサニタイゼーション関数について

HTMLサニタイゼーション関数は、ユーザーから入力されたHTMLコードから危険な要素を除去し、安全なコンテンツのみを保持する重要なセキュリティ機能です。

WordPressカスタマイズにおいて、この機能はXSS(クロスサイトスクリプティング)攻撃の防止に不可欠です。悪意のあるJavaScriptコードや不正なHTMLタグが投稿やコメントに混入することを防ぎ、サイトの安全性を確保します。

特にカスタムフィールドやユーザー投稿機能を実装する際、wp_kses()、wp_kses_post()、wp_strip_all_tags()などの関数を適切に使い分けることで、必要なHTMLタグのみを許可し、セキュリティリスクを最小限に抑えられます。

これらの関数は単なるセキュリティ対策にとどまらず、コンテンツの品質管理やSEO最適化にも貢献します。メタディスクリプション生成時にHTMLタグを除去したり、検索機能でのテキスト比較を正確に行うなど、WordPress開発における基礎的かつ重要な機能として位置づけられています。

wp_strip_all_tags()

基本機能

すべてのHTMLタグを完全に削除し、純粋なテキストのみを残します。

使用例

$html = '<wp-p>こんにちは<strong>世界</strong>!<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%3Ealert(%22%E5%8D%B1%E9%99%BA%22)%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="<script>" title="<script>" /></wp-p>';
$clean_text = wp_strip_all_tags($html);
// 結果: "こんにちは世界!alert("危険")"

パラメータ

wp_strip_all_tags($string, $remove_breaks = false)
  • $string
    : 処理対象の文字列
  • $remove_breaks
    : true の場合、改行も削除

適用場面


  • メタディスクリプション生成

  • 検索機能での文字列比較

  • プレーンテキストが必要な場面

wp_kses_post()

基本機能

WordPressの投稿で許可されている安全なHTMLタグのみを保持します。

許可されるタグの例

// 許可されるタグ(一部)
$allowed_tags = array(
    'a' => array('href', 'title', 'class', 'id'),
    'p' => array('class', 'id'),
    'strong' => array('class'),
    'em' => array('class'),
    'img' => array('src', 'alt', 'width', 'height', 'class'),
    'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
    'ul', 'ol', 'li',
    'blockquote' => array('cite'),
    // など
);

使用例

$html = '<wp-p>安全なコンテンツ</wp-p><img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%3Ealert(%22%E5%8D%B1%E9%99%BA%22)%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="<script>" title="<script>" />';
$safe_html = wp_kses_post($html);
// 結果: "<wp-p>安全なコンテンツ</wp-p>alert("危険")"

適用場面


  • ユーザー投稿の保存前処理

  • コメントの表示

  • カスタムフィールドの出力

wp_kses()

基本機能

指定したHTMLタグとその属性のみを許可する、最も柔軟なサニタイゼーション関数です。

使用例

// 基本的な使用方法
$allowed_html = array(
    'p' => array(
        'class' => array(),
        'id' => array(),
    ),
    'a' => array(
        'href' => array(),
        'title' => array(),
        'target' => array(),
    ),
    'strong' => array(),
    'em' => array(),
);

$html = '<wp-p class="text">テスト<a href="#" onclick="alert()">リンク</a></wp-p>';
$clean_html = wp_kses($html, $allowed_html);
// 結果: '<wp-p class="text">テスト<a href="#">リンク</a></wp-p>'

高度な設定例

// より詳細な制御
$allowed_html = array(
    'img' => array(
        'src' => array(),
        'alt' => array(),
        'width' => array(),
        'height' => array(),
        'class' => array(),
        'style' => array(), // CSSも制御可能
    ),
    'div' => array(
        'class' => array(),
        'data-*' => true, // data属性を許可
    ),
);

// プロトコル指定も可能
$allowed_protocols = array('http', 'https', 'mailto');
$clean_html = wp_kses($html, $allowed_html, $allowed_protocols);

実用的な使い分け

1. セキュリティレベル別使い分け

// 最高セキュリティ:HTMLを一切許可しない
$title = wp_strip_all_tags($user_input);

// 高セキュリティ:投稿レベルのHTMLのみ許可
$content = wp_kses_post($user_input);

// カスタムセキュリティ:特定のタグのみ許可
$custom_content = wp_kses($user_input, $custom_allowed_tags);

2. 用途別実装例

// カスタムフィールド保存時
function save_custom_field($value) {
    $allowed_html = array(
        'p' => array('class' => array()),
        'br' => array(),
        'strong' => array(),
        'em' => array(),
    );
    return wp_kses($value, $allowed_html);
}

// ユーザープロフィール表示
function display_user_bio($bio) {
    // リンクのみ許可
    $allowed_html = array(
        'a' => array(
            'href' => array(),
            'title' => array(),
            'target' => array(),
        )
    );
    return wp_kses($bio, $allowed_html);
}

// 検索用テキスト準備
function prepare_search_text($content) {
    return wp_strip_all_tags($content, true); // 改行も削除
}

3. パフォーマンス考慮

// 重い処理なので、必要な時のみ実行
function sanitize_content($content, $context = 'post') {
    switch ($context) {
        case 'title':
            return wp_strip_all_tags($content);
        case 'excerpt':
            return wp_kses_post($content);
        case 'custom':
            return wp_kses($content, get_custom_allowed_html());
        default:
            return wp_kses_post($content);
    }
}