Spec-Zone.ru › Node.js

Разрешения

Разрешения могут использоваться для управления тем, к каким системным ресурсам имеет доступ процесс Node.js, или какими действиями процесс может выполнять с этими ресурсами. Разрешения также могут управлять тем, к каким модулям могут получить доступ другие модули.

  • Разрешения на основе модулей контролируют, какие файлы или URL доступны другим модулям во время выполнения приложения. Это можно использовать, например, для контроля доступа к модулям сторонними зависимостями.

  • Разрешения на основе процесса контролируют доступ процесса Node.js к ресурсам. Ресурс может быть полностью разрешен или запрещен, или могут быть контролированы действия, связанные с ним. Например, чтение из файловой системы может быть разрешено, а запись запрещена.

Если вы обнаружите потенциальную уязвимость в системе безопасности, обратитесь к нашей Политике безопасности.

Модульные разрешения

Политики

Устойчивость: 0 - Устарело: Будет удалено в ближайшее время

Node.js содержит экспериментальную поддержку создания политик при загрузке кода.

Политики — это функция безопасности, предназначенная для обеспечения целостности загружаемого кода.

Хотя она не функционирует как механизм происхождения для отслеживания источника кода, она служит надежной защитой от выполнения вредоносного кода. В отличие от моделей, основанных на времени выполнения, которые могут ограничить возможности после загрузки кода, политики Node.js фокусируются на предотвращении загрузки вредоносного кода в приложение в первую очередь.

Использование политик предполагает безопасную практику для файлов политики, например, обеспечение невозможности перезаписи файлов политики приложением Node.js с помощью разрешений на файлы.

Лучшей практикой будет обеспечение того, чтобы манифест политики был только для чтения для работающего приложения Node.js, и файл не мог быть изменён работающим приложением Node.js каким-либо образом. Типичная настройка заключалась бы в создании файла политики с другим идентификатором пользователя, чем у работающего Node.js, и предоставлении разрешений на чтение пользователю, работающему с Node.js.

Включение

Флаг --experimental-policy может использоваться для включения функций политик при загрузке модулей.

После этого все модули должны соответствовать файлу манифеста политики, переданному в флаг:

node --experimental-policy=policy.json app.js copy

Манифест политики будет использоваться для применения ограничений к коду, загруженному Node.js.

Для предотвращения вмешательства в файлы политик на диске, целостность самого файла политики может быть обеспечена с помощью --policy-integrity. Это позволяет выполнять node и проверять содержимое файла политики, даже если файл изменён на диске.

node --experimental-policy=policy.json --policy-integrity="sha384-SggXRQHwCG8g+DktYYzxkXRIkTiEYWBHqev0xnpCxYlqMBufKZHAHQM3/boDaI/0" app.js copy
Функции
Поведение при ошибках

При неудачной проверке политики Node.js по умолчанию выведет ошибку. Можно изменить поведение при ошибке на один из нескольких вариантов, определив поле «onerror» в манифесте политики. Доступны следующие значения для изменения поведения:

  • "exit": немедленно завершит процесс. Никакой код очистки запускаться не будет.
  • "log": запишет ошибку в месте возникновения.
  • "throw": выведет ошибку JS в месте возникновения. Это значение по умолчанию.
{
  "onerror": "log",
  "resources": {
    "./app/checked.js": {
      "integrity": "sha384-SggXRQHwCG8g+DktYYzxkXRIkTiEYWBHqev0xnpCxYlqMBufKZHAHQM3/boDaI/0"
    }
  }
} copy
Проверки целостности

Файлы политики должны использовать проверки целостности с использованием строк Subresource Integrity, совместимых с атрибутом integrity браузера, связанным с абсолютными URL-адресами.

При использовании require() или import все ресурсы, участвующие в загрузке, проверяются на целостность, если указан манифест политики. Если ресурс не соответствует целостности, указанной в манифесте, будет выведена ошибка.

Пример файла политики, который разрешит загрузку файла checked.js:

{
  "resources": {
    "./app/checked.js": {
      "integrity": "sha384-SggXRQHwCG8g+DktYYzxkXRIkTiEYWBHqev0xnpCxYlqMBufKZHAHQM3/boDaI/0"
    }
  }
} copy

Каждый ресурс, указанный в манифесте политики, может иметь один из следующих форматов для определения его расположения:

  1. Строка относительного URL-адреса ресурса из манифеста, например, ./resource.js, ../resource.js, или /resource.js.
  2. Полная строка URL-адреса ресурса, например, file:///resource.js.

При загрузке ресурсов весь URL-адрес должен совпадать, включая параметры поиска и фрагмент хэша. ./a.js?b не будет использоваться при попытке загрузить ./a.js и наоборот.

Для генерации строк целостности можно использовать скрипт, такой как node -e 'process.stdout.write("sha256-");process.stdin.pipe(crypto.createHash("sha256").setEncoding("base64")).pipe(process.stdout)' < FILE.

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

Перенаправление зависимостей

Приложению может потребоваться отправить исправленные версии модулей или предотвратить доступ всех модулей ко всем другим модулям. Перенаправление может быть использовано для перехвата попыток загрузки модулей, подлежащих замене.

{
  "resources": {
    "./app/checked.js": {
      "dependencies": {
        "fs": true,
        "os": "./app/node_modules/alt-os",
        "http": { "import": true }
      }
    }
  }
} copy

Зависимости индексируются по строке запрошенного спецификатора и имеют значения либо true, либо null, либо строку, указывающую на модуль для разрешения, либо объект условий.

Строка спецификатора не выполняет никаких поисков и должна точно совпадать с предоставленным в require() или import, за исключением этапа канонизации. Поэтому в политике может потребоваться несколько спецификаторов, если она использует несколько различных строк для указания одного и того же модуля (например, исключая расширение).

Строки спецификаторов канонизируются, но не разрешаются до использования для сопоставления, чтобы обеспечить определённую совместимость с картами импорта, например, если ресурсу file:///C:/app/utils.js было дано следующее перенаправление из политики, расположенной по адресу file:///C:/app/policy.json:

{
  "resources": {
    "file:///C:/app/utils.js": {
      "dependencies": {
        "./utils.js": "./utils-v2.js"
      }
    }
  }
} copy

Любой спецификатор, используемый для загрузки file:///C:/app/utils.js, будет перехвачен и перенаправлен на file:///C:/app/utils-v2.js вместо этого, независимо от использования абсолютного или относительного спецификатора. Однако если используется спецификатор, который не является строкой абсолютного или относительного URL-адреса, он не будет перехвачен. Таким образом, если использовался импорт, например, import('#utils'), он не будет перехвачен.

Если значение перенаправления равно true, поле «dependencies» в верхней части файла политики будет использоваться. Если это поле в верхней части файла политики равно true, будут использоваться стандартные алгоритмы поиска Node для поиска модуля.

Если значение перенаправления является строкой, оно разрешается относительно манифеста и сразу же используется без поиска.

Любой спецификатор, для которого попытка разрешения и который не указан в зависимостях, приводит к ошибке в соответствии с политикой.

В карте зависимостей может быть указано логическое значение 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();
  }
}; copy
Сферы

Используйте поле "scopes" манифеста для установки конфигурации для многих ресурсов одновременно. Поле "scopes" работает путём сопоставления ресурсов по их сегментам. Если область или ресурс включает "cascade": true, неизвестные спецификаторы будут искаться в их содержащей области. Содержащая область для каскадирования находится путём рекурсивного сокращения URL-адреса ресурса путём удаления сегментов для специальных схем, сохранения последующих "/" суффиксов и удаления запроса и фрагмента хэша. Это приводит к окончательному сокращению 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: для своей области протокола, так как они не принимают источники.

Пример
{
  "scopes": {
    "file:///C:/app/": {},
    "file:": {},
    "": {}
  }
} copy

При заданном файле, расположенном по адресу file:///C:/app/bin/main.js, следующие области будут проверяться в порядке:

  1. "file:///C:/app/bin/"

Это определяет политику для всех файловых ресурсов в "file:///C:/app/bin/". Это не в поле "scopes" политики и будет пропущено. Добавление этой области в политику заставит её использоваться перед областью "file:///C:/app/".

  1. "file:///C:/app/"

Это определяет политику для всех файловых ресурсов в "file:///C:/app/". Это в поле "scopes" политики, и оно определит политику для ресурса по адресу file:///C:/app/bin/main.js. Если область имеет "cascade": true, любые невыполненные запросы о ресурсе будут делегированы следующей релевантной области для file:///C:/app/bin/main.js, "file:".

  1. "file:///C:/"

Это определяет политику для всех файловых ресурсов в "file:///C:/". Это не в поле "scopes" политики и будет пропущено. Оно не будет использоваться для file:///C:/app/bin/main.js, если "file:///C:/app/" установлено на каскадирование или не находится в "scopes" политики.

  1. "file:///"

Это определяет политику для всех файловых ресурсов на localhost. Это не в поле "scopes" политики и будет пропущено. Оно не будет использоваться для file:///C:/app/bin/main.js если "file:///C:/" установлено на каскадирование или не находится в "scopes" политики.

  1. "file:"

Это определяет политику для всех файловых ресурсов. Оно не будет использоваться для file:///C:/app/bin/main.js если "file:///" установлено на каскадирование или не находится в "scopes" политики.

  1. ""

Это определяет политику для всех ресурсов. Оно не будет использоваться для file:///C:/app/bin/main.js если "file:" установлено на каскадирование.

Целостность, использующая области

Установка целостности true в области установит целостность для любого ресурса, не найденного в манифесте, до true.

END_OF_DOCUMENT_MARKER

Установка целостности null в области приведет к тому, что целостность любого ресурса, не найденного в манифесте, будет отклонена при соответствии.

Отсутствие целостности эквивалентно установке целостности null.

"cascade" проверки целостности будут проигнорированы, если "integrity" явно задано.

Следующий пример позволяет загрузить любой файл:

{
  "scopes": {
    "file:": {
      "integrity": true
    }
  }
} copy
Перенаправление зависимостей с использованием областей

Следующий пример позволит получить доступ к fs для всех ресурсов в пределах ./app/:

{
  "resources": {
    "./app/checked.js": {
      "cascade": true,
      "integrity": true
    }
  },
  "scopes": {
    "./app/": {
      "dependencies": {
        "fs": true
      }
    }
  }
} copy

Следующий пример позволит получить доступ к fs для всех data: ресурсов:

{
  "resources": {
    "data:text/javascript,import('node:fs');": {
      "cascade": true,
      "integrity": true
    }
  },
  "scopes": {
    "data:": {
      "dependencies": {
        "fs": true
      }
    }
  }
} copy
Пример: эмуляция карт импорта

Учитывая карту импорта:

{
  "imports": {
    "react": "./app/node_modules/react/index.js"
  },
  "scopes": {
    "./ssr/": {
      "react": "./app/node_modules/server-side-react/index.js"
    }
  }
} copy
{
  "dependencies": true,
  "scopes": {
    "": {
      "cascade": true,
      "dependencies": {
        "react": "./app/node_modules/react/index.js"
      }
    },
    "./ssr/": {
      "cascade": true,
      "dependencies": {
        "react": "./app/node_modules/server-side-react/index.js"
      }
    }
  }
} copy

Карты импорта предполагают, что по умолчанию можно получить любой ресурс. Это означает, что "dependencies" на верхнем уровне политики должен быть установлен в true. Политики требуют, чтобы это было включено по умолчанию, так как это позволяет всем ресурсам приложения иметь перекрестные ссылки, что не имеет смысла во многих сценариях. Они также предполагают, что любая заданная область имеет доступ к любой области над ее разрешенными зависимостями; все области, эмулирующие карты импорта, должны установить "cascade": true.

Карты импорта имеют только одну область верхнего уровня для своих "импортов". Таким образом, для эмуляции "imports" используйте область "". Для эмуляции "scopes" используйте область "scopes" аналогичным образом к тому, как "scopes" работает в картах импорта.

Ограничения: Политики не используют сопоставление строк для различных способов поиска области. Они выполняют проход по URL. Это означает, что такие вещи, как blob: и data: URL могут быть не полностью совместимы между двумя системами. Например, карты импорта могут частично соответствовать data: или blob: URL, разделяя URL на символ /, политики намеренно не могут. Для blob: URL области карт импорта не принимают происхождение blob: URL.

Кроме того, карты импорта работают только с import, поэтому может быть целесообразно добавить условие "import" ко всем отображениям зависимостей.

Гарантии
  • Политики гарантируют целостность файла при загрузке модуля с помощью require(), import() или new Module().
  • Перенаправление не препятствует доступу к API через такие средства, как прямой доступ к require.cache , которые позволяют получить доступ к загруженным модулям. Перенаправление политики затрагивает только спецификаторы require() и import.
  • Одобрение целостности модуля в модели угроз политики подразумевает, что они могут изменять и даже обходить функции безопасности после загрузки, поэтому ожидается усиление среды/времени выполнения.

Разрешения, основанные на процессе

Модель разрешений

Устойчивость: 1.1 - Активное развитие

Модель разрешений Node.js — это механизм ограничения доступа к определенным ресурсам во время выполнения. API существует за флагом --experimental-permission, который при включении ограничит доступ ко всем доступным разрешениям.

Доступные разрешения документированы флагом --experimental-permission.

При запуске Node.js с --experimental-permission, возможность доступа к файловой системе через модуль fs, создание процессов, использование node:worker_threads, использование нативных дополнений, использование WASI и включение инспектора среды выполнения будут ограничены.

$ node --experimental-permission index.js
node:internal/modules/cjs/loader:171
  const result = internalModuleStat(filename);
                 ^

Error: Access to this API has been restricted
    at stat (node:internal/modules/cjs/loader:171:18)
    at Module._findPath (node:internal/modules/cjs/loader:627:16)
    at resolveMainPath (node:internal/modules/run_main:19:25)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:76:24)
    at node:internal/main/run_main_module:23:47 {
  code: 'ERR_ACCESS_DENIED',
  permission: 'FileSystemRead',
  resource: '/home/user/index.js'
} copy

Доступ к созданию процесса и созданию потоков рабочих процессов можно получить, используя соответственно --allow-child-process и --allow-worker.

Для разрешения нативных дополнений при использовании модели разрешений используйте флаг --allow-addons. Для WASI используйте флаг --allow-wasi.

API среды выполнения

При включении модели разрешений с помощью флага --experimental-permission к объекту process добавляется новое свойство permission. Это свойство содержит одну функцию:

permission.has(scope[, reference])

Вызов API для проверки разрешений во время выполнения (permission.has())

process.permission.has('fs.write'); // true
process.permission.has('fs.write', '/home/rafaelgss/protected-folder'); // true

process.permission.has('fs.read'); // true
process.permission.has('fs.read', '/home/rafaelgss/protected-folder'); // false copy
Разрешения файловой системы

Для разрешения доступа к файловой системе используйте флаги --allow-fs-read и --allow-fs-write:

$ node --experimental-permission --allow-fs-read=* --allow-fs-write=* index.js
Hello world!
(node:19836) ExperimentalWarning: Permission is an experimental feature
(Use `node --trace-warnings ...` to show where the warning was created) copy

Допустимые аргументы для обоих флагов:

  • * - для разрешения всех FileSystemRead или FileSystemWrite операций соответственно.
  • Пути, разделенные запятыми (,) для разрешения только соответствующих FileSystemRead или FileSystemWrite операций соответственно.

Пример:

  • --allow-fs-read=* - разрешит все FileSystemRead операции.
  • --allow-fs-write=* - разрешит все FileSystemWrite операции.
  • --allow-fs-write=/tmp/ - предоставит FileSystemWrite доступ к папке /tmp/.
  • --allow-fs-read=/tmp/ --allow-fs-read=/home/.gitignore - предоставляет FileSystemRead доступ к папке /tmp/ и пути /home/.gitignore.

Поддерживаются также подстановочные знаки:

  • --allow-fs-read=/home/test* позволит читать все, что соответствует подстановочному знаку. Например: /home/test/file1 или /home/test2

После символа подстановки (*) все последующие символы игнорируются. Например: /home/*.js будет работать аналогично /home/*.

Ограничения модели разрешений

Перед использованием этой системы необходимо знать следующие ограничения:

  • Модель не наследуется дочерним процессом или потоком рабочего процесса.
  • При использовании модели разрешений будут ограничены следующие функции:
    • Нативные модули
    • Дочерние процессы
    • Потоки рабочих процессов
    • Протокол инспектора
    • Доступ к файловой системе
    • WASI
  • Модель разрешений инициализируется после настройки среды Node.js. Однако некоторые флаги, такие как --env-file или --openssl-config, предназначены для чтения файлов до инициализации среды. В результате такие флаги не подчиняются правилам модели разрешений.
  • Запросы к OpenSSL-моторам во время выполнения недоступны при включенной модели разрешений, что влияет на встроенные модули crypto, https и tls.
  • Использование существующих дескрипторов файлов через модуль node:fs обходит модель разрешений.
Ограничения и известные проблемы
  • Символические ссылки будут следовать даже к расположениям за пределами набора путей, к которым был предоставлен доступ. Относительные символические ссылки могут позволить доступ к произвольным файлам и каталогам. При запуске приложений с включенной моделью разрешений необходимо убедиться, что ни один путь, к которому был предоставлен доступ, не содержит относительных символических ссылок.

© 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/api/permissions.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API