登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  科技周边 >  业界新闻

Node.js Permission Model 怎样限制运行时文件访问

来源:17golang原创

时间:2026-10-29 02:18:51 257浏览 收藏

如果一个 Node.js 程序只需要读配置、写缓存,却能顺手访问进程所在机器上的其他文件,可以用 Permission Model 把运行时文件访问收窄到明确目录。官方入口:https://nodejs.org/api/permissions.html。

核心做法是用 --permission 开启默认拒绝,再分别用 --allow-fs-read 和 --allow-fs-write 授权路径。它更像防止可信代码误操作的“安全带”,不是用来承诺恶意代码绝对无法绕过的完整沙箱。

一、先理解 --permission 的默认文件访问边界

启动 Node.js 时加入 --permission,文件系统访问会进入权限检查。应用的入口文件会自动加入允许读取列表,所以 node --permission app.js 可以先加载 app.js;除此之外,代码读取未授权文件时会得到 ERR_ACCESS_DENIED。

这个默认值很重要:它不是“所有文件都能读、只限制写入”,而是先限制文件系统,再按任务补充授权。网络、子进程、Worker、原生插件、WASI、FFI 和 Inspector 等能力也会受到 Permission Model 影响,本文只展开文件读写。

二、用两个参数分别授权读取和写入

假设程序需要读取 ./config 下的配置,并把运行数据写入 ./data,启动命令可以写成:

# 只开放配置目录的读取和数据目录的写入
node --permission \
  --allow-fs-read=./config \
  --allow-fs-write=./data \
  app.js

--allow-fs-read 和 --allow-fs-write 是两套独立范围:能读不代表能写,能写也不代表能读。路径可以使用相对当前工作目录的路径、绝对路径或 *;例如 --allow-fs-write=/tmp/ 只把写入范围交给该目录。生产启动脚本应优先写出实际目录,而不是直接使用全量通配符。

如果程序确实要访问一个尚不存在的目录,路径末尾应显式带上通配符,例如 --allow-fs-read=/srv/app/cache/*;Node.js 文档说明,对于已经存在的目录,初始化时可能自动补成目录通配范围,而不存在的目录不会自动补这个通配符。

Node.js Permission Model 中入口文件、配置读取目录和数据写入目录的静态权限边界说明图
图1:结构说明图,查看入口文件、读取范围和写入范围的边界;这不是运行截图。

三、把权限清单放进配置文件

命令行参数较多时,可以使用 --config-file 读取 Node.js 配置文件。权限项放在顶层 permission 对象中:

{
  "permission": {
    "allow-fs-read": ["./config"],
    "allow-fs-write": ["./data"],
    "allow-child-process": false,
    "allow-worker": false,
    "allow-net": false
  }
}

保存为 node.config.json 后,用下面的命令启动:

# 配置文件中的 permission 节点会自动启用权限模型
node --config-file=node.config.json app.js

JSON 不能写注释,因此字段旁边的说明要放在文档或配置说明里;不要为了注释破坏 JSON 格式。配置文件的好处是可以把读写目录和其他能力开关一起提交审查,减少启动脚本被多处复制后出现权限漂移。

Node.js 配置文件 permission 节点与运行时文件权限范围的静态关系说明图
图2:关系说明图,查看 node.config.json、permission 节点与运行时授权范围之间的关系;这不是运行结果截图。

四、权限收窄后最容易忽略的边界

第一,--permission 不是恶意代码沙箱。官方文档明确 Node.js 信任被要求执行的代码,Permission Model 主要用于避免可信代码意外改文件或使用未显式授予的资源。

第二,符号链接需要单独检查。文档提示,已授权路径中的相对符号链接可能指向授权目录之外的位置;给应用开放目录前,要确认目录里没有把访问范围引向其他位置的相对链接。

第三,已经打开的文件描述符、网络连接或子进程不会因为后续权限变化自动关闭。运行时 API process.permission.drop() 只能影响未来的权限检查,资源生命周期仍要由应用自己关闭或终止。

最后,用 --permission-audit 可以先观察哪些权限检查会被触发而不拒绝访问,再把整理后的最小目录清单切换到 --permission。判断配置是否合适时,重点看“程序实际需要读写哪些目录”,不要把整个工作目录一股脑授权。

常见问题

为什么入口文件能读,旁边的 JSON 却读不到?入口文件会被自动加入允许读取列表,其他文件仍需通过 --allow-fs-read 或配置文件授权。

只允许写入目录时是否也要允许读取?读写是分开的。如果程序在写入前还要读取旧文件、读取目录内容或读取配置,就要单独授予读取范围。

能不能把 Permission Model 当作执行不可信脚本的隔离层?不能。它适合减少可信应用的意外资源访问;面对恶意代码,还需要操作系统级隔离和独立运行身份等边界。

总结:先用 --permission 把文件访问设为默认拒绝,再按“配置只读、数据可写”的任务拆分授权,最后用配置文件固定清单并检查符号链接、已打开资源和模型自身限制。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>