Content Security Policy (CSP) без поломки сайта

Security2026-09-18TryQuickToolBox

Вы слышали, что Content Security Policy (CSP) необходима для защиты сайта от межсайтового скриптинга (XSS) и атак с внедрением данных. Но когда вы пытаетесь её добавить, сайт ломается: изображения исчезают, скрипты перестают работать, стили пропадают. Кажется, что это компромисс между безопасностью и функциональностью. Но это не обязательно так.

В этом руководстве вы узнаете практический пошаговый подход к внедрению CSP без поломки сайта. Мы рассмотрим основные директивы, использование nonce и хешей, а также безопасное тестирование. В итоге у вас будет работающая CSP, которая повышает безопасность без ущерба для пользовательского опыта.

Что такое CSP и почему она ломает сайты?

Content Security Policy — это стандарт безопасности браузера, который позволяет ограничить, какие ресурсы (скрипты, стили, изображения, шрифты и т.д.) могут загружаться на вашей странице. Он передаётся через HTTP-заголовок, например: Content-Security-Policy: default-src 'self'.

CSP ломает сайты, потому что блокирует любой ресурс, не соответствующий вашей политике. Если у вас есть встроенные скрипты, внешние скрипты с CDN или встроенные стили, они будут заблокированы, если вы явно их не разрешите. По умолчанию блокируется всё, что не разрешено, поэтому строгая политика может быстро сломать сайт.

Ключ в том, чтобы начать с разрешительной политики и постепенно ужесточать её, отслеживая нарушения.

Основные директивы CSP, которые нужно знать

CSP использует директивы для управления различными типами ресурсов. Вот наиболее распространённые:

Вы можете задать несколько директив в одном заголовке, разделяя их точкой с запятой. Например:

Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.cdn.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https://images.example.com

Каждая директива принимает разделённый пробелами список источников. Источники могут быть ключевыми словами, такими как 'self', 'unsafe-inline', 'unsafe-eval', или URL, или nonce/хешами.

Пошаговое руководство: внедрение CSP без поломки сайта

Следуйте этим шагам, чтобы безопасно развернуть CSP.

  1. Начните с политики только для отчётов. Используйте заголовок Content-Security-Policy-Report-Only вместо принудительного. Это позволит увидеть, что было бы заблокировано, без фактической блокировки.
  2. Установите разрешительную политику. Начните с чего-то вроде default-src 'self' 'unsafe-inline' 'unsafe-eval' https:, чтобы разрешить большинство вещей. Это минимизирует поломки.
  3. Собирайте отчёты о нарушениях. Настройте report-uri на эндпоинт, который регистрирует нарушения. Просматривайте эти отчёты, чтобы выявить заблокированные ресурсы.
  4. Исправьте нарушения. Обновите код, чтобы избежать встроенных скриптов/стилей, или добавьте nonce/хеши. Переместите внешние ресурсы на разрешённые домены.
  5. Постепенно ужесточайте политику. Удалите 'unsafe-inline' и 'unsafe-eval' после рефакторинга. Сузьте разрешённые домены.
  6. Переключитесь в режим принудительного применения. Как только отчёты не будут показывать неожиданных блокировок, измените заголовок на Content-Security-Policy (без -Report-Only).
  7. Постоянно мониторьте. Держите эндпоинт для отчётов активным, чтобы ловить новые проблемы.

Этот постепенный подход гарантирует, что вы не сломаете сайт, улучшая безопасность.

Использование nonce и хешей для встроенных скриптов

Встроенные скрипты — частая причина поломки CSP. Вместо разрешения 'unsafe-inline' используйте nonce (одноразовый номер) или хеш.

Подход с nonce: Генерируйте случайный nonce для каждого запроса, добавляйте его в заголовок CSP и включайте в теги script.

Content-Security-Policy: script-src 'nonce-abc123'
<script nonce="abc123">...</script>

Подход с хешем: Вычислите SHA-хеш вашего встроенного скрипта и добавьте его в политику.

Content-Security-Policy: script-src 'sha256-xyz...'

Хеши лучше всего подходят для статических встроенных скриптов, которые редко меняются. Nonce лучше для динамического контента.

Для стилей вы также можете использовать nonce или хеши, но учтите, что style-src с nonce не покрывает встроенные атрибуты стиля (например, style="..."). Для них нужно 'unsafe-inline' или рефакторинг на классы.

Распространённые директивы CSP и их влияние

Директива Что контролирует Типичные источники
default-src Запасной вариант для всех типов ресурсов 'self', https:
script-src Источники JavaScript 'self', 'nonce-...', 'sha256-...', https://cdn.com
style-src Источники CSS 'self', 'unsafe-inline', 'nonce-...'
img-src Источники изображений 'self', data:, https://images.com
connect-src AJAX, WebSocket, fetch 'self', https://api.com
font-src Веб-шрифты 'self', https://fonts.gstatic.com
frame-src Iframe 'self', https://youtube.com

Используйте эту таблицу как краткий справочник при построении политики.

Тестирование и мониторинг вашей CSP

Перед принудительным применением тщательно протестируйте. Используйте инструменты разработчика браузера: вкладка Console показывает нарушения CSP как ошибки. Вкладка Network показывает заголовок CSP.

Для автоматизированного тестирования рассмотрите такие инструменты, как Google CSP Evaluator (онлайн) или npm-пакет csp_evaluator. Они помогают выявить слабые политики.

Настройте эндпоинт для отчётов, чтобы собирать нарушения в продакшене. Вы можете использовать сервис вроде Report URI или создать свой эндпоинт, который логирует в файл или базу данных. Регулярно анализируйте отчёты, чтобы ловить новые проблемы.

Помните: CSP — не серебряная пуля. Это один из слоёв защиты. Сочетайте её с валидацией входных данных, экранированием выходных данных и другими лучшими практиками безопасности.

FAQ

В чём разница между Content-Security-Policy и Content-Security-Policy-Report-Only?

Принудительный заголовок (Content-Security-Policy) блокирует нарушения. Заголовок только для отчётов (Content-Security-Policy-Report-Only) только сообщает о нарушениях, не блокируя, что позволяет безопасно тестировать политику.

Можно ли использовать CSP с встроенными обработчиками событий, такими как onclick?

Нет, встроенные обработчики событий блокируются CSP, если вы не используете 'unsafe-inline' (что не рекомендуется) или не перейдёте на addEventListener. Для лучшей безопасности избегайте встроенных обработчиков событий.

Как разрешить Google Analytics с CSP?

Добавьте домены Google Analytics в директивы script-src и connect-src. Например: script-src 'self' https://www.googletagmanager.com; connect-src 'self' https://www.google-analytics.com. Проверьте документацию Google для последних требований.

Внедрение CSP не должно быть болезненным процессом. С постепенным подходом вы можете защитить пользователей от XSS и других атак, не нарушая работу сайта. Начните с режима только для отчётов, исправьте нарушения и со временем ужесточите политику.

Если вам нужно быстро отформатировать или проверить JSON-файлы конфигурации для ваших отчётов CSP, попробуйте наш JSON Formatter для форматирования и отладки данных JSON.