The Prototype Poison: How Object.prototype Pollution Escalates Node.js Admins
CYBER THREAT & EXPLOIT CASE STUDIESReal-World Breach Forensics

How Sites Get Hacked

Forensic breakdowns of multi-million dollar data breaches, state-sponsored cyber warfare, AI-generated code vulnerabilities, and how security auditors bulletproof web systems.

HIGH THREATCWE-1321 / Prototype Pollution6 min read

The Prototype Poison: How Object.prototype Pollution Escalates Node.js Admins

How unvalidated recursive object merging utilities in JavaScript (lodash, deepmerge) allow attackers to inject properties into Object.prototype, silently granting every user administrative privileges.

Documented Real-World Damage: Remote Code Execution & Universal Admin Privilege Escalation
Interactive Exploit Sandbox

Simulate Attack Payload vs. Defense

Injected Payload (Attacker Input):
{"__proto__": {"isAdmin": true}}
Server Execution Result (Unpatched Application):EXPLOIT SUCCEEDED
Object.prototype Polluted!
Global prototype modified: Object.prototype.isAdmin = true.
All standard users escalated to administrator privileges.

Source Code Dissection & Fix

// Vulnerable recursive merge utility (Node.js):
function mergeObjects(target, source) {
  for (let key in source) {
    if (typeof source[key] === 'object' && source[key] !== null) {
      if (!target[key]) target[key] = {};
      mergeObjects(target[key], source[key]); // FATAL FLAW: Does not filter '__proto__'!
    } else {
      target[key] = source[key];
    }
  }
  return target;
}

The Quirks of JavaScript Prototypes

In JavaScript, inheritance is prototype-based. Almost every object in JavaScript inherits properties from the root `Object.prototype`.

If an application accepts arbitrary JSON payloads (e.g. user profile updates) and merges them into an existing object using an un-sanitized recursive function, an attacker can submit:

{
  "__proto__": {
    "isAdmin": true
  }
}

When the recursive function encounters `__proto__`, it modifies the global prototype itself.

Now, examine what happens when an ordinary, unprivileged customer logs in:

const user = await getUser(userId); // Normal customer
if (user.isAdmin) {
  // Evaluates to TRUE because isAdmin was injected into Object.prototype!
  renderAdminPanel();
}

Every single object in the Node.js process now possesses `isAdmin: true`, instantly escalating all visitors into administrative superusers! In extreme cases, prototype pollution can be chained to achieve Remote Code Execution (RCE) via Node.js `child_process` forks.

Finished reviewing this exploit case study?

Mark it as analyzed below, or click Next Report to auto-complete.

The Prototype Poison: How Object.prototype Pol… · DataArena