highCWE-1321A03:2021

Prototype Pollution

Merging user-controlled objects without filtering lets attackers modify Object.prototype and affect every object in the application.

How It Works

JavaScript objects inherit from Object.prototype. If you deep-merge a payload like { '__proto__': { 'admin': true } }, you've just set admin=true on every plain object in the process. This can bypass authorization checks, crash the app, or enable remote code execution in some frameworks.

Vulnerable Code
// BAD: deep merge without filtering __proto__
function merge(target, source) {
  for (const key in source) {
    if (typeof source[key] === 'object') merge(target[key], source[key]);
    else target[key] = source[key]; // pollutes if key is '__proto__'
  }
}
Secure Code
// GOOD: skip dangerous keys during merge
function merge(target, source) {
  for (const key in source) {
    if (key === '__proto__' || key === 'constructor' || key === 'prototype') continue;
    if (typeof source[key] === 'object') merge(target[key] ?? {}, source[key]);
    else target[key] = source[key];
  }
}

Real-World Example

CVE-2019-10744 affected lodash's merge() and defaultsDeep() functions, used by millions of projects. An attacker could send a crafted JSON body to any API using lodash merge and modify global application state.

How to Prevent It

  • Filter '__proto__', 'constructor', and 'prototype' keys before any deep merge
  • Use Object.create(null) to create objects with no prototype when merging untrusted data
  • Prefer structured cloning (structuredClone()) or JSON.parse(JSON.stringify()) over custom deep merge
  • Keep lodash and similar libraries updated — prototype pollution patches are frequent

Affected Technologies

Node.jsjavascript

Data Hogo detects this vulnerability automatically.

Scan Your Repo Free

Related Vulnerabilities