Политики
Node.js содержит экспериментальную поддержку создания политик при загрузке кода.
Политики — это функция безопасности, предназначенная для обеспечения гарантий относительно того, какой код Node.js может загрузить. Использование политик предполагает безопасные методы работы с файлами политик, такие как обеспечение невозможности перезаписи файлов политик приложением Node.js с помощью разрешений на доступ к файлам.
Рекомендуется сделать файл манифеста политики только для чтения для работающего приложения Node.js и предотвратить его изменение приложением Node.js. Типичная настройка предполагает создание файла политики другим пользователем, отличным от пользователя, под которым запускается Node.js, и предоставление разрешений на чтение пользователю, под которым запускается Node.js.
Включение
Флаг --experimental-policy может использоваться для включения функций политик при загрузке модулей.
После этого все модули должны соответствовать файлу манифеста политики, переданному в флаг:
node --experimental-policy=policy.json app.js
Файл манифеста политики будет использоваться для обеспечения ограничений на код, загружаемый Node.js.
Для предотвращения несанкционированного изменения файлов политик на диске можно использовать целостность самого файла политики с помощью --policy-integrity. Это позволяет выполнять node и проверять содержимое файла политики, даже если файл изменён на диске.
node --experimental-policy=policy.json --policy-integrity="sha384-SggXRQHwCG8g+DktYYzxkXRIkTiEYWBHqev0xnpCxYlqMBufKZHAHQM3/boDaI/0" app.js
Функции
Поведение при ошибках
При неудачной проверке политики Node.js по умолчанию выводит ошибку. Можно изменить поведение при ошибке на одно из нескольких значений, определив поле «onerror» в манифесте политики. Доступны следующие значения для изменения поведения:
-
"exit": немедленно завершит процесс. Код очистки запускаться не будет. -
"log": выведет сообщение об ошибке в месте её возникновения. -
"throw": сгенерирует ошибку JS в месте возникновения ошибки. Это значение по умолчанию.
{
"onerror": "log",
"resources": {
"./app/checked.js": {
"integrity": "sha384-SggXRQHwCG8g+DktYYzxkXRIkTiEYWBHqev0xnpCxYlqMBufKZHAHQM3/boDaI/0"
}
}
} Проверки целостности
Файлы политик должны использовать проверки целостности с использованием строк Subresource Integrity, совместимых с атрибутом integrity браузера, связанным с абсолютными URL-адресами. атрибут integrity
При использовании require() все ресурсы, участвующие в загрузке, проверяются на целостность, если указан манифест политики. Если ресурс не соответствует целостности, указанной в манифесте, будет сгенерирована ошибка.
Пример файла политики, который позволит загрузить файл checked.js:
{
"resources": {
"./app/checked.js": {
"integrity": "sha384-SggXRQHwCG8g+DktYYzxkXRIkTiEYWBHqev0xnpCxYlqMBufKZHAHQM3/boDaI/0"
}
}
} Каждый ресурс, перечисленный в манифесте политики, может быть представлен в одном из следующих форматов для определения его расположения:
- Строка относительного URL-адреса к ресурсу из манифеста, например,
./resource.js,../resource.js, или/resource.js. - Полная строка URL-адреса к ресурсу, например,
file:///resource.js.
При загрузке ресурсов весь URL-адрес должен совпадать, включая параметры поиска и фрагмент хеша. ./a.js?b не будет использоваться при попытке загрузить ./a.js и наоборот.
Для генерации строк целостности можно использовать скрипт, например, printf "sha384-$(cat checked.js | openssl dgst -sha384 -binary | base64)".
Целостность может быть задана как булево значение true для принятия любого тела для ресурса, что может быть полезно для разработки на локальном компьютере. Это не рекомендуется в рабочей среде, так как это позволит считать допустимыми неожиданные изменения ресурсов.
Перенаправление зависимостей
Приложению может потребоваться отправить исправленные версии модулей или предотвратить доступ всех модулей ко всем другим модулям. Перенаправление можно использовать, перехватывая попытки загрузить модули, которые нужно заменить.
{
"resources": {
"./app/checked.js": {
"dependencies": {
"fs": true,
"os": "./app/node_modules/alt-os",
"http": { "import": true }
}
}
}
} Зависимости индексируются по запрошенной строке спецификатора и имеют значения true, null, строки, указывающие на модуль для разрешения, или объекта условий.
Строка спецификатора не выполняет поиск и должна точно совпадать с тем, что предоставляется require() или import Поэтому в политике может потребоваться несколько спецификаторов, если для указания одного и того же модуля используются несколько разных строк (например, без расширения).
Если значение перенаправления — true, используются стандартные алгоритмы поиска модуля.
Если значение перенаправления — строка, она разрешается относительно манифеста и сразу же используется без поиска.
Любой спецификатор, для которого происходит попытка разрешения и который не перечислен в зависимостях, приводит к ошибке в соответствии с политикой.
Перенаправление не препятствует доступу к API через такие средства, как прямой доступ к require.cache или через module.constructor, которые позволяют получить доступ к загружаемым модулям. Перенаправление политик затрагивает только спецификаторы для require() и import. Для блокировки доступа к API через переменные необходимы другие средства, например, предотвращение нежелательного доступа к API через переменные.
Для разрешения загрузки модулем любого спецификатора без перенаправления можно указать булево значение true для карты зависимостей. Это может быть полезно для разработки на локальном компьютере и может иметь определённое применение в рабочей среде, но должно использоваться с осторожностью после проверки модуля для обеспечения корректности его поведения.
Аналогично "exports" в package.json, зависимости также можно указать как объекты, содержащие условия, которые влияют на загрузку зависимостей. В предыдущем примере "http" разрешается, когда условие "import" является частью его загрузки.
Значение null для значения разрешения приводит к сбою разрешения. Это можно использовать для предотвращения некоторых видов динамического доступа.
Неизвестные значения для расположения разрешённого модуля приводят к сбою, но не гарантируют совместимость в будущем.
Пример: Исправленная зависимость
Перенаправленные зависимости могут предоставлять ослабленную или изменённую функциональность, подходящую для приложения. Например, регистрация данных о времени выполнения функций путём обертывания исходного кода:
const original = require('fn');
module.exports = function fn(...args) {
console.time();
try {
return new.target ?
Reflect.construct(original, args) :
Reflect.apply(original, this, args);
} finally {
console.timeEnd();
}
}; Области
Используйте поле "scopes" манифеста для настройки параметров сразу для многих ресурсов. Поле "scopes" работает путём сопоставления ресурсов по их сегментам. Если область или ресурс включает "cascade": true, неизвестные спецификаторы будут искать в содержащей области. Содержащая область для каскадирования определяется путём рекурсивного сокращения URL-адреса ресурса путём удаления сегментов для специальных схем, сохранения конечных "/" суффиксов и удаления запроса и фрагмента хеша. Это приводит к окончательному сокращению URL-адреса до его источника. Если URL-адрес не является специальным, область будет определяться источником URL-адреса. Если область не найдена для источника или в случае с непрозрачными источниками, в качестве области можно использовать строку протокола.
Обратите внимание, что URL-адреса blob: принимают свой источник из содержащегося в них пути, поэтому область "blob:https://nodejs.org" не повлияет, поскольку ни один URL не может иметь источник blob:https://nodejs.org; URL-адреса, начинающиеся с blob:https://nodejs.org/ будут использовать https://nodejs.org в качестве своего источника, а значит, https: в качестве своей области протокола. Для URL-адресов непрозрачных источников blob: их область протокола будет blob:, так как они не принимают источники.
Проверка целостности с использованием областей
Установка целостности true в области установит целостность любого ресурса, не найденного в манифесте, в true.
Установка целостности null в области установит целостность любого ресурса, не найденного в манифесте, на несоответствие.
Отсутствие целостности равнозначно установке целостности null.
"cascade" для проверок целостности будут проигнорированы, если "integrity" явно задано.
Следующий пример позволяет загружать любые файлы:
{
"scopes": {
"file:": {
"integrity": true
}
}
} Перенаправление зависимостей с использованием областей
Следующий пример позволит получить доступ к fs для всех ресурсов в ./app/:
{
"resources": {
"./app/checked.js": {
"cascade": true,
"integrity": true
}
},
"scopes": {
"./app/": {
"dependencies": {
"fs": true
}
}
}
} Следующий пример позволит получить доступ к fs для всех ресурсов data::
{
"resources": {
"data:text/javascript,import('fs');": {
"cascade": true,
"integrity": true
}
},
"scopes": {
"data:": {
"dependencies": {
"fs": true
}
}
}
}
© Joyent, Inc. and other Node contributors
Licensed under the MIT License.
Node.js is a trademark of Joyent, Inc. and is used with its permission.
We are not endorsed by or affiliated with Joyent.
https://nodejs.org/dist/latest-v14.x/docs/api/policy.html