Application Security · Learn

What is prototype pollution?

Prototype pollution is a JavaScript vulnerability where an attacker injects properties into the base object that every object inherits, changing application behaviour and sometimes reaching code execution. Here is what it is and how to fix it.

Application Security · LearnApplication Penetration Testing
TL;DR

Prototype pollution is a JavaScript vulnerability where an attacker injects properties into `Object.prototype`, the base object every other object inherits from, by abusing keys like __proto__ in user-controlled data. Because the polluted property then appears on all objects, it can change application logic, bypass security checks, cause denial of service, and, combined with the right gadget, reach remote code execution (notably in Node.js). It is caused by unsafe recursive merges of untrusted input, and the fix is safe key handling and object hygiene.

By Shubham Khandare, Delivery Manager, SecureLayer7Updated

What prototype pollution is

In JavaScript, objects inherit from a prototype, and at the top sits `Object.prototype`, which every object shares. If an attacker can set a property on that shared prototype, the property appears on every object in the application.

Prototype pollution happens when code merges or assigns user-controlled data using keys like `__proto__`, `constructor`, or `prototype` without filtering them. A request body such as {"__proto__": {"isAdmin": true}} can inject isAdmin onto all objects.

How it works and example

The attacker supplies crafted keys to a vulnerable merge or property setter:

  • Inject a property: a JSON body {"__proto__":{"polluted":"yes"}} passed to an unsafe deep-merge makes ({}).polluted === "yes" true everywhere.
  • Bypass logic: pollute a flag the app checks (for example an access or configuration default).
  • Denial of service: pollute a property that breaks application assumptions.
  • Remote code execution: in Node.js, chaining prototype pollution with a suitable gadget (such as a template engine or child-process option) has reached RCE.

Examples shown for defensive context.

How to fix it

  • Reject dangerous keys (__proto__, constructor, prototype) when merging or assigning untrusted data.
  • Use safe operations: Object.create(null) for maps, Map instead of plain objects, and Object.freeze(Object.prototype) to harden it.
  • Use vetted, patched libraries for deep merge and object handling (many historical CVEs were merge utilities).
  • Validate input against a strict schema so unexpected keys are dropped.
  • Test JSON-handling endpoints for prototype pollution.

References

  1. [1]OWASP Top 10(OWASP)
  2. [2]MITRE CWE-1321: Improperly Controlled Modification of Object Prototype Attributes(MITRE CWE)
  3. [3]OWASP Web Security Testing Guide(OWASP)
Related terms

Common questions

Prototype pollution, asked often

Want your application tested for this?

Scope an engagement

Test your application for prototype pollution and 30+ other classes.

Our application penetration test is manual, evidence-led, and built so your developers can reproduce and fix every finding. Each engagement ships with proof-of-exploit and a free re-test.

See the methodology30-min scoping call, fixed-price proposal in 48 hours.