CSP: как разрешить небезопасную оценку для данного префикса URI (Firefox)

Я пытаюсь использовать MathJax как часть нашего веб-приложения, которое использует довольно строгий Политика безопасности контента (CSP). Проблема в том, что MathJax кодируется для использования eval() [точнее, в форме Function()], который по умолчанию не считается безопасным CSP.

В настоящее время я использую следующий заголовок CSP:

X-Content-Security-Policy: allow 'self'; img-src *; media-src *; frame-src *; font-src *; frame-ancestors 'none'; style-src *; report-uri '/:save-csp-violation';

Из-за чего код MathJax 2.0 терпит неудачу, потому что он использует Function(). Я попытался разрешить небезопасное eval (т.е. Function()) только для MathJax, расположенного в том же самом происхождении ниже пути /:static/math/. Для этого я попытался добавить

unsafe-eval '/:static/math/*'

чтобы весь заголовок выглядел как

X-Content-Security-Policy: allow 'self'; img-src *; media-src *; frame-src *; font-src *; frame-ancestors 'none'; style-src *; report-uri '/:save-csp-violation'; unsafe-eval '/:static/math/*'

но я до сих пор не могу Firefox 13.0 запускать код. Я получаю сообщение об ошибке в Firefox Web Console (находится в Инструменты - Веб-разработчик):

[10:09:59.072] call to Function() blocked by CSP @ http://localhost:8080/:static/math/2.0/MathJax.js?config=TeX-AMS-MML_HTMLorMML:29

Однако я не получаю отчет CSP для отчета report-uri. (Как видите, в настоящее время я запускаю тест через пользовательский порт localhost без SSL, если это имеет значение. Двоеточие до static не является опечаткой, я резервирую все части пути, начиная с двоеточия для внутреннего использование приложения, все содержимое пользователя может свободно определять другие URL-адреса.)

Является ли использование атрибута unsafe-eval неправильным или невозможно разрешить небезопасную-eval только для подмножества "я"?. Цель состоит в том, чтобы разрешить небезопасную-eval только для одного префикса пути происхождения /:static/math, строгая реализация кода JSP CSP для 'self' и никакого JS-кода для любого другого метода.

Ответ 1

Существует несколько проблем:

  • Заголовки CSP не работают таким образом. CSP имеет только гранулярность единственной комбинации хоста и порта (источник). Если вы не можете разрешить script на своем хосте иметь unsafe-eval, то script может иметь его. Единственное возможное обходное решение - не использовать script, который требует unsafe-eval (удачи, написав замену MathJax самостоятельно).

  • Синтаксис allow является старым вариантом Mozilla и не должен использоваться. Текущий синтаксис состоит в том, чтобы сказать default-src, за которым следуют схемы или имена узлов или истоки, которые разрешены как источник всего, а затем, если необходимо, переопределяют значение по умолчанию для каждого подтипа (например, script-src). Некоторые источники могут поддерживать дополнительные ключевые слова источника в дополнение к self. Например, script-src поддерживает unsafe-eval, что означает, что любому script, которому в противном случае разрешено выполнение, разрешено запускать eval() или Function() и unsafe-inline, что означает, что любая часть разметки, которая может поддерживать некоторые вид встроенного script разрешен. Разрешить unsafe-eval может быть приемлемым, но unsafe-inline почти не работает с script -src (в противном случае вы вообще не должны беспокоиться о CSP).

  • Правильный синтаксис для script-src следующим образом:

    script-src 'self' 'unsafe-inline'
    
  • MathJax также использует встроенные атрибуты стиля, поэтому требуется следующее (если это уже разрешено), или MathJax попадет в Exception при попытке отобразить математику:

    style-src 'self' 'unsafe-inline'
    

    Невозможно использовать CSP, чтобы позволить JS вставлять атрибуты стиля и не иметь атрибутов стиля, уже вставленных в источник HTML, чтобы иметь эффект.

  • Похоже, что Firefox 13.0 (по крайней мере) не сразу "звонит домой" в случае нарушения CSP. Большинство отчетов о нарушениях поступают через некоторое время после события. Chrome, похоже, гораздо более агрессивен с представлением отчета, которое будет немного легче протестировать. По моему опыту, Firefox не всегда отправляет отчет CSP вообще - он может использовать какую-то эвристику, чтобы не отправлять повторяющиеся сообщения.

Бонус: для поддержки webkit вам нужно повторить конфигурацию с X-WebKit-CSP HTTP-заголовком.

В конце концов, чтобы MathJax работал с Content-Security-Protection, вам нужны следующие заголовки (предполагая, что вы распространяете библиотеку MathJax самостоятельно, а не через MNJMN):

X-Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; options eval-script
X-WebKit-CSP: default-src 'self'; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline'
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline'

Здесь атрибут options требуется для Firefox 13.0 и меньше. Я сообщил о проблеме CSP для MathJax на https://github.com/mathjax/MathJax/issues/256.