CSP перечисляет, откуда браузеру разрешено загружать ресурсы. Всё, чего нет в списке, блокируется. Это означает, что даже если злоумышленник сумеет вставить в страницу свой скрипт, браузер откажется его выполнять.
Content-Security-Policy: default-src 'self'; img-src 'self' data: https:; script-src 'self' https://mc.yandex.ru
Основные директивы
- default-src — правило по умолчанию для всего, что не указано отдельно;
- script-src — откуда можно грузить и выполнять скрипты;
- style-src — стили;
- img-src — изображения;
- font-src — шрифты;
- connect-src — куда можно отправлять запросы (fetch, XHR, WebSocket);
- frame-ancestors — кто может встраивать ваш сайт в iframe (замена устаревшему
X-Frame-Options); - form-action — куда могут отправляться формы.
Значения: 'self' — свой домен, 'none' — запретить всё, конкретный домен, data: — data-URI.
Почему это сложно
Строгая политика ломает сайты. Типичные препятствия:
- Инлайн-скрипты и стили (
<script>код</script>,style="...") блокируются, если не разрешить'unsafe-inline'— а разрешение обесценивает половину защиты. - Сторонние сервисы. Счётчики, чаты, карты, платёжные виджеты грузят ресурсы со своих доменов, часто с нескольких сразу и не документируя список.
- Плагины CMS добавляют инлайн-код без предупреждения.
Правильное решение для инлайн-скриптов — nonce: случайное значение, которое генерируется на каждый запрос и ставится и в заголовок, и в тег.
Content-Security-Policy: script-src 'self' 'nonce-r4nd0m'
<script nonce="r4nd0m">/* этот скрипт разрешён */</script>
Как внедрять без риска
Есть режим наблюдения — политика не применяется, но нарушения собираются:
Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report
Порядок работы:
- Включите
Report-Onlyс политикой, которую хотите получить. - Неделю собирайте отчёты (или смотрите ошибки в консоли браузера — они там появляются и в этом режиме).
- Дополните политику найденными легитимными источниками.
- Когда нарушений не остаётся, переключите на боевой заголовок.
Спешить некуда: CSP — единственный заголовок из этого раздела, который стоит внедрять неделями.
Полезный минимум
Если полноценная политика пока не по силам, начните с одной директивы:
add_header Content-Security-Policy "frame-ancestors 'self'" always;
Она запрещает встраивать ваш сайт в чужие iframe и защищает от кликджекинга — атаки, когда поверх вашего интерфейса накладывают невидимый слой. Ломает она разве что случаи, где сайт встраивают намеренно.
Рядом стоит настроить Permissions-Policy: она тем же способом отбирает у чужих скриптов доступ к камере, микрофону и геолокации.
Вторая по полезности:
add_header Content-Security-Policy "upgrade-insecure-requests" always;
Автоматически подставляет https:// вместо http:// в запросах ресурсов — временное лекарство от смешанного контента.
Как проверить
- Пункт аудита «Content-Security-Policy».
F12→ Console: нарушения выводятся с указанием заблокированного ресурса и директивы.- Сервис
csp-evaluator.withgoogle.comразбирает политику и показывает слабые места.