Политика защиты содержимого
Политика защиты содержимого (англ. Content Security Policy) автоматически применяется ко всем расширениям, разработанным с использованием WebExtension API. Она ограничивает источники, из которых расширение может загружать <script> и <object> ресурсы, и препятствует потенциально опасным практикам, например использованию eval()
.
Статья в краткой форме объясняет значимость этой политики, каковы её изначальные правила, как они влияют на расширение, и как расширение может изменять эти правила.
Политика защиты содержимого - это механизм, помогающий веб-сайтам предотвращать выполнение умышленно вредного кода. Веб-сайт устанавливает политику защиты, используя HTTP заголовок, посылаемый с сервера. Главным образом эта политика участвует в устанавливании допустимых источников для загрузки различного вида контента, к примеру, скриптов или встроенных плагинов. Например, веб-сайт может использовать политику защиты для инструктирования браузера, чтобы тот выполнял скрипты, загруженные только с самого сайта, а не из каких-либо других источников. Политика защиты содержимого так же может запретить браузеру использовать потенциально опасные практики, например использование eval().
Так же как веб-сайты, расширения могут загружать контент из различных источников. Например, всплывающее окно расширения определяется HTML документом, и может подключать JavaScript и CSS файлы из различных источников, точно так же, как и нормальная веб-страница:
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<!-- Некоторый HTML контент -->
<!--
Подключение сторонней библиотеки.
Смотрите также https://developer.mozilla.org/ru/docs/Web/Security/Subresource_Integrity.
-->
<script>
src="https://code.jquery.com/jquery-2.2.4.js"
integrity="sha256-iT6Q9iMJYuQiMWNd9lDyBUStIq/8PuOW33aOqmvFpqI="
crossorigin="anonymous">
</script>
<!-- Include my popup's own script-->
<script src="popup.js"></script>
</body>
</html>
В сравнении с веб-сайтами, расширения имеют доступ к дополнительному привилегированному API, так что вероятность получения к нему доступа сторонним кодом - это очень большой риск. По этой причине:
- довольно строгая политика по защите содержимого применяются изначально. Смотрите изначальные правила по защите содержимого.
- авторы расширений могут изменять изначальную политику, используя
content_security_policy
ключ в manifest.json, но даже в этом случае существуют ограничения на возможные разрешения. Для дополнительной информации смотритеcontent_security_policy
.
Изначальные правила по защите содержимого
Следующие правила по защите содержимого являются изначальными:
"script-src 'self'; object-src 'self';"
Они применяются к любому расширению, которое самостоятельно не указывает свою политику защиты, используя content_security_policy
ключ в manifest.json. Это имеет следующие последствия:
Расположение script и object ресурсов
Используя изначальную политику защиты содержимого, вы можете загружать только локальные к расширению <script> и <object> ресурсы. Например, рассмотрите эту строку из документа расширения:
<script src="https://code.jquery.com/jquery-2.2.4.js"></script>
Она не будет загружать запрашиваемый ресурс, и вы не сможете найти ни один ожидаемый от ресурса объект. К этой ситуации существует два решения:
- Скачать этот ресурс, упаковать его в ваше расширение и ссылаться к нему локально.
- Использовать ключ
content_security_policy
в manifest.json, чтобы позволить загрузку контента из вышеупомянутого источника..
eval() и товарищи
Изначальная политика защиты содержимого не позволяет выполнять код из JavaScript строк. Это означает, что следующие примеры кода изначально запрещены:
eval("console.log('some output');");
window.setTimeout("alert('Hello World!');", 500);
var f = new Function("console.log('foo');");
Встраиваемый (inline) JavaScript
Изначальная политика защиты содержимого не позволяет выполнять JavaScript-код, встраиваемый в HTML теги. Это запрещает как выполнение JavaScript-кода вложенного прямо в <script>
тег, так и выполнение вписанных в атрибут обработчиков событий, означая, что следующий код так же не будет работать:
<script>
console.log("foo");
</script>
<div onclick="console.log('click')">Click me!</div>
Вместо того, чтобы использовать код <body onload="main()">
для запуска вашего скрипта после загрузки страницы, поставьте обработчики событий на DOMContentLoaded или load.