CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2025-13465

Lodash: The Delete Button for the Universe (CVE-2025-13465)

Alon Barad
Alon Barad
Software Engineer

Jan 22, 2026·6 min read·498 visits

Executive Summary (TL;DR)

Lodash versions prior to 4.17.23 fail to sanitize paths in `_.unset` and `_.omit`. An attacker supplying a path like `__proto__.toString` can delete the `toString` method from `Object.prototype`, causing every object in the running application to lose that method. This leads to immediate application crashes (DoS) or security bypasses if logic relies on the existence of specific prototype methods. The fix involves strict validation of path segments to block `__proto__` and `constructor` access.

A prototype pollution vulnerability in the ubiquitous Lodash library allows attackers to delete critical properties from the global Object prototype. Unlike traditional pollution which injects malicious properties, this flaw uses `_.unset` and `_.omit` to destructively remove core language methods (like `toString` or `hasOwnProperty`) via path traversal, causing widespread Denial of Service or logic failures.

The Hook: The Swiss Army Knife with a Loose Blade

Lodash is the duct tape of the JavaScript ecosystem. It is the library you reach for when you realize JavaScript's standard library is missing the tools you actually need to do your job. It handles deep cloning, debouncing, and, crucially for this story, object manipulation. We trust it implicitly. We feed it our user input, our JSON blobs, and our complex state objects, expecting it to behave deterministically.

But here is the thing about utility belts: if you pull the wrong lever, you might just detach the floor you are standing on. CVE-2025-13465 isn't your standard 'injection' vulnerability where we sneak in a script tag. It is a Prototype Pollution flaw, but with a nihilistic twist.

Usually, hackers use prototype pollution to add properties—polluting the water supply, so to speak. This vulnerability allows us to delete properties. We aren't adding poison to the well; we are evaporating the water entirely. By targeting _.unset or _.omit, we can reach into the very soul of the JavaScript runtime—Object.prototype—and rip out methods that the application needs to breathe.

The Flaw: Logic Without Guardrails

The root of this vulnerability lies in how Lodash interprets 'paths'. When you tell Lodash to unset a property at a.b.c, it has to traverse the object graph to find c. It does this by splitting the string into segments or accepting an array of keys. The underlying engine for this is a function called baseUnset.

In vulnerable versions (pre-4.17.23), baseUnset was entirely too trusting. It would happily accept path segments like __proto__ or constructor and prototype. It treated them as valid keys to traverse. It didn't pause to ask, "Wait, should I really be climbing up the inheritance chain into the global scope?"

Because JavaScript objects are mutable by default, and because almost everything in JavaScript inherits from Object, traversing up to Object.prototype gives you write access to the blueprint of every object in the system. The flaw isn't just that it traverses; it's that after traversing, it executes the delete operator. While delete cannot remove non-configurable properties, many vital methods on the prototype chain are, in fact, configurable.

The Code: Examining the Fix

Let's look at the smoking gun. The fix was applied in baseUnset. The developers had to introduce a strict validation loop that runs before any traversal happens. They couldn't just check the final key; they had to check every step of the path.

Here is the logic introduced in commit edadd452146f7e4bad4ea684e955708931d84d81:

// The Fix Logic
while (++index < length) {
  var key = path[index];
  // ... checks for non-string keys ...
 
  // BLOCK 1: The Classic Proto
  if (key === '__proto__' && !hasOwnProperty.call(object, '__proto__')) {
    return false;
  }
 
  // BLOCK 2: The Constructor Bypass
  if (key === 'constructor' &&
      (index + 1) < length &&
      path[index + 1] === 'prototype') {
    // ... strict checks for primitive roots ...
    return false;
  }
}

Analysis:

  1. __proto__ Check: It explicitly looks for __proto__. If found, it ensures it's an "own" property (a real key on the object) rather than the inherited accessor. If it's the accessor, it bails.
  2. constructor.prototype Check: Attackers often bypass __proto__ filters by going through constructor.prototype. The patch explicitly looks for this sequence. If it sees constructor followed immediately by prototype, it hard-stops the operation.

This creates a whitelist of sorts—you can traverse anywhere except the forbidden zones of the prototype chain.

The Exploit: Deleting Reality

How do we weaponize this? We don't need RCE to ruin a sysadmin's day. A Denial of Service (DoS) via prototype deletion is often harder to debug than a crash. The application enters a "zombie state" where basic language features stop working.

Imagine a backend service that accepts a JSON payload to update user preferences. The code uses _.unset to remove restricted keys before saving.

The Setup:

const _ = require('lodash');
// The victim code
app.post('/update', (req, res) => {
   let userInput = req.body;
   // Developer tries to be safe by unsetting a specific field
   // But 'userInput.fieldToRemove' is controlled by the attacker
   _.unset(userInput.data, userInput.fieldToRemove);
});

The Attack: We send a payload where fieldToRemove is constructor.prototype.toString.

The Execution Flow:

  1. Lodash receives the path ['constructor', 'prototype', 'toString'].
  2. It traverses userInput.data.constructor, which is Object.
  3. It traverses .prototype, which is Object.prototype.
  4. It executes delete Object.prototype['toString'].

The Aftermath: The next time any part of that Node.js process tries to cast an object to a string (e.g., inside a logging library, an error handler, or a template engine), it will fail. [object Object] is gone. The application throws TypeError: ... is not a function and crashes. If you have an auto-restarter, it creates a crash loop until the malicious payload is flushed.

The Impact: Why This Matters

You might think, "So it crashes, big deal." But consider the subtlety. You can delete hasOwnProperty.

Many security mechanisms rely on obj.hasOwnProperty('isAdmin') to verify data integrity. If you delete hasOwnProperty from the prototype, the check might throw an error (DoS) or, depending on the implementation (e.g., try/catch blocks that swallow errors), it might fail open.

Furthermore, this vulnerability impacts _.omit as well. If an application uses _.omit(req.body, blocklist), an attacker can craft a request that pollutes the prototype during the omission process. Since Lodash is the backbone of thousands of high-traffic enterprise applications, the blast radius is massive. It turns a simple data processing utility into a remote kill switch.

The Fix: Remediation

The remediation is straightforward but urgent. You must upgrade Lodash.

Primary Fix: Update to version 4.17.23 or later.

npm install lodash@latest

Defense in Depth: Even with the patch, you should stop trusting objects. JavaScript provides tools to harden your environment against this class of bugs entirely:

  1. Object.freeze(Object.prototype): At the very start of your application, freeze the prototype. This prevents any library from modifying or deleting core methods.
  2. Use Map instead of Objects: For hash maps where keys are user-controlled, use the Map structure. It doesn't have a prototype chain to pollute.
  3. Input Validation: Never allow users to define paths for property access. Validate that keys are alphanumeric and do not contain special property names.

Official Patches

LodashCommit fixing baseUnset vulnerability

Fix Analysis (1)

Technical Appendix

CVSS Score
6.9/ 10
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:L/SC:H/SI:H/SA:H/E:P

Affected Systems

Node.js applications using lodash < 4.17.23Frontend React/Vue/Angular apps using lodash < 4.17.23Any JavaScript environment where `_.unset` or `_.omit` is passed user-controlled paths

Affected Versions Detail

Product
Affected Versions
Fixed Version
lodash
lodash
>= 4.0.0 < 4.17.234.17.23
AttributeDetail
CWE IDCWE-1321
CVSS v4.06.9 (Medium)
Attack VectorNetwork
ImpactDenial of Service / Logic Alteration
Affected Function_.unset, _.omit
Exploit StatusPoC Available

MITRE ATT&CK Mapping

T1499Endpoint Denial of Service
Impact
T1211Exploitation for Defense Evasion
Defense Evasion
CWE-1321
Prototype Pollution

Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')

Known Exploits & Detection

GitHub AdvisoryOfficial advisory containing PoC for .unset and .omit

Vulnerability Timeline

Fix commit pushed to GitHub
2025-12-05
Public Disclosure (GHSA & CVE)
2026-01-21

References & Sources

  • [1]GHSA Advisory
  • [2]NVD Detail
  • [3]Positive Technologies Research

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•about 1 hour ago•GHSA-C9XM-49CP-XCR9
6.3

GHSA-C9XM-49CP-XCR9: Server-Side Request Forgery in rmcp OAuth Client

A Server-Side Request Forgery (SSRF) vulnerability exists in the rmcp OAuth client, which is part of the Model Context Protocol (MCP) Rust SDK. The vulnerability arises from insecure processing of the resource_metadata parameter in WWW-Authenticate headers returned by a malicious or compromised MCP server. The client parses and fetches absolute URLs from this header without validation of scheme, origin, or network routing, allowing remote attackers to initiate HTTP GET requests to local network interfaces, RFC 1918 private subnets, or cloud metadata endpoints.

Alon Barad
Alon Barad
4 views•6 min read
•about 7 hours ago•CVE-2026-92945
4.2

CVE-2026-92945: Sandbox Escape and Module Allowlist Bypass via Path Prefix Matching in vm2

A module allowlist bypass vulnerability (CVE-2026-92945 / GHSA-7q3f-wx44-378m) was identified in the vm2 sandboxing library prior to version 3.11.7. This flaw permits unauthenticated or untrusted code running within the sandbox environment to bypass explicit module restrictions. When the transitive resolution option is disabled, the system fails to validate file system path boundaries, allowing prefix-sharing sibling directories to be resolved and loaded, thereby escaping intended sandbox restrictions.

Amit Schendel
Amit Schendel
6 views•6 min read
•about 7 hours ago•CVE-2026-92941
10.0

CVE-2026-92941: Sandbox Escape and Process-Wide TLS Trust Store Manipulation in vm2

CVE-2026-92941 is a critical sandbox-escape and trust-manipulation vulnerability in the vm2 library (versions 3.11.3 to 3.11.6). This security flaw allows untrusted code executing within a NodeVM sandbox environment to compromise the global TLS trust store of the host Node.js process. By leveraging a design flaw where the host's native 'tls.setDefaultCACertificates' can be executed via a proxy wrapper, combined with a bridge unwrapping bypass in the 'url' module, an attacker can modify the process-wide default root Certificate Authorities. Consequently, all subsequent outbound TLS/HTTPS clients running on the host thread are forced to trust attacker-signed certificates, facilitating transparent Man-in-the-Middle (MitM) attacks. The vulnerability was resolved in version 3.11.7 of vm2 by introducing built-in member-level sanitization before applying read-only proxy wrappers.

Amit Schendel
Amit Schendel
5 views•10 min read
•about 8 hours ago•CVE-2026-92944
9.8

CVE-2026-92944: Sandbox Escape in vm2 via Stale V8 PromiseThenLookupChain Protector

A critical engine-level reachability failure in Node.js 26 running V8 14.6 allows attackers to escape the vm2 sandbox environment. When consecutive prototype properties are modified using sequential assignments, a V8 optimization bug fails to invalidate the PromiseThenLookupChain protector. By calling Promise.prototype.finally, the attacker bypasses the vm2 wrappers, hijacks the promise reaction using a custom constructor, triggers a calibrated stack overflow to capture a host-realm RangeError, and executes arbitrary shell commands on the host.

Alon Barad
Alon Barad
7 views•8 min read
•about 9 hours ago•CVE-2026-92939
9.9

CVE-2026-92939: Critical Sandbox Escape via Host Crypto setEngine Native Code Execution in vm2

A critical sandbox escape vulnerability in the vm2 library allows sandboxed JavaScript code to bypass containment and execute arbitrary native code on the host process. This occurs when the host's builtin crypto module is exposed to the NodeVM environment. Although vm2 implements a read-only proxy layer to restrict direct modifications to host properties, it does not prevent invocation of host-level functions. By calling the crypto.setEngine API with a path to a malicious native library on disk, an attacker can trigger OpenSSL's dynamic module loader. The host's operating system loader immediately runs the dynamic library's initializers/constructors before verifying engine compatibility, leading to remote code execution in the context of the host process.

Amit Schendel
Amit Schendel
6 views•5 min read
•about 10 hours ago•CVE-2026-92938
9.9

CVE-2026-92938: Remote Code Execution in vm2 via node:sqlite DatabaseSync Sandbox Escape

CVE-2026-92938 is a critical sandbox escape vulnerability in the vm2 library (versions 3.11.3 through 3.11.6) that allows arbitrary native code execution on the host when the node:sqlite built-in module is loaded inside a sandboxed NodeVM environment.

Amit Schendel
Amit Schendel
8 views•8 min read