Что такое Content-Security-Policy
Content-Security-Policy (CSP) — HTTP-заголовок, который сообщает браузеру, откуда сайту разрешено загружать скрипты, стили, картинки, шрифты и фреймы и куда отправлять данные. Если злоумышленнику удастся внедрить на страницу вредоносный скрипт — через уязвимый плагин, поле комментария или взломанный сторонний сервис, — браузер откажется его выполнять, потому что источник не входит в список разрешённых. CSP не заменяет исправление уязвимостей, но превращает многие из них из катастрофы в неприятность.
Основные директивы
| Директива | Что ограничивает | Типичное значение |
|---|---|---|
| default-src | Всё, что не задано отдельно | 'self' |
| script-src | JavaScript | 'self' + домены аналитики и CDN |
| style-src | CSS | 'self' 'unsafe-inline' (часто нужно CMS) |
| img-src | Картинки | 'self' data: + домены счётчиков |
| connect-src | fetch, XHR, WebSocket | 'self' + API и аналитика |
| frame-src | Встраиваемые фреймы | Видеохостинги, карты, капча |
| object-src | Плагины | 'none' |
| frame-ancestors | Кто может встроить ваш сайт | 'self' или 'none' |
| form-action | Куда отправляются формы | 'self' + платёжные шлюзы |
Пресеты популярных сервисов
Самое трудоёмкое в CSP — собрать все домены, которые использует сайт. Яндекс Метрике нужны mc.yandex.ru для скриптов, картинок-пикселей и соединений, yastatic.net — для части скриптов, а Вебвизору — фреймы. Google Analytics 4 использует googletagmanager.com и поддомены google-analytics.com. Google Fonts — две разные зоны для стилей и для самих файлов шрифтов. Пресеты генератора содержат такие наборы; но сервисы иногда меняют домены, поэтому проверяйте работу сайта в режиме Report-Only.
Как внедрять, ничего не сломав
- Report-Only. Заголовок Content-Security-Policy-Report-Only ничего не блокирует, только пишет нарушения в консоль и, если указан report-uri, отправляет отчёты. Поставьте его на рабочий сайт.
- Соберите нарушения. Пройдите ключевые сценарии: оформление заказа, оплату, формы, личный кабинет. Добавьте недостающие источники в поля тонкой настройки.
- Подождите. Неделя трафика покажет редкие сценарии: виджеты, которые грузятся по условию, A/B-тесты, рекламные пиксели.
- Включите блокировку. Снимите Report-Only. Следите за ошибками в первые дни после включения.
- Поддерживайте. Подключаете новый сервис — сначала добавьте его в CSP.
unsafe-inline и unsafe-eval: когда без них нельзя
Самая сильная защита CSP — запрет встроенных скриптов (inline). Но многие сайты используют встроенные скрипты: код счётчиков, данные для фреймворков, обработчики в атрибутах. Если разрешить 'unsafe-inline' в script-src, защита от XSS становится существенно слабее. Правильная альтернатива — nonce (случайная метка, которую сервер генерирует для каждого ответа и ставит на разрешённые скрипты) или hash конкретного скрипта. Современные фреймворки, включая Next.js, умеют работать с nonce. Для стилей 'unsafe-inline' — меньшее зло и часто приемлемый компромисс.
Где прописать заголовок
- nginx — директива add_header в блоке server или location; ключ always нужен, чтобы заголовок отдавался и на страницах ошибок.
- Apache — Header always set в конфигурации или .htaccess (нужен модуль mod_headers).
- Next.js — функция headers() в next.config или middleware, если нужен nonce.
- Meta-тег — запасной вариант, если доступа к серверу нет. Ограничения: не поддерживает frame-ancestors, report-uri и режим Report-Only.
CSP — один из заголовков безопасности. Вместе с ним стоит настроить HSTS, X-Content-Type-Options, Referrer-Policy и Permissions-Policy; перечень проверок есть в чек-листе OWASP. Если сайт уже взломали, начните с пошагового плана. Для защиты почтового домена от подделки используйте генератор SPF, DKIM и DMARC.
Пример политики для типичного сайта
Сайт на CMS с Яндекс Метрикой, шрифтами Google Fonts и видео с YouTube в статьях. Базовые директивы — 'self' для всего. В script-src добавляются mc.yandex.ru и yastatic.net, в connect-src — mc.yandex.ru и wss://mc.yandex.ru для Вебвизора, в img-src — mc.yandex.ru и data: для мелких иконок. Для шрифтов — fonts.googleapis.com в style-src и fonts.gstatic.com в font-src. Для видео — youtube.com и youtube-nocookie.com в frame-src. Плюс object-src 'none', base-uri 'self' и frame-ancestors 'self'. Стили CMS обычно требуют 'unsafe-inline' в style-src. Такая политика ставится сначала в режиме Report-Only; если через неделю в консоли нет нарушений на ключевых страницах, режим отключается и политика начинает блокировать всё лишнее.
Вопросы и ответы
Сломает ли CSP мой сайт?
Может, если сразу включить блокировку. Поэтому начинайте с Content-Security-Policy-Report-Only: он только сообщает о нарушениях. Блокировку включайте, когда сообщений не останется.
Нужен ли CSP небольшому сайту?
Да, особенно на популярных CMS с плагинами. Большинство массовых взломов — внедрение скриптов через уязвимые расширения, и CSP заметно снижает их последствия.
Почему 'unsafe-inline' — это плохо?
Потому что внедрённый злоумышленником скрипт обычно и есть встроенный. Разрешив inline-скрипты, вы разрешаете и его. Используйте nonce или hash.
Генератор проверяет мой сайт?
Нет. Страница не делает запросов к вашему или другим сайтам — она только собирает строку политики из выбранных параметров.
Чем frame-ancestors отличается от X-Frame-Options?
Обе защищают от встраивания сайта в чужой фрейм. frame-ancestors — современная замена с гибкими правилами; X-Frame-Options можно оставить для старых браузеров.
Как узнать, какие домены использует мой сайт?
Откройте сайт с политикой в режиме Report-Only и посмотрите консоль браузера (F12 → Console) и вкладку Network на ключевых страницах: каждое нарушение политики там отображается с адресом источника.
