Content Security Policy

Content Security Policy (CSP) — это механизм безопасности веб-приложений, позволяющий ограничить источники, с которых загружаются ресурсы, и тем самым предотвращать атаки типа Cross-Site Scripting (XSS), внедрение вредоносных скриптов и других уязвимостей, связанных с загрузкой внешнего контента. CSP работает через установку заголовков HTTP или мета-тегов <meta> в HTML-документе, задающих правила для браузера.

Принцип работы CSP

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

Основные директивы CSP включают:

  • default-src — общий источник по умолчанию для всех типов контента.
  • script-src — допустимые источники JavaScript.
  • style-src — допустимые источники CSS.
  • img-src — допустимые источники изображений.
  • font-src — допустимые источники шрифтов.
  • connect-src — допустимые источники для запросов через XHR, WebSocket или Fetch API.
  • frame-src — допустимые источники для <iframe>.
  • object-src — источники для <object>, <embed> и <applet>.
  • report-uri и report-to — адрес для отправки отчетов о нарушении CSP.

Настройка CSP через заголовки HTTP

CSP обычно внедряется через заголовок Content-Security-Policy:

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

Разбор примера:

  • 'self' разрешает загрузку ресурса только с того же домена, что и веб-приложение.
  • https://cdn.example.com разрешает загрузку скриптов с указанного CDN.
  • 'unsafe-inline' позволяет использование встроенных стилей (не рекомендуется без крайней необходимости, повышает риск XSS).

Для тестирования политики можно использовать Content-Security-Policy-Report-Only, что позволяет собирать отчеты о потенциальных нарушениях без блокировки ресурсов.

Директивы и источники

CSP поддерживает несколько типов источников:

  • ‘self’ — текущий домен.
  • ‘none’ — блокировка всех источников.
  • URL или схема — например, https://example.com или data:.
  • ‘unsafe-inline’ — разрешение встроенных стилей или скриптов.
  • ‘unsafe-eval’ — разрешение динамического выполнения кода через eval() (не рекомендуется).

Дополнительно можно комбинировать источники, перечисляя их через пробел:

script-src 'self' https://cdn.example.com 'strict-dynamic';

Особенности директив

  • script-src-elem и style-src-elem позволяют задавать правила именно для <script> и <style> тегов, в отличие от общих script-src и style-src.
  • frame-ancestors ограничивает, кто может внедрять страницу в <iframe> (альтернатива X-Frame-Options).
  • worker-src управляет загрузкой ресурсов в Web Workers.

CSP и JavaScript

При работе с JavaScript CSP накладывает ограничения на динамическую вставку скриптов:

  • eval() и new Function() блокируются по умолчанию, если не указана директива 'unsafe-eval'.
  • Добавление <script> с помощью DOM разрешено только с источников, указанных в script-src.
  • Inline-обработчики событий (onclick, onload) блокируются без 'unsafe-inline'.

Пример безопасного использования динамических скриптов:

const script = document.createElement('script');
script.src = 'https://cdn.example.com/library.js';
document.head.appendChild(script);

Такой способ загружает скрипт с доверенного источника и полностью совместим с CSP, если URL указан в script-src.

CSP и AJAX / Fetch

Для запросов через fetch или XHR браузер проверяет connect-src:

Content-Security-Policy: connect-src 'self' https://api.example.com;

Это означает, что JavaScript сможет выполнять запросы только к текущему домену и указанному API.

CSP и внешние ресурсы

Использование сторонних библиотек требует явного разрешения источников:

  • CDN для скриптов или стилей.
  • Шрифты с внешних сервисов (fonts.googleapis.com, fonts.gstatic.com).
  • Изображения с других доменов.

Пример политики с внешними ресурсами:

Content-Security-Policy:
  default-src 'self';
  script-src 'self' https://cdn.example.com;
  style-src 'self' https://fonts.googleapis.com;
  font-src https://fonts.gstatic.com;
  img-src 'self' dat a:;

Здесь data: разрешает встроенные изображения в формате base64, что иногда необходимо для иконок или inline-графики.

Мониторинг и отчетность

CSP поддерживает механизм отчетности о нарушениях:

Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report-endpoint

Браузер отправляет JSON-отчеты на указанный URL, позволяя анализировать попытки загрузки запрещенного контента. Это полезно для отладки и постепенного внедрения строгой политики.

Рекомендации по безопасности

  • Использовать default-src 'self' как базовую защиту.
  • Минимизировать использование 'unsafe-inline' и 'unsafe-eval'.
  • Явно указывать доверенные источники для всех внешних ресурсов.
  • Включать механизм отчетности перед применением строгой политики.
  • Разделять правила для скриптов, стилей, изображений и подключения данных через директивы типа script-src, style-src, img-src, connect-src.
  • Проверять консоль браузера на сообщения о нарушении CSP при тестировании.

CSP является мощным инструментом, но требует внимательной настройки: слишком строгая политика может сломать функциональность сайта, слишком мягкая — не обеспечит надежной защиты. Сбалансированное применение директив и контроль источников контента повышает безопасность веб-приложения без ущерба для пользовательского опыта.