Content-Security-Policy теперь использует 'strict-dynamic'

Начиная с версии v3.3.0.beta1, в Discourse внедрена политика безопасности контента (CSP) со строгим динамическим режимом (strict-dynamic). Это устранит необходимость в ручной настройке CSP и значительно улучшит совместимость с внешними инструментами, такими как менеджеры тегов и рекламные платформы.

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

Для тем никаких изменений не требуется. Небольшому количеству плагинов [1] может потребоваться небольшая корректировка для обеспечения совместимости с этим изменением (например, 1, 2).

Форумы, которые ранее отключали CSP для совместимости с внешними скриптами, теперь смогут снова включить его без каких-либо проблем или дополнительных настроек.

Технические детали можно найти в этой теме:

На данный момент всё ещё возможно вернуться к старой системе, отключив настройку сайта «content security policy strict dynamic». Если у вас есть причины сделать это, пожалуйста, сообщите нам!


Начиная с версии v3.3.0.beta3, ключевое слово «strict-dynamic» стало обязательной частью нашей CSP. Настройка сайта «content security policy strict dynamic» была удалена, а настройка «content security policy script src» обновлена так, чтобы принимать только допустимые значения.

Администраторы смогут найти предыдущее значение настройки «content security policy script src» в логах действий персонала вашего сайта (https://<site_url>/admin/logs/staff_action_logs?filters=%7B%22action_name%22%3A%22change_site_setting%22%2C%22action_id%22%3A3%2C%22subject%22%3A%22content_security_policy_script_src%22%7D — замените <site_url> на базовый URL вашего сайта).


  1. технически: те, которые добавляют элементы <script> через register_html_builder или шаблон erb. ↩︎

26 лайков

Как я могу настроить 'unsafe-eval' после этого изменения так же, как и раньше?

1 лайк

Ничего не изменилось — вы по-прежнему можете добавить «unsafe eval» (в кавычках) в настройку сайта content security script src.

3 лайка

Я заметил, что в описании настройки content security script src указано, что включение content_security_policy_strict_dynamic игнорирует эту настройку, поэтому я обратился сюда за консультацией.

3 лайка

В описании сказано:

Источники хостов будут игнорироваться, когда включен параметр content_security_policy_strict_dynamic.

Ключевой момент здесь — «источники хостов». ‘unsafe-inline’ не является источником хоста, поэтому он всё ещё поддерживается.

Тем не менее, я полностью согласен, что это сбивает с толку. Учитывая успех внедрения strict-dynamic, мы планируем удалить старую систему. Как только это произойдёт, мы сможем автоматически удалять все источники хостов из списка, и администраторам будет гораздо проще. :rocket:

5 лайков

Хорошо, спасибо за уточнение.

4 лайка

Дэвид,

Несколько уточнений.

Эта новая система, по-видимому, хорошо работает со:

  • встроенными скриптами
  • полными исходными файлами скриптов, размещёнными локально

Но как быть со случаем, когда удалённые скрипты вызывались с помощью «loadScript» и полного URL-адреса?

Исправьте меня, если я ошибаюсь, но мне кажется, что нет удобного способа обработать этот случай?

Так значит ли это, что в таких ситуациях нам нужно полагаться на:

  • перенос этого вызова во встроенный скрипт ИЛИ
  • загрузку полного исходного кода как актива темы?

В первом случае, со встроенным скриптом, я предполагаю, что нет способа гарантировать загрузку скрипта до использования его элементов? (В отличие от того, что можно сделать внутри .then после loadScript)

2 лайка

strict-dynamic должен работать с удаленными скриптами, загружаемыми через loadScript. Фактически, это была главная причина перехода: нам больше не нужно заранее указывать каждый внешний URL скрипта. Это особенно полезно для тех, кто размещает рекламу, поскольку она часто подгружает множество удаленных скриптов.

Вы видите ошибки при использовании loadScript?

3 лайка

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

Я в основном готовился к стабильному обновлению, которое, как я знаю, включает loadScript и удаленные скрипты.

Не могли бы вы объяснить, как удаленные скрипты, которые случайно вызываются в коде с помощью loadScript, оказываются «авторизованными» в режиме Dynamic CSP? Там происходит какая-то магия?

3 лайка

Да!

На MDN есть хорошее объяснение с примерами.

Выражение источника 'strict-dynamic' указывает, что доверие, явно предоставленное скрипту в разметке (например, через nonce или хеш), должно распространяться на все скрипты, загружаемые этим корневым скриптом.

Таким образом, пока исходный скрипт считается доверенным (благодаря nonce), браузер разрешает ему загружать любые другие скрипты без ограничений. А поскольку эти скрипты также считаются доверенными, они могут загружать ещё больше!


Однако есть одно ограничение: скрипты не могут быть «вставлены парсером». Это предотвращает использование strict-dynamic для XSS-атак.

Например, такой код считается «вставленным парсером» и будет заблокирован:

document.head.appendChild("<script src='https://example.com/xss-attempt.js' />");

Но создание элемента скрипта программно не требует HTML-парсинга, гораздо менее вероятно является вектором XSS, поэтому это разрешено:

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

^^ именно так работает функция loadScript()

3 лайка

Отличная ссылка.

О, почти получилось, спасибо!

Так что же nonce включается также в теги скриптов, которые рендерит loadScript?

2 лайка

Нет, nonce включается только в исходный тег script, сгенерированный Rails (например, для скриптов ядра, плагинов или тем).

Это означает, что код ядра/плагина/темы считается доверенным и может вставлять любые другие скрипты. Здесь nonce не требуется — браузер знает, какой скрипт выполнил вставку, и автоматически понимает, что ему можно доверять.

4 лайка

Дэвид, ещё раз спасибо за ваше время!

4 лайка

6 сообщений были перенесены в новую тему: Ошибка CSP при добавлении скрипта через компонент темы