~ 4 min read
Introducing Node.js Security Permissions Model, Threat Model, and Security Releases
In this blog post, I’ll shortly review some of the built-in security features in Node.js that can help you secure your applications. These features include the new and still experimental Node.js Permissions Model, which allows you to enforce code execution boundaries, and the Node.js Security Threat Model, which outlines potential threats to Node.js applications, being aware on Node.js Security Releases and how to keep up with them.
Node.js Permissions Model: Enforcing Code Execution Boundaries
Node.js 18 introduces a new experimental feature now available in Node.js 20 too: the permissions model. This model aims to enhance security by allowing granular control over what resources code can access within the Node.js process.
Traditionally, Node.js code has relied on a privileged execution environment. This means code could access most system resources by default. For example, a Node.js application could read and write files arbitrarily on the file system, open network connections, and spawn child processes without any restrictions.
The Node.js Permissions Model operates with two key concepts: permissions and flags. Permissions define specific actions code can perform (e.g., fs.read, fs.write), while flags control the overall model behavior and allowed operations.
By default, the Permissions Model is disabled. To activate it, use the --experimental-permission
flag when starting Node.js. This flag immediately restricts access to all available permissions unless overridden with specific allow flags. Here’s what happens when you run your application without explicit permissions:
$ node --experimental-permission index.js
node:internal/modules/cjs/loader:171
const result = internalModuleStat(filename);
^
Error: Access to this API has been restricted
This error message indicates that the fs module’s stat function, used for file system access, is restricted by the Permissions Model.
To enable specific permissions, use the --experimental-permission
flag followed by the permission name. For example, to allow file system read access, use the following command:
$ node --experimental-permit=fs.read index.js
Other supported flags are for example:
--allow-child-process
: Allows spawning child processes.--allow-worker
: Allows creating worker threads usingnode:worker_threads
.--allow-addons
: Allows using native addons.--allow-fs-read
and--allow-fs-write
: Control file system access permissions.
You can then also check for permissions in your code using the permissions
module so that you can assert at runtime whether the Node.js process has the necessary permissions to execute specific operations.
// true (assuming write access is allowed)
process.permission.has('fs.write');
// Might be false if write access is restricted to specific folders
process.permission.has('fs.write', '/home/user/protected-folder');
Keeping Up with Node.js Security Releases
Node.js releases security updates periodically to address vulnerabilities reported by the community. These vulnerabilities are documented as Common Vulnerabilities and Exposures (CVEs). Let’s look at some recent CVEs to understand the potential risks:
CVE-2024-27983 (High Severity): This vulnerability in Node.js HTTP/2 server could lead to Denial-of-Service (DoS) attacks. An attacker could exploit this by sending malformed HTTP requests.
CVE-2024-21892 (High Severity): This critical vulnerability allows code injection and privilege escalation through Linux capabilities. Attackers could potentially gain unauthorized access to your system. These are just a few examples, and new vulnerabilities are discovered regularly.
đź‘‹ Just a quick break
I'm Liran Tal and I'm the author of the newest series of expert Node.js Secure Coding books. Check it out and level up your JavaScript
Staying Informed about Security Updates:
Here are practical steps to ensure you’re notified about security updates:
Subscribe to the Node.js security mailing list: The nodejs-sec mailing list provides low-volume announcements about security vulnerabilities and related releases.
Follow the official Node.js blog: The Node.js blog regularly publishes articles about security releases. Pay attention to posts with titles like “Security Releases”.
Utilize Node.js version management tools: Tools like
nvm
andfnm
make it easy to switch between Node.js versions. They also provide commands to list available versions and check for updates.Use Official Node.js Docker Images: The official Node.js Docker Hub images are built from secure base images and often include the latest security patches. Pin image versions and avoid using the latest tag when pulling Node.js Docker images. Specify a specific version number to ensure consistent security posture across deployments.
Node.js Security Threat Model
Understanding the threat model for Node.js applications is crucial for building secure systems, and a community of Node.js volunteers maintains a security working group that focuses on identifying and mitigating security risks.
One of the outcomes of this work is the Node.js threat model. This document outlines the potential threats to Node.js applications and provides guidance on how to mitigate them. Some of the key threats include:
- The loss of integrity or confidentiality of data protected through the correct use of Node.js APIs.
- The loss of availability of services provided by Node.js applications, including degradation of performance.
You are also encouraged to report security vulnerabilities in Node.js through the Node.js JavaScript Runtime project on HackerOne.