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

Prototype Pollution

security CWE-1321 OWASP A3:2021 CVSS 8.1 ES5 Advanced

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 24
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 1 ping F 0 pings S 1 ping S 0 pings M 0 pings T 1 ping W 3 pings T 1 ping F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 2 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 1 ping S
No pings yesterday
Amazonbot 9 Google 4 Unknown AI 3 Perplexity 2 ChatGPT 2 Ahrefs 1
crawler 16 crawler_json 4 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