Skip to content

Commit

Permalink
permission,net,dgram: add permission for net
Browse files Browse the repository at this point in the history
  • Loading branch information
theanarkh committed Jun 12, 2024
1 parent ce531af commit ed0b811
Show file tree
Hide file tree
Showing 16 changed files with 758 additions and 1 deletion.
180 changes: 180 additions & 0 deletions doc/api/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,176 @@ Error: Access to this API has been restricted
}
```

### `--allow-net-tcp-in`

<!-- YAML
added: REPLACEME
-->

> Stability: 1.1 - Active development
When using the [Permission Model][], the process will not be able to bind to any
ip or port by default. Attempts to do so will throw an `ERR_ACCESS_DENIED` unless
the user explicitly passes the `--allow-net-tcp-in` flag when starting Node.js.

The valid arguments for the `--allow-net-tcp-in` flag are:

* `*` - To allow all `bind` operations.
* Multiple addresses can be allowed using multiple `--allow-net-tcp-in` flags.
Example `--allow-net-tcp-in=127.0.0.1:8080 --allow-net-tcp-in=127.0.0.1:9090`

Example:

```js
const net = require('node:net');
net.createServer().listen(9297, '127.0.0.1')
```

```console
$ node --experimental-permission --allow-fs-read=./index.js index.js
node:net:1840
err = handle.bind(address, port);
^

Error: Access to this API has been restricted
at createServerHandle (node:net:1840:20)
at Server.setupListenHandle [as _listen2] (node:net:1879:14)
at listenInCluster (node:net:1961:12)
at doListen (node:net:2135:7)
at process.processTicksAndRejections (node:internal/process/task_queues:83:21) {
code: 'ERR_ACCESS_DENIED',
permission: 'NetTCPIn',
resource: '127.0.0.1/9297'
}
```

### `--allow-net-tcp-out`

<!-- YAML
added: REPLACEME
-->

> Stability: 1.1 - Active development
When using the [Permission Model][], the process will not be able to connect to any
ip or port by default. Attempts to do so will throw an `ERR_ACCESS_DENIED` unless
the user explicitly passes the `--allow-net-tcp-out` flag when starting Node.js.

The valid arguments for the `--allow-net-tcp-out` flag are:

* `*` - To allow all `connect` operations.
* Multiple addresses can be allowed using multiple `--allow-net-tcp-out` flags.
Example `--allow-net-tcp-out=127.0.0.1:8080 --allow-net-tcp-out=127.0.0.1:9090`

Example:

```js
const net = require('node:net');
net.connect(9297, '127.0.0.1');
```

```console
$ node --experimental-permission --allow-fs-read=./index.js index.js
node:net:1075
err = self._handle.connect(req, address, port);
^

Error: Access to this API has been restricted
at internalConnect (node:net:1075:26)
at defaultTriggerAsyncIdScope (node:internal/async_hooks:464:18)
at node:net:1324:9
at process.processTicksAndRejections (node:internal/process/task_queues:77:11) {
code: 'ERR_ACCESS_DENIED',
permission: 'NetTCPOut',
resource: '127.0.0.1/9297'
}

```

### `--allow-net-udp-in`

<!-- YAML
added: REPLACEME
-->

> Stability: 1.1 - Active development
When using the [Permission Model][], the process will not be able to bind to any
ip or port by default. Attempts to do so will throw an `ERR_ACCESS_DENIED` unless
the user explicitly passes the `--allow-net-udp-in` flag when starting Node.js.

The valid arguments for the `--allow-net-udp-in` flag are:

* `*` - To allow all `bind` operations.
* Multiple addresses can be allowed using multiple `--allow-net-udp-in` flags.
Example `--allow-net-udp-in=127.0.0.1:8080 --allow-net-udp-in=127.0.0.1:9090`

Example:

```js
const dgram = require('node:dgram');
dgram.createSocket('udp4').bind(9000, '127.0.0.1')
```

```console
$ node --experimental-permission --allow-fs-read=./index.js index.js
node:dgram:364
const err = state.handle.bind(ip, port || 0, flags);
^

Error: Access to this API has been restricted
at node:dgram:364:32
at process.processTicksAndRejections (node:internal/process/task_queues:83:21) {
code: 'ERR_ACCESS_DENIED',
permission: 'NetUDPIn',
resource: '127.0.0.1/9297'
}
```

### `--allow-net-udp-out`

<!-- YAML
added: REPLACEME
-->

> Stability: 1.1 - Active development
When using the [Permission Model][], the process will not be able to connect to any
ip or port by default. Attempts to do so will throw an `ERR_ACCESS_DENIED` unless
the user explicitly passes the `--allow-net-udp-out` flag when starting Node.js.

The valid arguments for the `--allow-net-udp-out` flag are:

* `*` - To allow all `connect` operations.
* Multiple addresses can be allowed using multiple `--allow-net-udp-out` flags.
Example `--allow-net-udp-out=127.0.0.1:8080 --allow-net-udp-out=127.0.0.1:9090`

Example:

```js
const dgram = require('node:dgram');
dgram.createSocket('udp4').bind(8000, '127.0.0.1', function () {
this.connect(9001, '127.0.0.1')
});
```

```console
$ node --experimental-permission --allow-net-udp-in=127.0.0.1/8000 --allow-fs-read=./index.js index.js
node:dgram:433
const err = state.handle.connect(ip, port);
^

Error: Access to this API has been restricted
at doConnect (node:dgram:433:30)
at defaultTriggerAsyncIdScope (node:internal/async_hooks:464:18)
at afterDns (node:dgram:416:5)
at process.processTicksAndRejections (node:internal/process/task_queues:83:21) {
code: 'ERR_ACCESS_DENIED',
permission: 'NetUDPOut',
resource: '127.0.0.1/9001'
}
```

### `--build-snapshot`

<!-- YAML
Expand Down Expand Up @@ -1012,6 +1182,8 @@ following permissions are restricted:
* Child Process - manageable through [`--allow-child-process`][] flag
* Worker Threads - manageable through [`--allow-worker`][] flag
* WASI - manageable through [`--allow-wasi`][] flag
* Net - manageable through [`--allow-net-tcp-in`][], [`--allow-net-tcp-out`][],
[`--allow-net-udp-in`][] and [`--allow-net-udp-out`][] flags

### `--experimental-require-module`

Expand Down Expand Up @@ -2804,6 +2976,10 @@ one is included in the list below.
* `--allow-child-process`
* `--allow-fs-read`
* `--allow-fs-write`
* `--allow-net-tcp-in`
* `--allow-net-tcp-out`
* `--allow-net-udp-in`
* `--allow-net-udp-out`
* `--allow-wasi`
* `--allow-worker`
* `--conditions`, `-C`
Expand Down Expand Up @@ -3356,6 +3532,10 @@ node --stack-trace-limit=12 -p -e "Error.stackTraceLimit" # prints 12
[`--allow-child-process`]: #--allow-child-process
[`--allow-fs-read`]: #--allow-fs-read
[`--allow-fs-write`]: #--allow-fs-write
[`--allow-net-tcp-in`]: #--allow-net-tcp-in
[`--allow-net-tcp-out`]: #--allow-net-tcp-out
[`--allow-net-udp-in`]: #--allow-net-udp-in
[`--allow-net-udp-out`]: #--allow-net-udp-out
[`--allow-wasi`]: #--allow-wasi
[`--allow-worker`]: #--allow-worker
[`--build-snapshot`]: #--build-snapshot
Expand Down
8 changes: 8 additions & 0 deletions doc/api/permissions.md
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,9 @@ using the [`--allow-child-process`][] and [`--allow-worker`][] respectively.
To allow native addons when using permission model, use the [`--allow-addons`][]
flag. For WASI, use the [`--allow-wasi`][] flag.

For net, use the [`--allow-net-tcp-in`][], [`--allow-net-tcp-out`][],
[`--allow-net-udp-in`][] and [`--allow-net-udp-out`][] flags.

#### Runtime API

When enabling the Permission Model through the [`--experimental-permission`][]
Expand Down Expand Up @@ -575,6 +578,7 @@ There are constraints you need to know before using this system:
* Inspector protocol
* File system access
* WASI
* DNS
* The Permission Model is initialized after the Node.js environment is set up.
However, certain flags such as `--env-file` or `--openssl-config` are designed
to read files before environment initialization. As a result, such flags are
Expand All @@ -598,6 +602,10 @@ There are constraints you need to know before using this system:
[`--allow-child-process`]: cli.md#--allow-child-process
[`--allow-fs-read`]: cli.md#--allow-fs-read
[`--allow-fs-write`]: cli.md#--allow-fs-write
[`--allow-net-tcp-in`]: cli.md#--allow-net-tcp-in
[`--allow-net-tcp-out`]: cli.md#--allow-net-tcp-out
[`--allow-net-udp-in`]: cli.md#--allow-net-udp-in
[`--allow-net-udp-out`]: cli.md#--allow-net-udp-out
[`--allow-wasi`]: cli.md#--allow-wasi
[`--allow-worker`]: cli.md#--allow-worker
[`--experimental-permission`]: cli.md#--experimental-permission
Expand Down
12 changes: 12 additions & 0 deletions doc/node.1
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,18 @@ Allow execution of WASI when using the permission model.
.It Fl -allow-worker
Allow creating worker threads when using the permission model.
.
.It Fl -allow-net-tcp-in
Allow bind when using the permission model.
.
.It Fl -allow-net-tcp-out
Allow connect when using the permission model.
.
.It Fl -allow-net-udp-in
Allow bind when using the permission model.
.
.It Fl -allow-net-udp-out
Allow connect when using the permission model.
.
.It Fl -completion-bash
Print source-able bash completion script for Node.js.
.
Expand Down
8 changes: 8 additions & 0 deletions lib/internal/process/pre_execution.js
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,10 @@ function initializePermission() {
const warnFlags = [
'--allow-addons',
'--allow-child-process',
'--allow-net-tcp-in',
'--allow-net-tcp-out',
'--allow-net-udp-in',
'--allow-net-udp-out',
'--allow-wasi',
'--allow-worker',
];
Expand Down Expand Up @@ -574,6 +578,10 @@ function initializePermission() {
'--allow-child-process',
'--allow-wasi',
'--allow-worker',
'--allow-net-tcp-in',
'--allow-net-tcp-out',
'--allow-net-udp-in',
'--allow-net-udp-out',
];
ArrayPrototypeForEach(availablePermissionFlags, (flag) => {
const value = getOptionValue(flag);
Expand Down
2 changes: 2 additions & 0 deletions node.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@
'src/permission/permission.cc',
'src/permission/wasi_permission.cc',
'src/permission/worker_permission.cc',
'src/permission/net_permission.cc',
'src/pipe_wrap.cc',
'src/process_wrap.cc',
'src/signal_wrap.cc',
Expand Down Expand Up @@ -280,6 +281,7 @@
'src/permission/permission.h',
'src/permission/wasi_permission.h',
'src/permission/worker_permission.h',
'src/permission/net_permission.h',
'src/pipe_wrap.h',
'src/req_wrap.h',
'src/req_wrap-inl.h',
Expand Down
20 changes: 20 additions & 0 deletions src/env.cc
Original file line number Diff line number Diff line change
Expand Up @@ -936,6 +936,26 @@ Environment::Environment(IsolateData* isolate_data,
options_->allow_fs_write,
permission::PermissionScope::kFileSystemWrite);
}
if (!options_->allow_net_tcp_in.empty()) {
permission()->Apply(this,
options_->allow_net_tcp_in,
permission::PermissionScope::kNetTCPIn);
}
if (!options_->allow_net_tcp_out.empty()) {
permission()->Apply(this,
options_->allow_net_tcp_out,
permission::PermissionScope::kNetTCPOut);
}
if (!options_->allow_net_udp_in.empty()) {
permission()->Apply(this,
options_->allow_net_udp_in,
permission::PermissionScope::kNetUDPIn);
}
if (!options_->allow_net_udp_out.empty()) {
permission()->Apply(this,
options_->allow_net_udp_out,
permission::PermissionScope::kNetUDPOut);
}
}
}

Expand Down
16 changes: 16 additions & 0 deletions src/node_options.cc
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,22 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
"allow worker threads when any permissions are set",
&EnvironmentOptions::allow_worker_threads,
kAllowedInEnvvar);
AddOption("--allow-net-tcp-in",
"allow host:port or ip:port to listen when any permissions are set",
&EnvironmentOptions::allow_net_tcp_in,
kAllowedInEnvvar);
AddOption("--allow-net-tcp-out",
"allow host:port or ip:port to dial when any permissions are set",
&EnvironmentOptions::allow_net_tcp_out,
kAllowedInEnvvar);
AddOption("--allow-net-udp-in",
"allow host:port or ip:port to bind when any permissions are set",
&EnvironmentOptions::allow_net_udp_in,
kAllowedInEnvvar);
AddOption("--allow-net-udp-out",
"allow host:port or ip:port to connect when any permissions are set",
&EnvironmentOptions::allow_net_udp_out,
kAllowedInEnvvar);
AddOption("--experimental-repl-await",
"experimental await keyword support in REPL",
&EnvironmentOptions::experimental_repl_await,
Expand Down
4 changes: 4 additions & 0 deletions src/node_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@ class EnvironmentOptions : public Options {
bool allow_child_process = false;
bool allow_wasi = false;
bool allow_worker_threads = false;
std::vector<std::string> allow_net_tcp_in;
std::vector<std::string> allow_net_tcp_out;
std::vector<std::string> allow_net_udp_in;
std::vector<std::string> allow_net_udp_out;
bool experimental_repl_await = true;
bool experimental_vm_modules = false;
bool expose_internals = false;
Expand Down
Loading

0 comments on commit ed0b811

Please sign in to comment.