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·435 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•CVE-2026-64849
9.3

CVE-2026-64849: Server-Side Request Forgery (SSRF) in MLflow Webhooks via DNS Rebinding

CVE-2026-64849 is a critical Server-Side Request Forgery (SSRF) vulnerability affecting MLflow tracking servers prior to version 3.15.0. It allows unauthenticated remote attackers to bypass outbound request destination filters using DNS rebinding or HTTP redirects. This exposure risks compromising sensitive cloud infrastructure metadata and internal microservices.

Alon Barad
Alon Barad
2 views•5 min read
•about 2 hours ago•CVE-2026-69146
6.5

CVE-2026-69146: Missing Authorization Bypass in MLflow Basic Authentication Middleware

This technical report details a missing authorization vulnerability (CVE-2026-69146 / GHSA-3p64-6gvh-82v5) affecting the MLflow platform from version 3.13.0 to 3.15.0. When MLflow is configured with the built-in basic-auth plugin, authenticated users can bypass run-level UPDATE authorization checks, enabling unauthorized dataset and model lineage metadata injection.

Alon Barad
Alon Barad
1 views•7 min read
•about 3 hours ago•CVE-2026-69148
7.1

CVE-2026-69148: Broken Object Level Authorization (BOLA) in MLflow Model Registry

MLflow prior to version 3.15.0 fails to perform proper authorization checks when registering model versions, allowing authenticated users with access to a registered model to link and access artifacts from runs and models belonging to other users without authorization.

Amit Schendel
Amit Schendel
4 views•7 min read
•about 4 hours ago•CVE-2026-59893
7.5

CVE-2026-59893: Regular Expression Denial of Service in sqlparse Lexer

A high-severity Regular Expression Denial of Service (ReDoS) vulnerability in the sqlparse Python library prior to version 0.6.0 allows unauthenticated remote attackers to trigger CPU exhaustion and application denial of service via crafted SQL inputs containing unmatched dollar-quoted literals or unclosed multiline comments.

Alon Barad
Alon Barad
4 views•6 min read
•about 5 hours ago•GHSA-FHGH-WQ4Q-R37X
7.8

GHSA-FHGH-WQ4Q-R37X: Remote Code Execution via Sigstore Signature Verification Bypass in uniget CLI

A high-severity logic inversion flaw in the uniget CLI completely bypasses Sigstore cryptographic signature verification on metadata files by default. If an attacker can poison the package metadata cache or repository, they can execute arbitrary OS commands under the privileges of the active user.

Alon Barad
Alon Barad
5 views•5 min read
•about 6 hours ago•CVE-2026-59903
6.5

CVE-2026-59903: Cache Poisoning and Information Disclosure via CorsHandler Vary Header Overwrite

A technical analysis of CVE-2026-59903 in Netty's HTTP CORS handler, where the CorsHandler overwrites existing application Vary headers with Origin, leading to unauthorized caching of sensitive information.

Alon Barad
Alon Barad
5 views•5 min read