Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions doc/api/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -2322,6 +2322,9 @@ changes:
Enable the Permission Model for current process. When enabled, the
following permissions are restricted:

> See also [`--permission-audit`](#--permission-audit) for an audit-only mode
> that logs violations without denying access.

* File System - manageable through
[`--allow-fs-read`][], [`--allow-fs-write`][] flags
* Network - manageable through [`--allow-net`][] flag
Expand All @@ -2337,9 +2340,22 @@ following permissions are restricted:
added: v25.8.0
-->

Enable audit only for the permission model. When enabled, permission checks
are performed but access is not denied. Instead, a warning is emitted for
each permission violation via diagnostics channel.
Enable audit mode for the permission model. When enabled, permission checks
are performed but access is **not** denied — no `ERR_ACCESS_DENIED` error is
thrown. Instead, each permission violation is published through the
`node:diagnostics_channel` module, and execution continues normally.

This flag does not require [`--permission`](#--permission) to be specified. The
`--allow-*` flags are not needed in audit mode, since no
access is denied.

Audit mode is useful for discovering what permissions your application
requires before deploying with [`--permission`](#--permission). See the
[Permission Model][] documentation for the list of diagnostics channel names
and the message format.

If both [`--permission`](#--permission) and `--permission-audit` are specified,
`--permission` takes precedence and the Permission Model runs in enforce mode.

### `--preserve-symlinks`

Expand Down
66 changes: 64 additions & 2 deletions doc/api/permissions.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,17 @@ will restrict access to all available permissions.
The available permissions are documented by the [`--permission`][]
flag.

The Permission Model has two operational modes:

* **Enforce mode** (default when using [`--permission`][]): Access is denied and
an `ERR_ACCESS_DENIED` error is thrown for any operation the process has not
been granted permission to perform.
* **Audit mode** (when using [`--permission-audit`][]): Permission checks are
performed and violations are published through the diagnostics channel, but
access is **not** denied. Execution continues normally. This mode is useful
for discovering what permissions your application requires before deploying
with enforce mode.

When starting Node.js with `--permission`,
the ability to access the file system through the `fs` module, access the network,
spawn processes, use `node:worker_threads`, use native addons, use WASI, use
Expand Down Expand Up @@ -77,8 +88,8 @@ flag. For WASI, use the [`--allow-wasi`][] flag. For FFI, use the
#### Runtime API

When enabling the Permission Model through the [`--permission`][]
flag a new property `permission` is added to the `process` object.
This property contains the following functions:
or [`--permission-audit`][] flags, a new property `permission` is added to the
`process` object. This property contains the following functions:

##### `permission.has(scope[, reference])`

Expand Down Expand Up @@ -127,6 +138,56 @@ process.permission.has('fs.read', '/etc/myapp/config.json'); // false
process.permission.drop('child');
```

#### Audit Mode

The [`--permission-audit`][] flag enables audit mode for the Permission Model.
In audit mode, permission checks are performed but access is **not** denied —
no `ERR_ACCESS_DENIED` error is thrown. Instead, each permission violation is
published through the `node:diagnostics_channel` module, allowing the
application to observe and log which operations would be denied under enforce
mode. Execution continues normally.

Audit mode is useful for discovering what permissions your application
requires before deploying with [`--permission`][]. It can also be combined
with the [`--allow-fs-read`][], [`--allow-fs-write`][], [`--allow-net`][],
[`--allow-child-process`][], [`--allow-worker`][], [`--allow-addons`][],
[`--allow-wasi`][], and [`--allow-ffi`][] flags to audit a subset of
permissions while granting others.

When a permission check fails in audit mode, a message is published to the
diagnostics channel corresponding to the denied scope. The channel names are:

* `node:permission-model:fs` — File System (read and write)
* `node:permission-model:net` — Network
* `node:permission-model:child` — Child Process
* `node:permission-model:worker` — Worker Threads
* `node:permission-model:inspector` — Inspector
* `node:permission-model:wasi` — WASI
* `node:permission-model:addon` — Native Addons
* `node:permission-model:ffi` — FFI

Each message is an object with the following properties:

* `permission` {string} The name of the denied permission scope.
* `resource` {string} The resource that access was denied to (e.g. a file path
or host).

```js
const diagnostics_channel = require('node:diagnostics_channel');

diagnostics_channel.channel('node:permission-model:fs').subscribe((msg) => {
console.log(`Permission denied: ${msg.permission} on ${msg.resource}`);
});

// Running with --permission-audit, this publishes a diagnostics channel
// message but does not throw
const fs = require('node:fs');
fs.readFileSync('/etc/passwd');
```

If both [`--permission`][] and [`--permission-audit`][] are specified,
`--permission` takes precedence and the Permission Model runs in enforce mode.

#### File System Permissions

The Permission Model, by default, restricts access to the file system through the `node:fs` module.
Expand Down Expand Up @@ -324,6 +385,7 @@ Developers relying on --permission to sandbox untrusted code should be aware tha
[`--allow-net`]: cli.md#--allow-net
[`--allow-wasi`]: cli.md#--allow-wasi
[`--allow-worker`]: cli.md#--allow-worker
[`--permission-audit`]: cli.md#--permission-audit
[`--permission`]: cli.md#--permission
[`npx`]: https://docs.npmjs.com/cli/commands/npx
[`permission.has()`]: process.md#processpermissionhasscope-reference
11 changes: 10 additions & 1 deletion doc/api/process.md
Original file line number Diff line number Diff line change
Expand Up @@ -3128,7 +3128,8 @@ added: v20.0.0

* Type: {Object}

This API is available through the [`--permission`][] flag.
This API is available through the [`--permission`][] or
[`--permission-audit`][] flags.

`process.permission` is an object whose methods are used to manage permissions
for the current process. Additional documentation is available in the
Expand All @@ -3149,6 +3150,9 @@ If no reference is provided, a global scope is assumed, for instance,
`process.permission.has('fs.read')` will check if the process has ALL
file system read permissions.

In audit mode ([`--permission-audit`][]), this method still returns the actual
permission status, but denied operations will not throw `ERR_ACCESS_DENIED`.

The reference has a meaning based on the provided scope. For example,
the reference when the scope is File System means files and folders.

Expand Down Expand Up @@ -3183,6 +3187,10 @@ Drops the specified permission from the current process. This operation is
**irreversible** — once a permission is dropped, it cannot be restored through
any Node.js API.

In audit mode ([`--permission-audit`][]), dropping a permission takes effect,
but since denied operations do not throw, the impact is limited to changing the
return value of `permission.has()`.

If no reference is provided, the entire scope is dropped. For example,
`process.permission.drop('fs.read')` will revoke ALL file system read
permissions.
Expand Down Expand Up @@ -4614,6 +4622,7 @@ cases:
[`'message'`]: child_process.md#event-message
[`'uncaughtException'`]: #event-uncaughtexception
[`--no-deprecation`]: cli.md#--no-deprecation
[`--permission-audit`]: cli.md#--permission-audit
[`--permission`]: cli.md#--permission
[`--unhandled-rejections`]: cli.md#--unhandled-rejectionsmode
[`Buffer`]: buffer.md
Expand Down
17 changes: 14 additions & 3 deletions doc/node.1
Original file line number Diff line number Diff line change
Expand Up @@ -1166,6 +1166,7 @@ developers may leverage to detect deprecated API usage.
.It Fl -permission
Enable the Permission Model for current process. When enabled, the
following permissions are restricted:

.Bl -bullet
.It
File System - manageable through
Expand All @@ -1185,9 +1186,19 @@ FFI - manageable through \fB--allow-ffi\fR flag
.El
.
.It Fl -permission-audit
Enable audit only for the permission model. When enabled, permission checks
are performed but access is not denied. Instead, a warning is emitted for
each permission violation via diagnostics channel.
Enable audit mode for the permission model. When enabled, permission checks
are performed but access is \fBnot\fR denied — no \fBERR_ACCESS_DENIED\fR error is
thrown. Instead, each permission violation is published through the
\fBnode:diagnostics_channel\fR module, and execution continues normally.
This flag does not require \fB--permission\fR to be specified. The
\fB--allow-*\fR flags are not needed in audit mode, since no
access is denied.
Audit mode is useful for discovering what permissions your application
requires before deploying with \fB--permission\fR. See the
Permission Model documentation for the list of diagnostics channel names
and the message format.
If both \fB--permission\fR and \fB--permission-audit\fR are specified,
\fB--permission\fR takes precedence and the Permission Model runs in enforce mode.
.
.It Fl -preserve-symlinks
Instructs the module loader to preserve symbolic links when resolving and
Expand Down
Loading