Политика содержимого безопасности Написание заголовка CSP, который действительно работает
Большинство разработчиков знают, что им следует добавить заголовок политики безопасности содержимого в свои приложения. Мало кто имеет такую политику, которая действительно выполняет полезные действия. Либо она слишком разрешающая и лишает смысла, либо она нарушает половину сайта и удаляется из-за раздражения.
Этот гайд описывает, что делает политика безопасности содержимого, какие директивы важны и как написать заголовок, который блокирует реальные атаки, не нарушая работу вашего приложения.
Что делает политика безопасности содержимого на самом деле
Политика безопасности содержимого устанавливает, откуда разрешено загружать ресурсы в браузере. Скрипты только из этого домена. Стили — из этого CDN. Изображения — из любого источника. Нет встроенных скриптов.
Когда браузер получает заголовок политики безопасности содержимого, он применяет эти правила до выполнения каких-либо действий. Если атака XSS вставляет вредоносный скрипт в HTML вашего сайта, политика безопасности содержимого блокирует его на уровне браузера — даже если скрипт прошёл проверку ввода.
Это основное значение: политика безопасности содержимого является вашей второй линией защиты, когда проверка ввода не сработала.
Директивы, которые важны
Политика безопасности содержимого имеет десятки директив, но большинство производственных заголовков требуют только шести:
| Директива | Что она ограничивает | Обычные ошибки |
|---|---|---|
default-src |
Заголовок для любого ресурса, не перечисленного явно | Параметр 'self', затем забывая, что шрифты и рамки не покрываются |
script-src |
Источники скриптов JavaScript и встроенные выполнения | Добавление 'unsafe-inline' чтобы устранить ошибки консоли |
style-src |
Источники CSS и встроенные блоки стилей | Забывание о CDN или встроенных стилях, вставленных JavaScript-библиотеками |
img-src |
Источники изображений, включая data URIs | Отсутствие data: для изображений в формате base64, blob: для экспорта из canvas |
connect-src |
Цели для XHR, fetch, WebSocket и EventSource | Забывание об аналитических конечных точках и поддоменах API |
frame-ancestors |
Какие источники могут встраивать ваш сайт в <iframe> |
Пропуск этого шага полностью — оставляя уязвимость к кликджекингу |
frame-ancestors заменяет устаревший X-Frame-Options заголовок и стоит добавить даже до того, как вы полностью покрываете политику безопасности содержимого в других местах.
Почему unsafe-inline Уничтожает суть
Когда вы добавляете 'unsafe-inline' к script-srcвы сообщаете браузеру: выполняйте любой скрипт, который вы найдёте, независимо от того, откуда он поступил. Это включает скрипты, вставленные в результате атак XSS.
'unsafe-eval' Более опасно — позволяет eval(), Function()и setTimeout("string"), которые являются распространёнными векторами атак даже в чистых кодбейсах.
Политика с этими документами не обеспечивает никакой защиты от вставки. Атакующий не заинтересован в том, откуда загружаются легальные скрипты, если он может вставить свои встроенные скрипты.
Правильный способ: нонсы и хэши
Если у вас есть легальные встроенные скрипты, у вас есть два варианта, которые не требуют отказа от политики:
Нонсы генерируют уникальный токен на каждой загрузке страницы. Сервер добавляет его в заголовок политики безопасности содержимого и в атрибут встроенного скрипта. nonce Только скрипты с совпадающим нонсом выполняются.
<!-- CSP header -->
Content-Security-Policy: script-src 'nonce-abc123xyz'
<!-- Inline script with matching nonce -->
<script nonce="abc123xyz">
window.analyticsId = '...';
</script>
Хэши вычисляют хэш SHA-256 точного содержимого скрипта. Добавьте этот хэш в script-src и браузер выполняет только этот конкретный скрипт — но не выполняет ничего другого.
Content-Security-Policy: script-src 'sha256-RFWPLDbv2BY+rCkDzsE+0fr8ylGr2R2faWMhq4lfEQc='
Нонсы работают лучше для динамических страниц, где содержимое меняется с каждым запросом. Хэши подходят для статических скриптов, которые не меняются между деплоями.
Развертывание с режимом отчета сначала
Добавление CSP в существующий сайт без тестирования — это то, как вы разрушаются в производственной среде. Начните с заголовка отчета:
Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self' 'nonce-{random}'; report-uri /csp-violations
Браузер применяет правила и отмечает нарушения — он не блокирует ничего ещё. Этот журнал нарушений показывает вам ровно то, что нужно добавить в политику до того, как вы переключитесь на режим исполнения.
Большинство развертываний CSP, которые разрушают сайты, пропустили этот шаг.
Реальная политика безопасности содержимого для типичного приложения SaaS
Вот готовый заголовок для приложения, использующего CDN, Google Analytics и Stripe. Каждая директива аннотирована:
Content-Security-Policy:
# Tight default: only load from your own origin
default-src 'self';
# Scripts: your origin, GA tag manager via nonce, Stripe.js
script-src 'self' https://www.googletagmanager.com https://js.stripe.com 'nonce-{SERVER_NONCE}';
# Styles: your origin and Google Fonts CSS
style-src 'self' https://fonts.googleapis.com;
# Fonts: your origin and Google Fonts CDN
font-src 'self' https://fonts.gstatic.com;
# Images: your origin, CDN subdomain, and base64 data URIs
img-src 'self' https://cdn.yourdomain.com data:;
# Fetch/XHR: your API, GA collection endpoint, Stripe API
connect-src 'self' https://www.google-analytics.com https://api.stripe.com;
# Stripe renders its fields in an iframe
frame-src https://js.stripe.com;
# Nobody should be framing your app
frame-ancestors 'none';
# Block <object> and <embed> entirely
object-src 'none';
# Force HTTP requests to upgrade to HTTPS
upgrade-insecure-requests;
Замените {SERVER_NONCE} с криптографически случайным значением, генерируемым на каждом запросе — например, в PHP или base64_encode(random_bytes(16)) в Node. crypto.randomBytes(16).toString('base64') Обычные ошибки политики безопасности содержимого
Широкие звёздочки, слишком широкие.
Позволяет скрипты из любого источника. Вы можете считать, что у вас вообще нет политики скриптов. script-src * Забывание о поддоменах.
Охватывает только ваш точный источник. 'self' является другим источником и требует явного включения под https://api.yourdomain.com Пропуск connect-src.
Защита от кликджекинга независима от защиты от XSS. Добавляйте её отдельно от остальных директив. frame-ancestors. Установка CSP в нескольких местах.
Если ваш CDN и ваше приложение устанавливают заголовок CSP, поведение становится непредсказуемым. Устанавливайте его в одном слое — обычно на вашем исходном сервере или в обратном прокси. без обработчика.
Использование report-uri Нарушения генерируют POST-запросы к вашему конечному пункту на каждой загруженной странице. Либо обрабатывайте их, либо направляйте на сервис, такой как Report URI. Создание заголовка без лишних усилий
Отслеживание каждого домена, из которого загружаются ресурсы, через скрипты, стили, шрифты, изображения и API-запросы, становится быстро утомительным. Онлайн-генератор заголовка политики безопасности содержимого
позволяет вам настроить каждую директиву визуально и выдает готовый заголовок, который вы можете вставить напрямую в настройки сервера. Используйте его как начальную точку, затем проверяйте фактические сетевые запросы в DevTools, чтобы найти то, что могло быть упущено генератором. Политика, слишком расслабленная, — это просто украшение. Тех, слишком строгая, — она нарушает работу пользователей. Начинайте с режима отчета, ужимайте с течением времени, и используйте нонсы там, где встроенные скрипты неизбежны. Ваша политика должна усложнять задачу атакующего, а не вас.
Используйте это как отправную точку, затем проверяйте реальные запросы к сети в DevTools, чтобы выявить то, что пропустил генератор.
Слишком релаксированный CSP — это просто украшение. Слишком строгий CSP нарушает работу пользователей. Начните в режиме отчетов, постепенно ужесточайте его и используйте нонсы при необходимости встраивания скриптов. Ваша политика должна усложнять задачу атакующего, а не вас.
Установите наши расширения
Добавьте инструменты ввода-вывода в свой любимый браузер для мгновенного доступа и более быстрого поиска
恵 Табло результатов прибыло!
Табло результатов — это интересный способ следить за вашими играми, все данные хранятся в вашем браузере. Скоро появятся новые функции!
Подписаться на новости
все Новые поступления
всеОбновлять: Наш последний инструмент была добавлена 2 мая 2026 года
