2026年5月20日

2026年5月20日

WordPressのContent Security Policy(CSP)エラーを解決する方法

はじめに

ブラウザコンソールに「Refused to load the script because it violates the following Content Security Policy directive」と表示されてJavaScriptが動かない、プラグインのスタイルがブロックされてデザインが崩れる、Google FontsやYouTubeの埋め込みが表示されない。CSPは強力なセキュリティ機能ですが、設定が厳しすぎると正常なコンテンツもブロックされます。

症状・原因

CSPエラーが発生する主な原因:

  • default-src 'self'のみ設定:外部リソースを全てブロックしている
  • unsafe-inlineの欠如:WordPressのインラインスクリプト・スタイルがブロックされる
  • 外部ドメインの未許可:Google Fonts・YouTube・Gravatar等が許可されていない
  • フレーミング制限frame-ancestors設定でiframeが使えない

解決手順

ステップ1:CSPエラーの内容を確認する

// ブラウザコンソールのエラー例
Refused to load the script 'https://www.googletagmanager.com/gtag/js'
because it violates the following Content Security Policy directive:
"script-src 'self'"
// → script-src に googletagmanager.com を追加する必要がある

ステップ2:WordPress向けの基本CSP設定

// functions.php — WordPressに適したCSPヘッダーを設定
add_action('send_headers', function() {
    $csp = implode('; ', [
        "default-src 'self'",
        
        // スクリプト:WordPress + 一般的な外部サービス
        "script-src 'self' 'unsafe-inline' 'unsafe-eval' " .
            "https://www.google-analytics.com " .
            "https://www.googletagmanager.com " .
            "https://connect.facebook.net",
        
        // スタイル:インラインスタイルとGoogle Fonts
        "style-src 'self' 'unsafe-inline' " .
            "https://fonts.googleapis.com",
        
        // フォント
        "font-src 'self' " .
            "https://fonts.gstatic.com " .
            "data:",
        
        // 画像:データURIとGravatar
        "img-src 'self' data: " .
            "https://*.gravatar.com " .
            "https://secure.gravatar.com " .
            "https://www.google-analytics.com",
        
        // フレーム:YouTube・Vimeo
        "frame-src 'self' " .
            "https://www.youtube.com " .
            "https://player.vimeo.com",
        
        // 接続先
        "connect-src 'self' " .
            "https://www.google-analytics.com",
        
        // XSS対策のアップグレード
        "upgrade-insecure-requests",
    ]);
    
    header("Content-Security-Policy: $csp");
});

ステップ3:nonceベースのCSPでinline-scriptを安全に許可する

'unsafe-inline'を使わずインラインスクリプトを許可するより安全な方法:

// functions.php — nonceベースのCSP
add_action('init', function() {
    // wp_headでnonceを生成
    $nonce = base64_encode(random_bytes(16));
    
    // スクリプトタグにnonce属性を追加するフィルター
    add_filter('script_loader_tag', function($tag, $handle) use ($nonce) {
        return str_replace('<script ', '<script nonce="' . $nonce . '" ', $tag);
    }, 10, 2);
    
    // CSPヘッダーにnonceを含める
    add_action('send_headers', function() use ($nonce) {
        header("Content-Security-Policy: script-src 'self' 'nonce-$nonce'");
    });
});

ステップ4:Report-Only モードでテストする

本番環境で直接CSPを有効化する前に、レポートモードでテストします。

// functions.php — レポートモード(ブロックせずエラーをログ)
add_action('send_headers', function() {
    header("Content-Security-Policy-Report-Only: " .
        "default-src 'self'; " .
        "report-uri /csp-report-endpoint"
    );
});

// レポートを受信するエンドポイント
add_action('rest_api_init', function() {
    register_rest_route('csp/v1', '/report', [
        'methods'  => 'POST',
        'callback' => function($request) {
            $report = $request->get_json_params();
            error_log('CSP Report: ' . json_encode($report));
            return new WP_REST_Response(null, 204);
        },
        'permission_callback' => '__return_true',
    ]);
});

ステップ5:.htaccessでCSPを設定する

<IfModule mod_headers.c>
    Header always set Content-Security-Policy "\
        default-src 'self'; \
        script-src 'self' 'unsafe-inline' https://www.googletagmanager.com; \
        style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; \
        font-src 'self' https://fonts.gstatic.com; \
        img-src 'self' data: https:; \
        frame-src https://www.youtube.com; \
        upgrade-insecure-requests"
</IfModule>

注意事項

  • 'unsafe-inline''unsafe-eval'を許可するとCSPの効果が弱まりますが、WordPressの多くのプラグインはこれらを必要とします。
  • CSPはセキュリティと利便性のトレードオフです。まずReport-Onlyモードでテストしてから本番に適用してください。

まとめ

CSPエラーはコンソールのエラーメッセージから許可が必要なドメインを特定し、対応するディレクティブ(script-srcstyle-srcfont-src等)に追加することで解決します。まずContent-Security-Policy-Report-Onlyでテストし、問題がないことを確認してから本番環境に適用しましょう。関連記事:Mixed Contentエラーの解決方法CORSエラーの解決方法

お気軽にご相談ください

お見積りへ お問い合わせへ