Prototype pollution is the JavaScript-native member of the injection family: a single attacker-controlled key name can change the behaviour of every object in a running program. It sits under A03:2021 - Injection in the OWASP Top 10 (CWE-1321).
Prerequisites. This lesson requires intermediate JavaScript familiarity — you need to know what objects ({key: value}), functions, and property access (obj.prop) look like, but you also need to have encountered the idea that objects can inherit properties from other objects. The web-technology-primer and the DOM XSS lesson together provide the minimum background. If you have never written JavaScript at all, complete the web-technology-primer's JavaScript section and spend time writing small JS scripts before starting here — the prototype chain is not a beginner concept and the lesson will not make sense without it.
Prototypal inheritance and the shared prototype
In JavaScript, every value can have properties — pieces of data attached to it by name, like user.name or config.timeout. Objects do not store every property themselves; each one links to a prototype object, and a property lookup that misses on the object walks up this chain until it finds the property or reaches the end. Almost every plain object ultimately inherits from one shared object: Object.prototype.
Analogy. Think of Object.prototype as a shared template card that every plain object in the program consults when it cannot find a property on itself. Writing a new entry onto that card makes it instantly visible to every object in the entire program — even objects created later. An attacker who can write to that card effectively edits the defaults for every object the application will ever create.That is exactly what happens in code. The dangerous part is that Object.prototype is shared by reference across the whole program. If an attacker can write a property onto it, that property instantly appears on every object that does not define its own — including objects the application creates and trusts later:
({}).polluted // undefined — normally
Object.prototype.polluted = "yes";
({}).polluted // "yes" — for every object nowThe three special key names that reach the shared prototype are __proto__, constructor, and prototype. For any plain object, obj.__proto__ and obj.constructor.prototype both point directly at Object.prototype — so writing to those keys means writing to the shared template card.
What you will do in this lesson
- Understand the shared prototype chain and the three keys that reach it.
- See how an unsafe recursive merge or property-set lets a
__proto__key in the input land onObject.prototype. - Distinguish client-side impact (a gadget leading to DOM XSS) from server-side impact (denial of service or RCE on Node).
- Locate a merge/JSON sink in your practice target and submit a working pollution payload.
Dedicated practice target required. NovaCart has no named prototype-pollution challenge, so use the PortSwigger Web Security Academy client-side and server-side prototype pollution labs, or a learner-controlled Node endpoint that deep-merges request JSON with a vulnerable merge / lodash.set.
When you are ready, send the Continue signal.