Статья A.S Groups

Content Security Policy в WordPress: как настроить CSP без поломки сайта

Content Security Policy для WordPress: защищённые источники скриптов и безопасный rollout CSP

Навигация по статье

Услуги A.S Groups

Нужен сайт, магазин или автоматизация?

Помогаю бизнесу запускать и дорабатывать WordPress-проекты: от посадочной страницы до WooCommerce, CRM и Telegram-уведомлений.

Обсудить проект Telegram
WordPress под ключ Лендинги, корпоративные сайты и структура под заявки. WooCommerce Интернет-магазины, каталог, оплата, доставка и интеграции. Доработка сайта Правки, скорость, формы, баги и развитие текущего проекта. CRM / Telegram / AI Автоматизация заявок, уведомлений и ручных процессов.

Content Security Policy в WordPress — это дополнительный уровень защиты браузера, который ограничивает, откуда страница может загружать и выполнять скрипты, стили, iframe, изображения и другие ресурсы. Правильно настроенная CSP помогает уменьшить последствия внедрения вредоносного кода, но неправильно настроенная политика способна сразу сломать checkout, формы, аналитику, Elementor, видеовиджеты и внешние интеграции.

Поэтому CSP для WordPress лучше внедрять не как «один заголовок из генератора», а как контролируемый rollout: сначала увидеть реальное поведение сайта, затем ограничить источники и только после тестирования включать блокировку.

Что именно делает CSP

Спецификация Content Security Policy Level 3 определяет механизм, который позволяет сайту управлять ресурсами, разрешёнными для загрузки и выполнения. CSP полезна как defense-in-depth: она снижает возможности вредоносного кода после инъекции, но не заменяет валидацию данных, экранирование вывода, обновления и устранение самой уязвимости.

Для WordPress это особенно важно, потому что одна страница может собираться из ядра, темы, нескольких плагинов, inline-скриптов и внешних сервисов. Политика должна учитывать фактическую архитектуру конкретного сайта.

Почему нельзя сразу включать строгий Content-Security-Policy

Если поставить script-src 'self' на сайте, который использует Google Analytics, платежный виджет, Turnstile, карту, чат или CDN, браузер начнёт блокировать эти ресурсы. На первый взгляд страница может выглядеть нормально, а ошибка проявится только при отправке формы или оплате.

Поэтому безопаснее начинать с Content-Security-Policy-Report-Only. W3C прямо предусматривает этот режим для наблюдения за нарушениями без принудительной блокировки. Он позволяет собрать список реальных источников и увидеть, что сломалось бы при enforcement.

Report-Only — обязательный этап для рабочего сайта

В режиме Report-Only браузер оценивает политику и сообщает о нарушениях, но продолжает загружать ресурс. Это удобно для production, где нельзя экспериментировать ценой неработающего checkout.

Практический процесс выглядит так:

  1. собрать текущие внешние домены и inline-скрипты;
  2. добавить базовую Report-Only политику;
  3. пройти ключевые пользовательские сценарии;
  4. собрать нарушения из браузера и endpoint отчётов;
  5. отделить нужные источники от случайных и устаревших;
  6. ужесточить директивы;
  7. только после проверки переключить заголовок на enforcement.

Какие директивы встречаются чаще всего

У CSP много директив, но для WordPress обычно начинают с нескольких основных.

  • default-src задаёт fallback для типов ресурсов, у которых нет отдельной директивы;
  • script-src управляет JavaScript;
  • style-src ограничивает CSS;
  • img-src — изображения;
  • font-src — шрифты;
  • connect-src — fetch, XHR, WebSocket и другие соединения;
  • frame-src — загружаемые iframe;
  • frame-ancestors ограничивает, кто может встраивать вашу страницу;
  • object-src обычно можно сильно ограничить на современных сайтах.

Нельзя копировать список доменов из другого проекта: даже два WordPress-сайта на одинаковой теме могут иметь разные аналитические и рекламные интеграции.

script-src — самый чувствительный участок

MDN отмечает, что script-src контролирует не только внешние файлы JavaScript, но и inline-скрипты и обработчики. Именно поэтому WordPress-проект часто сталкивается с проблемой 'unsafe-inline'.

Просто разрешить 'unsafe-inline' легко, но это заметно ослабляет смысл CSP. Более строгий вариант — использовать nonce или hashes для доверенных inline-блоков. Подробности описаны в MDN script-src.

Что такое nonce и почему он должен меняться

Nonce — случайное значение, которое сервер добавляет одновременно в CSP и в доверенный <script>. Браузер запускает скрипт только при совпадении значения.

Nonce должен быть непредсказуемым и уникальным для каждого ответа. Статическая строка, прописанная раз и навсегда в конфиге Nginx, не даёт нужной модели доверия. Именно поэтому nonce-подход в WordPress требует интеграции с генерацией HTML, а не только изменения заголовка веб-сервера.

Hashes подходят для стабильных inline-блоков

Для статического inline-скрипта можно разрешить конкретный SHA-256/384/512 hash. Но любое изменение пробелов или содержимого меняет hash. На WordPress, где плагины могут генерировать динамические inline-настройки, такой способ подходит не для каждого блока.

В итоге на реальном проекте часто используется комбинация: внешние источники с точным allowlist, nonce для динамических доверенных скриптов и hashes для действительно стабильных фрагментов.

Elementor, WooCommerce и плагины требуют инвентаризации

Конструкторы и плагины могут добавлять inline CSS/JS, JSON-конфигурацию, динамические загрузчики и запросы к внешним доменам. Поэтому CSP нужно тестировать на всех шаблонах, а не только на главной странице.

Для WooCommerce отдельно проверяются каталог, карточка товара, корзина, checkout, личный кабинет и платёжный сценарий. Даже если CSP не блокирует интерфейс магазина, она может мешать 3-D Secure iframe, токенизации карты или callback-скрипту платёжного провайдера.

Turnstile требует собственных разрешений

Если сайт использует Cloudflare Turnstile, Cloudflare указывает, что CSP должна разрешать его скрипты и iframe. В документации перечислены https://challenges.cloudflare.com для script-src и frame-src; также поддерживается nonce-based подход. Актуальные требования стоит брать из официальной документации Cloudflare, а не из старого примера в блоге.

Практическую установку Turnstile на формы WordPress я отдельно разбирал в статье Cloudflare Turnstile для WordPress.

Где задавать CSP: сервер, CDN или WordPress

Предпочтительный способ доставки политики — HTTP response header. Технически CSP можно добавить на уровне Nginx/Apache, CDN или PHP. Выбор зависит от того, нужна ли статическая политика или динамический nonce.

Статические директивы удобно контролировать на веб-сервере или reverse proxy. Если же nonce должен создаваться для каждого запроса и попадать в теги WordPress, появляется логика на уровне приложения.

Важно иметь один понятный источник политики. Когда часть CSP добавляет Nginx, часть security-плагин, а часть CDN, диагностика становится сложнее: браузер применяет несколько политик одновременно, и результат может оказаться строже, чем ожидалось.

Не начинайте с огромного allowlist

Бессмысленно разрешить https:, все wildcard-домены и 'unsafe-inline', а затем считать задачу выполненной. Такая политика может почти не ограничивать вредоносный сценарий.

Цель — минимальный набор действительно необходимых источников. Если сайт больше не использует старый чат или аналитический сервис, его домен не должен оставаться в CSP «на всякий случай».

Проверка после включения enforcement

  • главная и ключевые лендинги открываются без CSP errors;
  • Elementor/тема корректно выполняют интерактивные скрипты;
  • формы отправляются;
  • Turnstile/reCAPTCHA загружаются;
  • аналитика и рекламные события отправляются;
  • WooCommerce checkout проходит до успешной оплаты;
  • личный кабинет и AJAX-функции работают;
  • видео, карты, чаты и iframe не блокируются;
  • административная часть не получает неожиданных ограничений;
  • отчёты CSP продолжают контролироваться после релиза.

CSP не заменяет базовую безопасность WordPress

CSP полезна против части последствий content injection, но она не обновляет уязвимый плагин, не исправляет SQL injection, не делает пароль сильнее и не создаёт резервную копию. Нужен комплексный подход, который я описывал в материале Безопасность WordPress на практике.

Если сайт давно не обслуживался, сначала разумно устранить очевидные проблемы обновлений и доступа, а затем добавлять строгие browser-level ограничения.

Как внедрять CSP без хаоса

Я начинаю с аудита фактических ресурсов сайта и ключевых сценариев. Затем формирую Report-Only политику, убираю ненужные внешние зависимости и постепенно перевожу inline-код на безопасные механизмы там, где это технически оправдано.

После включения enforcement проверяю не только визуальную часть, но и реальные действия: отправку форм, оплату, авторизацию, AJAX, webhooks со стороны браузера и внешние виджеты. При необходимости такую работу можно включить в техническую поддержку WordPress.

Если нужна CSP для рабочего WordPress или WooCommerce без экспериментов на пользователях, пришлите ссылку и список критичных интеграций. Сначала проверю текущие источники и предложу безопасный план rollout через Report-Only.

Следующий шаг

Нужно решить похожую задачу?

Предложить аудит фактически загружаемых ресурсов и поэтапный rollout CSP через Report-Only; не обещать, что CSP заменяет обновления и устранение XSS.

Обсудить задачу

Источники

Обсуждение

Вопросы и комментарии

Можно уточнить детали статьи или поделиться своим опытом. Первый комментарий проходит проверку.

Оставить комментарий

Email не публикуется. Ссылки и HTML в тексте удаляются.

Мы используем приватную аналитику SlimStat, чтобы понимать, какие страницы полезны посетителям, и улучшать сайт. IP-адреса анонимизируются и хэшируются. Вы можете согласиться или отказаться от аналитики.
Cookies и конфиденциальность

Используем необходимые cookies, аналитику и данные форм, чтобы сайт работал корректно и заявки доходили.