The Node.js permission model restricts what a process may do with files, the network, child processes and more. The Node.js docs call it a seat belt: it protects against trusted code making unintended changes, and it does not defend against malicious code.
What it is and its status
The permission model was added in v20.0.0. According to the docs, it is Stability 2 (Stable), and it stopped being experimental as of v23.5.0 and v22.13.0. You turn it on with --permission, after which denied operations throw ERR_ACCESS_DENIED.
The permissions you can grant
The documentation lists flags for file system read and write (with a path, or * for all), child processes, worker threads, network access, native addons, WASI, and a few others. A typical start is to allow reading only your app folder:
node --permission --allow-fs-read=/app --allow-net index.js
You can also check at runtime with process.permission.has(), which returns a boolean, and revoke a grant irreversibly with process.permission.drop(). Only the exact grant that was made can be dropped, not one file inside a granted directory.
Audit mode
Run with --permission-audit to log violations to diagnostics channels without blocking them. That is a good way to learn what your app really touches before you enforce. If both flags are set, enforcement wins.
What it does not protect against
The docs list limits that matter:
- Malicious code. It can be bypassed, and Node.js trusts any code it is asked to run.
- Symbolic links are followed even outside granted paths.
- Already open file descriptors bypass the file checks.
- Worker threads inherit parent flags unless
execArgvis set. - Startup time flags such as
--env-filerun outside the model. process._debugProcess(pid)is not gated, so a sandboxed process can signal another Node.js process owned by the same OS user. The docs suggest separate OS users or OS level isolation.
When it helps
Use it to reduce accidents: a dependency that writes where it should not, a script that reads the whole disk, or a build tool that opens network sockets. Do not use it as the only barrier against an untrusted package. For that, combine it with container isolation, a separate user, and review of what you install.
A practical rollout
- Run in audit mode in a test environment.
- Read the violations and decide what to grant.
- Enforce in staging with the minimal flags.
- Keep container or VM isolation for untrusted code.
Quick check
Does the permission model stop a malicious npm package?
No. The docs say it protects against trusted code making unintended changes, not malicious code.
Is it still experimental?
The docs list it as Stable, no longer experimental as of v23.5.0 and v22.13.0.
Sources
Last reviewed: 19 October 2026.