Understanding Prototype Pollution

Table of contents
- In short :
- 1. JavaScript Prototypes & Inheritance → “Family Traditions”
- 2. Prototype Pollution → “Bad Tradition Injection”
- 3. Sources → “How the Stranger Enters”
- 4. Sinks → “Where the Damage Shows”
- 5. Gadgets → “How to Weaponize the Tradition”
- 6. Client-Side PP → “Messing With the Village Notice Board”
- 7. Server-Side PP → “Corrupting the Town’s Archive”
- 8. Browser APIs → “Town Services That Trust Outsiders”
- 9. Full Exploitation Chain Example (Story + Payload)
- TL;DR Mapping
- Common built-in prototypes and custom objects
Intro Hook:
Imagine a village with family traditions, town archives, and public notice boards. Now, imagine a stranger sneaks in and subtly changes these traditions. Suddenly, rules that everyone depends on are corrupted. This is exactly what prototype pollution does in JavaScript: a hidden attacker changes the default “rules” of every object in the system, creating security risks. Let’s break it down in plain analogies.
In short :
- Prototype = Family tradition
- Pollution = Malicious new tradition
- Source = Door stranger used
- Sink = Where tradition influences decisions
- Gadget = Specific practice that turns tradition into real power
- Client-side = Public notice board corrupted
- Server-side = Town archive corrupted
1. JavaScript Prototypes & Inheritance → “Family Traditions”
Imagine a family.
The grandparent teaches “every child in this family can sing.”
Every child automatically inherits that ability, even if they didn’t learn it directly.
That’s whatObject.prototype
is. Every object inherits from it.
2. Prototype Pollution → “Bad Tradition Injection”
Now imagine a malicious stranger sneaks in and says:
- “From now on, every child in this family lies by default.”
Suddenly, every child inherits that new “tradition.”
That’s pollution: attacker modifies the shared ancestor, and everyone down the chain is corrupted.
3. Sources → “How the Stranger Enters”
The intruder needs a door:
Front door = query params (
?__proto__=bad
).Back door = JSON body (
{"__proto__":{}}
).Window = URL fragment (
#attack
).
Each is just an entry point for injecting the bad tradition.
4. Sinks → “Where the Damage Shows”
Not every new tradition matters.
But if a polluted tradition affects something important (like honesty during voting), damage happens.
- Sink = point in the system where the poisoned value gets used.
5. Gadgets → “How to Weaponize the Tradition”
A gadget is a cultural practice that can be hijacked.
Example:
Tradition: “Before signing a contract, everyone must tell their family motto.”
Attacker polluted the motto → now every contract gets signed with the wrong words.
In code: iftoString()
is poisoned, anything that calls.toString()
will run attacker code.
6. Client-Side PP → “Messing With the Village Notice Board”
On the browser, pollution = attacker changes defaults used in rendering the UI.
Impact: fake content, redirecting links, or injecting script → like rewriting public notices.
7. Server-Side PP → “Corrupting the Town’s Archive”
On the backend/server, pollution = attacker alters global settings of the archive.
Impact: every new law, every decision is poisoned → bypass rules, maybe take full control.
8. Browser APIs → “Town Services That Trust Outsiders”
Think of postman delivering letters (browser APIs).
If they don’t check envelopes properly, strangers can slip in poisoned “family rules” and the town accepts them.
9. Full Exploitation Chain Example (Story + Payload)
Story Analogy:
Stranger sneaks into a town meeting (source).
He convinces the mayor’s secretary that the family motto is now “Give me the treasury key” (pollution).
Later, when the mayor signs documents (sink), he must use the motto.
Because it’s polluted, the treasury key gets handed over (gadget/exploit).
Technical Reality:
Source – Attacker injects:
https://target.com/?__proto__[isAdmin]=true
Pollution –
Object.prototype.isAdmin = true
Sink – Some code checks:
if (user.isAdmin) { giveAccess(); }
Gadget – Because every user now “inherits”
isAdmin=true
, attacker bypasses auth.
Result: attacker becomes admin without valid credentials.
TL;DR Mapping
Prototype = Family tradition
Pollution = Malicious new tradition
Source = Door stranger used
Sink = Where tradition influences decisions
Gadget = Specific practice that turns tradition into real power
Client-side = Public notice board corrupted
Server-side = Town archive corrupted
A cheat sheet is below for prototype pollution concepts to get quick overview and to revise quickly
JS Term / Concept | Analogy (Non-Tech World) | What Happens / Why It Matters | Quick Example |
Object.prototype | Family traditions / rules passed down from grandparents | Every object (“child”) automatically inherits these traits | toString() exists on all objects |
Prototype Pollution | A malicious new tradition injected into the family | Every “child” now follows the attacker’s rule | All objects now have isAdmin = true |
Source | Door/window where the stranger enters | Where the attacker injects their malicious rule | ?__proto__[isAdmin]=true in URL |
Sink | Where the new tradition actually affects decisions | Pollution only matters if it reaches a critical point | if(user.isAdmin) { giveAccess() } |
Gadget | A specific cultural practice that can be hijacked for power | Turns the polluted rule into a real exploit | .toString() called on an object runs attacker code |
Client-side PP | Public notice board / village bulletin | Affects what everyone in the village sees / interacts with | UI renders polluted values → fake content |
Server-side PP | Town archive / government records | Corrupts rules globally → bypasses permissions / controls | Node.js merges user input into global settings |
Browser API | Town services (postmen, messengers) that blindly trust outsiders | Attacker can slip in pollution via legit channels | URLSearchParams , postMessage handling unvalidated input |
Query Params | Front door | User-controlled input in URLs | ?theme=dark |
Hash Fragment | Window / secret note passed to town notice board | Another way to feed user input into app state | #/profile?id=123 |
Merge Function (Object.assign , _.merge ) | Town clerk combining family rules with user instructions | Where pollution actually changes the default behavior | Object.assign(defaults, userInput) |
Payload | The specific “bad tradition” / instruction attacker injects | The concrete data that corrupts defaults | {"__proto__":{"polluted":"yes"}} |
Common built-in prototypes and custom objects
1. Object.prototype → “Grandparent’s Rules”
Root for most objects. Pollution here affects almost everything.
Analogy: The grandparent sets family rules everyone inherits.
Example: If the grandparent suddenly declares “all kids must wear red hats,” every child and even distant relatives follow it.
2. Array.prototype → “School Club Rules”
Pollution affects arrays (
[].push
,[].map
) and objects inheriting from arrays.Analogy: A school club has its own rules in addition to family rules.
Example: “All club members must raise their hand before speaking.” If this rule is changed by a mischief-maker, every member of the club follows it, but non-members aren’t affected.
3. Function.prototype → “Coach’s Guidelines”
Pollution affects functions (
.call
,.apply
) and objects inheriting from functions.Analogy: Every coach has a set of instructions for exercises.
Example: If a bad coach says “run clockwise instead of counterclockwise,” all athletes following that coach change their routine.
4. Custom Prototypes → “Mentors for Special Teams”
Any object can have its own prototype chain. Polluting a parent prototype here affects only children inheriting from it.
Analogy: Special mentorship groups have their own rules on top of family and school rules.
Example: “Mentorship rule: always submit homework on Monday.” Changing this affects only students in this group, not the whole school.
5. Pollution Flow → “How the Bad Rule Spreads”
Adding a property to any prototype → children inherit it → sinks/gadgets trigger impact.
Analogy: A single “bad rule” injected at the grandparent, coach, or mentor level spreads down the chain: children, students, or athletes follow it, and when someone acts on that rule (sink/gadget), it causes real-world effects.
Example: The red-hat rule gets enforced at a parade (sink), causing chaos because everyone follows it blindly.
Subscribe to my newsletter
Read articles from Sangharsha directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Sangharsha
Sangharsha
I write to revisit topics I’m interested in or when I’m bored and curious.