Enhanced Security in Node.js v20: The New Permission Model

A Node process inherits the user's full filesystem and process-spawn rights by default, which means any third-party dependency you install can read your ~/.ssh directory or shell out to curl. Node's Permission Model — --permission, introduced as --experimental-permission in Node 20 and renamed in Node 22 — narrows that surface. The model itself is still Stability 1 (experimental), but the flag is no longer prefixed.

Bun has no permission model as of late 2025; for sandboxing on Bun you're back to OS-level isolation (containers, nsjail, sandbox-exec).

What it covers

ResourceFlag
Filesystem read--allow-fs-read=<path>
Filesystem write--allow-fs-write=<path>
child_process--allow-child-process
worker_threads--allow-worker
WASI--allow-wasi
Native addons--allow-addons

Notably absent: network access. Node has no --allow-net equivalent. If isolating outbound HTTP matters, that gap is the headline.

Enabling it

1node --permission index.js

Everything is denied by default. Grant only what the script needs. Quote glob characters on zsh — bare --allow-fs-read=* gets expanded by the shell:

1node --permission --allow-fs-read='*' --allow-fs-write='/tmp/' index.js

For path-scoped grants:

1node --permission --allow-fs-read=/home/me/project --allow-fs-write=/tmp index.js

Checking permissions at runtime

1process.permission.has('fs.write') // true if any write was granted 2process.permission.has('fs.write', '/tmp/foo.log') // true if /tmp/ matches a granted prefix

Useful for libraries that want to degrade gracefully under restricted permissions.

How it stacks up against Deno

Deno shipped with permissions from day one, so they've had years longer to mature.

Node 22+ Permission ModelDeno 2
Default stateSandbox with --permissionSandbox always
Filesystem--allow-fs-read, --allow-fs-write--allow-read, --allow-write
Child processes--allow-child-process--allow-run
Worker threads--allow-workernot separately gated
Native code--allow-addons, --allow-wasi--allow-ffi (was --allow-plugin pre-1.10)
Networknot gated--allow-net=host:port
Environment varsnot gated--allow-env
Module loadingnot gated--allow-import (Deno 2)
StabilityStability 1 (experimental)Stable

Deno 2 also dropped --allow-hrtime — high-resolution time is no longer permission-gated.

Further reading