Sign in
Topics
Let prompts build your secure app infrastructure.
What is prototype pollution—and why does it matter? Discover how a minor code change can expose your entire application. This guide breaks down the risks, real-world impact, and provides guidance on how to defend your JavaScript projects.
A single line of code can silently open the door to serious security threats.
As JavaScript applications handle more user input and third-party data, a hidden risk has started to surface—one that targets the very foundation of how objects behave.
What happens when attackers gain control over the object prototype itself?
This blog explores what prototype pollution is and how malicious payloads can compromise the prototype chain, impacting everything from access control to application stability. You’ll see how these attacks happen, what kind of damage they cause, and how to prevent them before they reach production.
Let’s get started with how this vulnerability works and what it means for your code.
Prototype pollution is a JavaScript vulnerability that allows attackers to modify the object’s prototype, thereby affecting all JavaScript objects that inherit from it. In simpler terms, it’s like changing the blueprint of every house in a neighborhood by tweaking a single base plan. This leads to severe issues like denial of service, remote code execution, and unauthorized access.
Attackers exploit this by injecting malicious properties into an empty object or an existing object, which then propagates across the application's logic. This attack surface was unintentionally introduced with ECMAScript 2015, which made the proto
attribute a standard part of the prototype chain.
Prototype pollution occurs when a target object accepts user input that manipulates the object’s prototype.
Here's how:
JavaScript uses the proto
property to link an object to its prototype object
Modifying proto
on one object alters the base behavior of many created objects
If no input validation is enforced, attackers can add arbitrary properties to the default prototype
Let’s say your app merges user input like this:
1let config = {}; 2deepMerge(config, userInput);
If userInput
contains:
1{ "__proto__": { "isAdmin": true } }
Then suddenly, every object created in the app will have isAdmin
set to true
.
The following key components are crucial for understanding how prototype pollution works:
Component | Explanation |
---|---|
object’s prototype | Base object from which others inherit properties |
merge function | Merges nested properties, often without validation |
created object | Any object that inherits from the polluted prototype |
javascript runtime | The execution environment, such as Node.js or browsers |
target object | The object that receives the polluted input |
1{ "__proto__": { "role": "admin" } }
This payload enables attackers to gain unauthorized access by modifying the role
 of every object they create.
1{ "__proto__": { "toString": "A".repeat(1000000) } }
Overwrites the toString
method, causing the app to crash due to resource exhaustion. This is a classic denial-of-service use case.
In server-side apps using poorly validated input with eval or dynamic functions, prototype pollution enables arbitrary code execution. By modifying critical configuration settings or control properties, attackers can hijack logic and achieve remote code execution.
Client-side prototype pollution targets JavaScript objects in browsers.
It often leads to:
DOM manipulation
Cross-site scripting
Arbitrary property injection
Example: Injecting a script through the browser console that manipulates DOM event handlers.
Server-side prototype pollution is more severe and includes:
Unauthorized data access
Privilege escalation
Remote code or arbitrary JavaScript execution
SQL injections
It is especially risky in systems that use object-oriented languages, such as Node.js.
Numerous libraries have been known to suffer from prototype pollution vulnerabilities, including:
lodash (pre-4.17.15)
minimist
jQuery
express
These often use recursive merge functions or cloneDeep, which fail to properly sanitize nested properties.
A prototype pollution payload is any input that includes proto
or its variants like constructor.prototype
.
A prototype pollution gadget refers to functions or objects that use polluted properties to perform sensitive operations. For example, a gadget may rely on the admin
flag without verifying its origin, making it vulnerable to exploitation.
Here's what prototype pollution vulnerabilities can lead to:
Remote Code Execution – Modify configurations to execute system commands
Denial of Service – Crash apps via oversized payloads or recursive loops
Arbitrary Code Execution – Run injected scripts with application-level privileges
Poison Prototype Objects – Alter global object behavior, affecting all modules
Strategy | Details |
---|---|
Avoid Unsafe Merge Functions | Especially those that copy nested properties without checks |
Use Object.create(null) | Prevents inheritance from Object.prototype, creating a clean object literal |
Freeze Prototypes | Using Object.freeze(Object.prototype) blocks unauthorized changes |
Validate User Input | Always enforce schemas for JSON data |
Use Detection Tools | Tools like Burp Suite DOM Invader catch client side prototype pollution |
The JavaScript context is highly flexible. The language runtime allows dynamic object creation and modification.
While powerful, this also means attackers can:
Modify default values of functions
Alter the base object logic
Inject arbitrary properties during object creation
Such a definition of dynamic behavior makes JavaScript both versatile and susceptible to vulnerabilities.
Prototype pollution is not just a theoretical risk; it’s a real-world vulnerability that threatens both client-side and server-side applications by exposing them to remote code execution, denial-of-service attacks, and arbitrary property injection. By understanding how object prototype manipulation works, you can eliminate a critical entry point for attackers and regain control over your JavaScript objects.
Implementing prototype pollution mitigation techniques, such as input validation, avoiding unsafe merge functions, and using prototypeless objects, directly addresses these risks. These methods offer a proactive defense against hidden flaws that can compromise the integrity of your entire application.
Don’t wait for a breach to reveal your vulnerabilities. Audit your code, secure your dependencies, and empower your team to recognize and prevent prototype pollution attacks before they cause damage.