Коротко. Ошибка CSP в консоли означает, что политика безопасности страницы (заголовок Content-Security-Policy) запретила загрузку или выполнение ресурса — чаще всего скрипта, стиля или запроса к чужому домену. Читается она по одной директиве: в сообщении указано, какая директива сработала (script-src, style-src, connect-src…) и какой источник заблокирован. Чинится двумя путями: разрешить нужный источник в этой директиве — или, что безопаснее, убрать инлайновый код в отдельный файл либо подписать его через nonce/hash вместо 'unsafe-inline'. Ниже — как разобрать сообщение и выбрать правильное исправление, не ослабляя защиту.
Что такое ошибка CSP
Content-Security-Policy — заголовок, которым сайт говорит браузеру, откуда разрешено грузить скрипты, стили, картинки, шрифты и куда можно отправлять запросы. Всё, что не разрешено политикой, браузер блокирует и пишет ошибку в консоль. Это не поломка сайта, а сработавшая защита: CSP — один из сильнейших барьеров против XSS. Как настроить политику с нуля — в руководстве по настройке CSP; здесь — про чтение и починку ошибок.
Ошибка CSP — это не баг, а сработавший предохранитель. Прежде чем «разрешить всё», спросите: почему политика заблокировала ресурс? Часто правильный ответ — не ослабить политику, а привести код в соответствие с ней.
Как прочитать сообщение
Типичная ошибка в консоли (F12) выглядит так:
Refused to execute inline script because it violates the following
Content Security Policy directive: "script-src 'self'".
Either the 'unsafe-inline' keyword, a hash (...), or a nonce (...) is required.
Разбираем по частям:
- Что заблокировано — «Refused to execute inline script» (инлайновый скрипт), «Refused to load the stylesheet» (стиль), «Refused to connect» (запрос fetch/XHR).
- Какая директива сработала —
script-src 'self': политика разрешает скрипты только со своего домена. - Что предлагается — добавить источник, либо использовать
nonceилиhashвместо инлайна.
Директива в сообщении — главное: она говорит, какой тип ресурса и с каким правилом столкнулся.
| Директива | Что контролирует | Частая причина ошибки |
|---|---|---|
| script-src | Откуда грузить и выполнять скрипты | Инлайновый <script>, сторонний CDN, eval() |
| style-src | Стили и инлайновые style= | Инлайновые стили, шрифтовые CDN |
| connect-src | Куда можно слать fetch/XHR/WebSocket | Запрос к API на другом домене |
| img-src / font-src | Картинки и шрифты | Внешний хост картинок/шрифтов |
Как исправить — правильно
Инлайновый скрипт или стиль заблокирован
Сообщение просит 'unsafe-inline', но добавлять его — плохое решение: это открывает дверь для XSS, ради защиты от которого CSP и существует. Правильно:
- Вынести код в отдельный файл (
.js/.css) со своего домена — тогда его покрывает'self', и инлайн не нужен. - Или подписать инлайн через nonce/hash: сервер добавляет к разрешённому блоку одноразовый
nonce(или хэш содержимого), и только он выполняется. Это разрешает конкретный код, не открывая все инлайны.
# политика с nonce (сервер генерирует новый на каждый запрос):
Content-Security-Policy: script-src 'self' 'nonce-Ab3xZ...'
# и в HTML:
<script nonce="Ab3xZ...">...</script>
Заблокирован сторонний скрипт или стиль (CDN)
Если это доверенный источник (например, ваш аналитический скрипт), добавьте его домен в нужную директиву: script-src 'self' https://cdn.example.com. Не разрешайте лишнего — только конкретные хосты, а не *.
Ошибка на eval()
Сообщение про 'unsafe-eval' значит, что код (или библиотека) использует eval() / new Function(). Лучшее решение — заменить такой код; добавлять 'unsafe-eval' стоит лишь как крайнюю меру, понимая риск.
Заблокирован запрос fetch/XHR
Директива connect-src не разрешает домен, к которому идёт запрос. Добавьте его: connect-src 'self' https://api.example.com.
Правило выбора: сначала попробуйте привести код к политике (вынести инлайн, убрать eval), и только если источник действительно нужен и доверен — точечно разрешите именно его. «Разрешить всё» через'unsafe-inline'или*убивает смысл CSP.
Как отлаживать безопасно
Чтобы не сломать рабочий сайт, пока настраиваете политику, используйте режим Content-Security-Policy-Report-Only: браузер не блокирует ресурсы, а только сообщает о нарушениях. Так вы соберёте все проблемы, ничего не сломав, а потом включите блокирующую политику. Проверить итоговую политику и её директивы удобно через анализатор CSP — он разбирает заголовок и показывает, что каждая директива разрешает. Общий разбор директив — в руководстве по CSP; про подпись сторонних ресурсов — в статье о Subresource Integrity.
Частые вопросы
Можно просто добавить 'unsafe-inline' и забыть?
Технически да, ошибка исчезнет — но вы отключите главную защиту CSP от XSS. Это допустимо лишь как временный костыль. Правильно — вынести инлайн в файлы или использовать nonce/hash; тогда и ошибок нет, и защита работает.
Ошибка появляется только в консоли, сайт вроде работает. Это важно?
Да. Значит, какой-то ресурс блокируется — возможно, часть функционала (аналитика, виджет, стиль) не работает, просто это не всегда заметно. Разберите каждое сообщение: либо ресурс нужен (разрешите источник правильно), либо он лишний (тогда уберите его вызов).
Как понять, какая именно строка политики виновата?
В сообщении консоли всегда указана директива в кавычках ("script-src 'self'") — это и есть виноватое правило. Прогоните заголовок через анализатор CSP, найдите эту директиву и решите: добавить источник или починить код.
Чеклист на память
- Ошибка CSP = сработавшая защита: политика запретила ресурс, а не «сломался сайт».
- В сообщении всегда есть директива (
script-src,connect-src…) — она и есть виноватое правило. - Инлайн чините выносом в файл или nonce/hash, а не
'unsafe-inline'. - Сторонний источник — точечно разрешайте конкретный хост, не
*. - Настраивайте через
Report-Only, чтобы собрать нарушения, ничего не сломав.