Permissions

Deno is secure by default. Therefore, unless you specifically enable it, a program run with Deno has no file, network, or environment access. Access to security sensitive functionality requires that permisisons have been granted to an executing script through command line flags, or a runtime permission prompt.

For the following example mod.ts has been granted read-only access to the file system. It cannot write to the file system, or perform any other security sensitive functions.

  1. deno run --allow-read mod.ts

Permissions list

The following permissions are available:

  • —allow-env=\ Allow environment access for things like getting and setting of environment variables. Since Deno 1.9, you can specify a optional, comma-separated list of environment variables to provide an allow-list of allowed environment variables.
  • —allow-hrtime Allow high-resolution time measurement. High-resolution time can be used in timing attacks and fingerprinting.
  • —allow-net=\ Allow network access. You can specify an optional, comma-separated list of IP addresses or hostnames (optionally with ports) to provide an allow-list of allowed network addresses.
  • —allow-ffi Allow loading of dynamic libraries. Be aware that dynamic libraries are not run in a sandbox and therefore do not have the same security restrictions as the Deno process. Therefore, use with caution. Please note that —allow-ffi is an unstable feature.
  • —allow-read=\ Allow file system read access. You can specify an optional, comma-separated list of directories or files to provide an allow-list of allowed file system access.
  • —allow-run=\ Allow running subprocesses. Since Deno 1.9, You can specify an options, comma-separated list of subprocesses to provide an allow-list of allowed subprocesses. Be aware that subprocesses are not run in a sandbox and therefore do not have the same security restrictions as the deno process. Therefore, use with caution.
  • —allow-write=\ Allow file system write access. You can specify an optional, comma-separated list of directories or files to provide an allow-list of allowed file system access.
  • -A, —allow-all Allow all permissions. This disables all security.

Permissions allow-list

Deno allows you to control the granularity of some permissions with allow-lists.

File system access

This example restricts file system access by allow-listing only read access to the /usr directory. In consequence the execution fails as the process was attempting to read a file in the /etc directory:

  1. $ deno run --allow-read=/usr https://deno.land/std@$STD_VERSION/examples/cat.ts /etc/passwd
  2. error: Uncaught PermissionDenied: read access to "/etc/passwd", run again with the --allow-read flag
  3. $deno$/dispatch_json.ts:40:11
  4. at DenoError ($deno$/errors.ts:20:5)
  5. ...

Try it out again with the correct permissions by allow-listing /etc instead:

  1. deno run --allow-read=/etc https://deno.land/std@$STD_VERSION/examples/cat.ts /etc/passwd

--allow-write works the same as --allow-read.

Note for Windows users: the /etc and /usr directories and the /etc/passwd file do not exist on Windows. If you want to run this example yourself, replace /etc/passwd with C:\Windows\System32\Drivers\etc\hosts, and /usr with C:\Users.

Network access

  1. // fetch.js
  2. const result = await fetch("https://deno.land/");

This is an example of how to allow-list hostnames, ip addresses, optionally locked to a specified port:

  1. # Multiple hostnames, all ports allowed
  2. deno run --allow-net=github.com,deno.land fetch.js
  3. # A hostname at port 80:
  4. deno run --allow-net=deno.land:80 fetch.js
  5. # An ipv4 address on port 443
  6. deno run --allow-net=1.1.1.1:443 fetch.js
  7. # A ipv6 address, all ports allowed
  8. deno run --allow-net=[2606:4700:4700::1111] fetch.js

If fetch.js tries to establish network connections to any hostname or IP not in the allow-list, the relevant call will error.

Allow net calls to any hostname/ip:

  1. deno run --allow-net fetch.js

Environment variables

  1. // env.js
  2. Deno.env.get("HOME");

This is an example of how to allow-list environment variables:

  1. # Allow all environment variables
  2. deno run --allow-env env.js
  3. # Allow access to only the HOME env var
  4. deno run --allow-env=HOME env.js

Note for Windows users: environment variables are case insensitive on Windows, so Deno also matches them case insensitively in the allow-list.

Subprocess permissions

Subprocesses are very powerful, and can be a little scary: they access system resources irregardless of the permissions you granted to the Deno process that spawns them. The cat program on unix systems can be used to read files from disk. If you start this program through the Deno.run API it will be able to read files from disk even if the parent Deno process can not read the files directly. This is often reffered to as privledge escalation.

Because of this, make sure you carefully consider if you want to grant a program --allow-run access: it essentially invalidates the Deno security sandbox. If you really need to spawn a specific executable, you can reduce the risk by limiting which programs a Deno process can start using an allow-list for the --allow-run flag:

  1. // run.js
  2. const proc = Deno.run({ cmd: ["cat", "/etc/passwd"] });
  1. # Allow only spawning a `cat` subprocess:
  2. deno run --allow-run=cat run.js
  3. # Allow running any subprocess:
  4. deno run --allow-run run.js

Note for Windows users: the cat executable and the /etc/passwd file do not exist on Windows. To try out this example you will need to replace these with an alternatives that exist on Windows.

Conference

Permission flags where explained by Ryan Dahl in his 2020 talk about the Deno security model at Speakeasy JS: https://www.youtube.com/watch?v=r5F6dekUmdE#t=34m57