Security
Prototype Pollution
Master Prototype Pollution in JavaScript. Learn how attackers inject properties into the global Object.prototype and implement secure defense strategies.
1. Introduction
Prototype Pollution is a JavaScript-specific security vulnerability that occurs when an attacker mutates the shared prototype helper: Object.prototype, injecting custom properties that pollute all objects created in the application.
2. Why It Matters
Because JavaScript uses prototypal inheritance, adding a property to Object.prototype makes that property available on every object. If an attacker injects a property like isAdmin: true into the prototype, checks like if (user.isAdmin) will return true for all users, bypassing security controls.
3. Real-World Analogy
Think of a Global Template Factory Guideline:
- Standard Template (Blueprint): The factory blueprint guidelines state that every car has four wheels, a steering wheel, and doors.
- Prototype Pollution (Vandalizing the blueprint): An intruder sneaks into the master cabinet room and writes on the master blueprint card: "Every product has a red flag on it" (pollutes
Object.prototype). Symmetrically, every department starts manufacturing items with a red flag, even if they only ordered chairs or desks, corrupting the factory output.
4. How Prototype Pollution Occurs
Prototype pollution typically occurs when an application recursively merges or copies properties from user-controlled objects (like JSON payloads) without validating the property keys (like __proto__ or constructor):
5. Prevention Strategies
To protect your application from Prototype Pollution:
• Block proto/constructor keys: Validate keys before performing recursive merges or deep copies:
• Use prototype-free objects: Create dictionary objects using Object.create(null). These objects do not inherit from Object.prototype and are immune to prototype pollution.
• Freeze the prototype: Freeze the global prototype object to prevent mutations: Object.freeze(Object.prototype).
6. Practical Example
This script demonstrates creating a secure, prototype-free dictionary object to store configuration parameters:
7. Common Mistakes
- • Relying on simple key validation rules: Blocking only the
__proto__key can be bypassed using alternative prototype access pathways (likeconstructor.prototype). Always validate both keys or use a prototype-free object structure.
8. Quick Quiz
Q1: Which JavaScript method allows you to instantiate a dictionary object that does not inherit from Object.prototype?
A) Object.freeze({})
B) Object.create(null)
Answer: B — Object.create(null) creates an object with no prototype chain, making it immune to prototype pollution.
9. Scenario-Based Challenge
The Vulnerable Deep-Clone Helper:
An application performs deep copies of user preference payloads: deepClone(userSettings). Attackers send malicious JSON arrays targeting the prototype chain. Refactor the clone helper to block __proto__ and constructor keys, preventing prototype pollution.
10. Debugging Exercise
Explain why this prototype pollution block can be bypassed, and how to fix it:
function safeSet(obj, path, value) { // Bug: only checks for the __proto__ string key! if (path.includes('__proto__')) { throw new Error('Blocked!'); }// Set value on path... }
// Show how an attacker bypasses this check: // Path: constructor.prototype.isAdmin = true
View Solution
Diagnosis: The check only blocks the __proto__ key, allowing attackers to access the prototype using the constructor pathway (e.g. constructor.prototype).
Fix: Block both keys, or use a secure helper library (like Lodash's safe set functions) to parse object paths safely:
function safeSet(obj, path, value) {
// Block both prototype access keys
if (path.includes('__proto__') || path.includes('constructor') || path.includes('prototype')) {
throw new Error('Blocked!');
}
// execution...
}
11. Interview Questions
🟢 Q1: Explain what Prototype Pollution is and how it can lead to privilege escalation.
Answer: Prototype Pollution is a vulnerability where an attacker mutates JavaScript's shared Object.prototype, injecting properties that pollute all objects.
It leads to privilege escalation because many security controls rely on checking object properties (e.g. checking if a user is an admin using if (user.isAdmin)). If the attacker pollutes the prototype with isAdmin: true, every user object inherits this property, bypassing access control checks.
12. Production Considerations
- • Freeze the Prototype: In security-critical applications, freeze the global object prototype at startup:
Object.freeze(Object.prototype)andObject.freeze(Array.prototype)to block all runtime mutations.