What Is Prototype Pollution
Prototype pollution is a JavaScript vulnerability where an attacker modifies the prototype of a base object (Object.prototype), injecting properties that are inherited by all objects in the application. Because JavaScript uses prototypal inheritance, any property added to Object.prototype becomes accessible on every object unless explicitly overridden.
Mapped to CWE-1321 and classified under OWASP A03:2021 – Injection, prototype pollution can lead to denial of service, authentication bypass, or remote code execution depending on how the polluted properties are used downstream in the application.
The vulnerability arises from JavaScript's dynamic property assignment and prototype chain lookup. When code recursively merges objects or sets properties using attacker-controlled keys, the special keys __proto__, constructor, and prototype can modify the prototype chain rather than the target object.
How the Prototype Chain Is Exploited
Prototype pollution typically occurs through unsafe object merging or property assignment functions:
// Vulnerable deep merge function
function merge(target, source) {
for (const key in source) {
if (typeof source[key] === 'object') {
if (!target[key]) target[key] = {};
merge(target[key], source[key]);
} else {
target[key] = source[key];
}
}
}
// Attacker-controlled input
const malicious = JSON.parse('{"__proto__": {"isAdmin": true}}');
merge({}, malicious);
// Now EVERY object has isAdmin = true
const user = {};
console.log(user.isAdmin); // true
The attacker sets __proto__ as a key, which the merge function follows into Object.prototype, adding isAdmin to the prototype of all objects.
Exploitation Scenarios
- Authentication bypass: If the application checks
user.isAdminwithouthasOwnProperty, polluting the prototype withisAdmin: truegrants admin access to all users - Denial of service: Polluting
toStringorvalueOfon the prototype crashes the application when objects are coerced to strings - Remote code execution: In server-side JavaScript, polluting properties consumed by template engines (e.g., Handlebars, Pug) or child process spawning can lead to RCE
Real-World Prototype Pollution CVEs
- Lodash (CVE-2020-8203): The
zipObjectDeepfunction allowed prototype pollution through crafted property paths. Lodash has over 25 million weekly npm downloads, making this one of the most impactful JavaScript CVEs. - jQuery (CVE-2019-11358): The
$.extend(true, {}, malicious)deep merge function was vulnerable to prototype pollution in jQuery versions before 3.4.0. - Handlebars (CVE-2021-23369): Prototype pollution in the template compiler led to remote code execution when processing attacker-controlled templates.
- minimist (CVE-2020-7598): The popular argument parser (used by thousands of CLI tools) was vulnerable to prototype pollution through crafted command-line arguments.
These CVEs demonstrate that prototype pollution affects foundational JavaScript libraries used across millions of projects.
How CodeSlick Detects Prototype Pollution
CodeSlick identifies prototype pollution patterns in JavaScript and TypeScript codebases:
- Recursive object merge functions that do not filter
__proto__,constructor, andprototypekeys - Dynamic property assignment using bracket notation with user-controlled keys (
obj[userInput] = value) - Path-based property setting functions (e.g.,
set(obj, path, value)) without path sanitization
Findings are mapped to CWE-1321 with CVSS severity scoring. CodeSlick's AI-powered fixes suggest safe alternatives including Object.create(null), key allowlisting, and property descriptor freezing.
Detect prototype pollution vulnerabilities in your JavaScript and TypeScript code automatically.