Prevent Prototype Manipulation
The Node.js runtime has introduced a feature to prevent a security vulnerability specific to JavaScript known as prototype pollution. This feature, enabled using a command-line flag, helps to prevent modifications and manipulation to the prototype of objects that are known as Primitives. These primitives are the building blocks of JavaScript, and they include Object
, Array
, Function
, and String
.
The two Node.js command-line flags that can be enabled to remove prototype pollution related vulnerabilities are:
--disable-proto=<mode>
wheremode
can be one ofthrow
orwarn
.--frozen-intrinsics
which freezes the built-in objects to prevent modifications.
Simple Example of Prototype Poisoning
Consider the following example to demonstrate a prototype poisoning vulnerability:
In the first phase, we demonstrate how a payload received from users may be a JavaScript object. That object, may be manipulated to include a __proto__
property, which is then assigned to an empty object. In the second phase, when JSON.parse()
is called, the __proto__
property is treated as a valid property and together with the Object.assign()
method, this combination results in the isAdmin
property being added to the empty object.
The end result is that the isAdmin
property gets added to the empty object, which is then printed to the console. This overrides the __proto__
property of the object, which is a security vulnerability.
Simple Example of Prototype Pollution
Often, prototype pollution is demonstrated with the classic example of unsafe deep merging of objects. So popular, that this practice has been ill-followed by developers and maintainers so much that dozens of libraries, including lodash
, have been affected by this vulnerability.
For the purpose of our demonstration though, I will display a simple example of prototype pollution that uses direct object access to pollute the Object
prototype. We will do so by specifically accessing 2-dimensional nested properties of an object.
Prevent Prototype Pollution
To minimize the impact of prototype pollution for Node.js applications, you should enable the Node.js runtime flag --disable-proto=throw
and --disable-proto=warn
. This will throw an error or log a warning when a prototype pollution attempt is detected.