Skip to content

权限

权限可以用来控制 Node.js 进程能够访问哪些系统资源,或者进程能够对这些资源执行哪些操作。

  • 基于进程的权限 控制 Node.js 进程对资源的访问。资源可以被完全允许或拒绝,或者可以控制与其相关的操作。例如,可以允许文件系统读取,同时拒绝写入。此功能无法防止恶意代码。根据 Node.js 的 安全策略,Node.js 信任其被要求运行的任何代码。

权限模型实现了一种“安全带”方法,防止受信任的代码无意中更改文件或使用未明确授予访问权限的资源。在存在恶意代码的情况下,它不提供安全保证。恶意代码可以绕过权限模型并执行任意代码,而不会受到权限模型施加的限制。

如果您发现潜在的安全漏洞,请参阅我们的 安全策略

基于进程的权限

权限模型

[稳定: 2 - 稳定]

稳定: 2 稳定性: 2 - 稳定.

Node.js 权限模型是一种在执行期间限制访问特定资源的机制。该 API 位于标志 --permission 后面,启用该标志后,将限制对所有可用权限的访问。

可用权限由 --permission 标志记录。

使用 --permission 启动 Node.js 时,将限制通过 fs 模块访问文件系统、生成进程、使用 node:worker_threads、使用原生插件、使用 WASI 以及启用运行时检查器的能力。

bash
$ node --permission index.js

Error: Access to this API has been restricted
    at node:internal/main/run_main_module:23:47 {
  code: 'ERR_ACCESS_DENIED',
  permission: 'FileSystemRead',
  resource: '/home/user/index.js'
}

可以使用 --allow-child-process--allow-worker 分别允许访问生成进程和创建 Worker 线程。

要在使用权限模型时允许原生插件,请使用 --allow-addons 标志。对于 WASI,请使用 --allow-wasi 标志。

运行时 API

当通过 --permission 标志启用权限模型时,process 对象会添加一个新的属性 permission。此属性包含一个函数:

permission.has(scope[, reference])

运行时检查权限的 API 调用 (permission.has())

js
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

文件系统权限

默认情况下,权限模型通过 node:fs 模块限制对文件系统的访问。它不能保证用户无法通过其他方式访问文件系统,例如通过 node:sqlite 模块。

要允许访问文件系统,请使用 --allow-fs-read--allow-fs-write 标志:

bash
$ node --permission --allow-fs-read=* --allow-fs-write=* index.js
Hello world!

这两个标志的有效参数为:

  • * - 分别允许所有 FileSystemReadFileSystemWrite 操作。
  • 以逗号 (,) 分隔的路径,分别只允许匹配的 FileSystemReadFileSystemWrite 操作。

示例:

  • --allow-fs-read=* - 将允许所有 FileSystemRead 操作。
  • --allow-fs-write=* - 将允许所有 FileSystemWrite 操作。
  • --allow-fs-write=/tmp/ - 将允许对 /tmp/ 文件夹进行 FileSystemWrite 访问。
  • --allow-fs-read=/tmp/ --allow-fs-read=/home/.gitignore - 允许对 /tmp/ 文件夹/home/.gitignore 路径进行 FileSystemRead 访问。

也支持通配符:

  • --allow-fs-read=/home/test* 将允许读取与通配符匹配的所有内容。例如:/home/test/file1/home/test2

在传递通配符字符 (*) 后,所有后续字符都将被忽略。例如:/home/*.js 的作用类似于 /home/*

初始化权限模型时,如果指定的目录存在,它将自动添加通配符 (_)。例如,如果 /home/test/files 存在,则将其视为 /home/test/files/_。但是,如果目录不存在,则不会添加通配符,访问将仅限于 /home/test/files。如果要允许访问尚不存在的文件夹,请确保显式包含通配符:/my-path/folder-do-not-exist/\*

权限模型约束

使用此系统之前,您需要了解以下约束:

  • 模型不会继承到子节点进程或工作线程。

  • 使用权限模型时,以下功能将受到限制:

    • 原生模块
    • 子进程
    • 工作线程
    • 检查器协议
    • 文件系统访问
    • WASI
  • 权限模型在 Node.js 环境设置完成后初始化。但是,某些标志(例如 --env-file--openssl-config)旨在在环境初始化之前读取文件。因此,此类标志不受权限模型规则的约束。通过 v8.setFlagsFromString 在运行时设置的 V8 标志也是如此。

  • 启用权限模型时,无法在运行时请求 OpenSSL 引擎,这会影响内置的 crypto、https 和 tls 模块。

  • 启用权限模型时,无法加载运行时加载扩展,这会影响 sqlite 模块。

  • 通过 node:fs 模块使用现有文件描述符会绕过权限模型。

限制和已知问题

  • 符号链接将被跟随,即使目标位置不在已授予访问权限的路径集合内。相对符号链接可能允许访问任意文件和目录。在启用权限模型启动应用程序时,必须确保已授予访问权限的路径不包含相对符号链接。