Cybersecurity glossary
What is Prototype Pollution?
Learn what prototype pollution is in JavaScript, how attackers abuse __proto__ and constructor.prototype, how client- and server-side variants differ, and how to prevent pollution of Object.prototype.
Definition
Prototype Pollution is a JavaScript vulnerability in which untrusted input modifies Object.prototype (or other prototypes) via keys such as __proto__ or constructor.prototype, causing unexpected inherited properties that can escalate into XSS, logic bypasses, or remote code execution.
Why prototype pollution matters
JavaScript’s inheritance model is powerful and easy to misuse. Almost every {} shares Object.prototype. When untrusted data can write keys like __proto__ or walk constructor.prototype, Prototype Pollution plants properties that appear on unrelated objects across the application.
That single bug class bridges frontends and backends: the same inheritance abuse can enable DOM XSS in a SPA or remote code execution in Node.js, depending on where polluted properties are read.
How prototype pollution works
Supply special property paths
Attackers send __proto__, constructor, or prototype keys in JSON, query objects, or nested configs.
Unsafe merge or assignment
Deep merge, clone, or recursive setters copy those keys onto a real prototype object.
Inherited properties appear everywhere
Later code reading obj.isAdmin or obj.shell sees attacker values via the prototype chain.
Gadget turns pollution into impact
XSS sinks, auth checks, child_process options, or template paths consume the polluted values.
Core concepts to know
__proto__ assignment
Payloads like {"__proto__":{"polluted":true}} target Object.prototype during merges.
constructor.prototype
Alternate path when __proto__ is blocked but constructor remains writable in assignment logic.
Client-side gadgets
Polluted properties reach innerHTML, script URLs, or SPA auth flags in the browser.
Server-side gadgets
Node merges feed polluted options into dangerous APIs, sometimes enabling RCE.
Prevention that works
| Control | Notes |
|---|---|
| Block dangerous keys | Reject __proto__, constructor, and prototype during recursive merges and parsers |
| Null-prototype objects | Use Object.create(null) for dictionaries so inherited keys cannot appear |
| Hardened merge utilities | Prefer libraries and patterns that skip prototype paths by design |
| Schema validation | Allowlist expected fields before deep-assigning untrusted JSON |
| Freeze critical prototypes | Object.freeze(Object.prototype) where compatibility allows, as defense in depth |
| Separate client vs server tests | Probe browser gadgets and Node sinks independently after confirming pollution |
- Search for deep merge, extend, defaultsDeep, and recursive Object.assign of user input.
- Deny __proto__, constructor, and prototype keys at every recursive assignment boundary.
- Store untrusted key-value data in Map or Object.create(null), not plain {}.
- Validate JSON with schemas before merging into application configuration.
- Add regression tests that assert Object.prototype stays clean after parsing attacker JSON.
- Review client gadgets (DOM sinks) and server gadgets (child_process, template paths) separately.
- Upgrade merge/clone dependencies known for historical pollution bugs.
- Treat confirmed prototype pollution as a security defect even before a full RCE/XSS chain.
The practical takeaway
Prototype Pollution is inheritance abuse: attacker-controlled keys rewrite shared prototypes, then gadgets turn those properties into XSS, logic bypass, or code execution.
Block dangerous keys, stop unsafe deep merges, and assume any polluted property will eventually be read by something important.
Related security terms
Client-Side Prototype Pollution
Browser-focused pollution that often chains into DOM XSS or privilege gadgets.
Server-Side Prototype Pollution
Node.js merge/clone pollution that can reach RCE and dangerous sinks.
Cross-Site Scripting (XSS)
A frequent client-side impact when polluted properties reach DOM sinks.
Code Injection
Server gadgets may turn polluted config into executable code paths.
Frequently asked questions
What is prototype pollution in simple terms?
JavaScript objects inherit properties from a shared prototype. If an attacker can set properties on that shared prototype, almost every object in the program suddenly 'has' those properties—and security-sensitive code may trust them.
What are the common pollution vectors?
Nested keys named __proto__, constructor, and prototype during deep merges, recursive property assignment, or unsafe JSON-to-object utilities that walk attacker-controlled structures.
Is prototype pollution only a browser issue?
No. It affects both browsers and Node.js. Client-side cases often lead to XSS; server-side cases can alter application logic or enable remote code execution via library gadgets.
Why does polluting Object.prototype matter so much?
Most plain objects inherit from Object.prototype. A single polluted property can change defaults, configuration lookups, and control-flow checks across the entire runtime.
How do you prevent prototype pollution?
Block dangerous keys, use Object.create(null) for maps, prefer hardened merge libraries, freeze prototypes where practical, validate JSON schemas, and avoid recursive assignment of untrusted objects.
Does using Map instead of plain objects help?
Yes for key-value storage. Map does not use the prototype chain for keys, so it avoids many inheritance surprises—but merge utilities that still write to plain objects remain risky.
Is detecting pollution enough without a gadget?
Pollution alone proves a flaw. Impact depends on gadgets—code that reads the polluted property unsafely. Treat pollution as high priority even before a full exploit chain is proven.
References
Explore authoritative guidance and frameworks related to prototype pollution.
Explore every security definition
Return to the glossary to search by term, alias, starting letter, or security category.