← Home ← Codex ← DEBT
Browse by Category
+ added · updated 7d
← Back to glossary

Prototype Pollution

Security CWE-1321 OWASP A3:2021 CVSS 8.1 ES5 Advanced
debt(d5/e3/b3/t7)
d5 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'specialist tool catches' (d5), semgrep/snyk rules flag recursive merges and unsafe key assignment, but plain code review often misses it since the vulnerable pattern (_.merge) looks innocuous.

e3 Effort Remediation debt — work required to fix once spotted

Closest to 'simple parameterised fix' (e3), quick_fix says swap recursive merge for safe alternatives, add __proto__/constructor key validation, or use Object.create(null) — a targeted pattern replacement rather than architectural change.

b3 Burden Structural debt — long-term weight of choosing wrong

Closest to 'localised tax' (b3), applies to object-handling code paths that accept user input; doesn't shape the whole system but recurs wherever deep merge / dynamic key assignment is used.

t7 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'serious trap' (t7), misconception explicitly notes devs assume it's browser-only and that __proto__ assignment is harmless, but it silently mutates global Object.prototype affecting every object in the process — contradicts intuition about object scoping.

About DEBT scoring →

Also Known As

JS prototype pollution __proto__ attack object prototype injection

TL;DR

An attacker injects properties into JavaScript's Object.prototype, affecting all objects in the application.

Explanation

Prototype pollution is a JavaScript-specific vulnerability where user-controlled keys like __proto__ or constructor.prototype are used to write properties onto Object.prototype. Because all JavaScript objects inherit from Object.prototype, injected properties propagate globally and can override application logic, bypass security checks, or escalate to remote code execution in server-side Node.js contexts. PHP is not affected, but PHP applications serving JavaScript-heavy frontends should sanitise JSON inputs and use libraries with known mitigations.

How It's Exploited

POST /api/merge Content-Type: application/json
{"__proto__": {"isAdmin": true}}
# All subsequent {} objects have isAdmin: true → auth bypass

Common Misconception

Prototype pollution is only exploitable in the browser. Server-side JavaScript (Node.js) is equally vulnerable — polluting Object.prototype can affect all objects in the process, enabling DoS, property injection, and in some cases RCE via gadget chains.

Why It Matters

Polluting JavaScript's Object.prototype affects every object in the runtime — attackers can inject properties that alter application behaviour, bypass checks, or enable XSS.

Common Mistakes

  • Deep-merging objects using recursive assignment without checking for __proto__ or constructor keys.
  • Using user-supplied strings as keys in object assignment — an attacker sends __proto__[isAdmin]=true.
  • Not using Object.create(null) for dictionaries/maps that accept user-controlled keys.
  • Ignoring prototype pollution in server-side Node.js — it's not only a browser problem.

Code Examples

✗ Vulnerable
// JavaScript — merging user object pollutes Object.prototype
function merge(target, source) {
    for (let key in source) {
        target[key] = source[key]; // key could be '__proto__'
    }
}
merge({}, JSON.parse('{"__proto__":{"admin":true}}'));
console.log({}.admin); // true — every new object is now 'admin'
✓ Fixed
// Use Object.keys() — own keys only, no prototype chain
function safeMerge(target, source) {
    for (let key of Object.keys(source)) {
        if (['__proto__','constructor','prototype'].includes(key)) continue;
        target[key] = source[key];
    }
}

// Or use Object.create(null) — no prototype at all
const safe = Object.create(null);

// Or JSON round-trip for deep clone of untrusted data:
const clone = JSON.parse(JSON.stringify(untrusted));

// PHP note: not applicable — PHP objects don't share a mutable prototype

Added 15 Mar 2026
Edited 22 Mar 2026
Views 48
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 1 ping W 1 ping T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 1 ping T 2 pings F 0 pings S 2 pings S 1 ping M 2 pings T 0 pings W 1 ping T 1 ping F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 1 ping T 0 pings W
No pings yet today
PetalBot 1
Amazonbot 9 Scrapy 6 Google 5 Unknown AI 4 ChatGPT 4 Ahrefs 3 Perplexity 2 Claude 2 Bing 2 SEMrush 2 Meta AI 1 PetalBot 1
crawler 33 crawler_json 7 pre-tracking 1
DEV INTEL Tools & Severity
🟠 High ⚙ Fix effort: Medium
⚡ Quick Fix
Never merge user-supplied objects into application objects with recursive merge; use Object.create(null) for hash maps; validate that __proto__ and constructor keys are absent
📦 Applies To
javascript ES5 web cli
🔗 Prerequisites
🔍 Detection Hints
Recursive object merge with user input: _.merge(target, userInput) or deep assign without __proto__ filtering
Auto-detectable: ✓ Yes semgrep eslint snyk
⚠ Related Problems
🤖 AI Agent
Confidence: High False Positives: Medium ✗ Manual fix Fix: Medium Context: Function Tests: Update
CWE-915 CWE-1321


✓ schema.org compliant