Skip to content

CVE-2025-13465: Verified Repro With Script Download

CVE-2025-13465: lodash: prototype pollution in .unset/ .omit deletes global prototype methods

CVE-2025-13465 is verified against lodash · npm. Affected versions: >= 4.0.0, <= 4.17.22. Fixed in 4.17.23. Vulnerability class: Prototype Pollution. This medium reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00134.

REPRO-2026-00134 lodash · npm Prototype Pollution May 22, 2026 CVE entry ↗ .txt
Severity
MEDIUM
CVSS
5.3
Reproduced in
29m 27s
Tool calls
149
Spend
$1.27
01 · Overview

What Is CVE-2025-13465?

CVE-2025-13465 (GHSA-xxjr-mmjv-4gpg) is a medium-severity prototype-pollution-by-deletion vulnerability (CWE-1321) in lodash's _.unset and _.omit functions. Pruva reproduced it (reproduction REPRO-2026-00134).

02 · Severity & CVSS

CVE-2025-13465 Severity & CVSS Score

CVE-2025-13465 is rated medium severity, with a CVSS base score of 5.3 out of 10.

MEDIUM threat level
5.3 / 10 CVSS base
Weakness CWE-1321 — Improperly Controlled Modification of Object-Attribute Properties and Methods

Medium — meaningful risk under specific conditions. Schedule a fix in the normal cycle.

03 · Affected Versions

Affected lodash Versions

lodash · npm versions >= 4.0.0, <= 4.17.22 are affected.

How to Reproduce CVE-2025-13465

$ pruva-verify REPRO-2026-00134
or curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00134/artifacts/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh
Run in a VM or disposable container. This exploits a real vulnerability.
06 · Proof of Reproduction

Proof of Reproduction for CVE-2025-13465

Reproduced by Pruva's autonomous agents — 149 tool calls over 29 min. Full root-cause analysis and the complete transcript are below.

How the agent worked 567 events · 149 tool calls · 29 min
29 minDuration
149Tool calls
138Reasoning steps
567Events
Agent activity over 29 min
Support
16
Repro
156
Variant
391
0:0029:27

Root Cause and Exploit Chain for CVE-2025-13465

Summary

CVE-2025-13465 is a prototype-pollution-by-deletion vulnerability in lodash's _.unset and _.omit functions. When a user-controlled string path containing __proto__ is passed to these functions, lodash traverses into Object.prototype and deletes the targeted property globally. This affects every object in the Node.js process, causing denial-of-service or integrity degradation. The issue is fixed in lodash 4.17.23 by adding a guard in baseUnset that rejects dangerous string path segments (__proto__, constructor.prototype).

Impact

  • Package: lodash (npm)
  • Affected versions: 4.0.0 through 4.17.22 (inclusive)
  • Fixed version: 4.17.23
  • Risk level: Moderate (CVSS 3.1 base 5.3)
  • Consequences: Any application that forwards attacker-controlled key names into _.unset or _.omit (e.g., from JSON request input) can have built-in prototype methods deleted globally, leading to denial-of-service or unexpected behavior across the entire process.

Root Cause

The root cause lies in the baseUnset function (shared by _.unset and _.omit). Before the fix, baseUnset parsed the path string into segments and walked each segment on the target object without validating whether a segment was a dangerous prototype accessor such as __proto__, constructor, or prototype.

Because someObject.__proto__ returns the live Object.prototype, a crafted path like __proto__.toString causes the function to traverse out of the intended object and into the global prototype, then delete the specified key from it.

Fix commit: edadd452146f7e4bad4ea684e955708931d84d81

The fix adds a loop in baseUnset that iterates over path segments and:

  1. Skips non-string keys.
  2. Blocks __proto__ anywhere in the path if it is not an own property of the current object.
  3. Blocks constructor.prototype chains, with a narrow exception for primitive roots (e.g., _.unset(0, 'constructor.prototype.a')).

Reproduction Steps

The reproduction script is repro/reproduction_steps.sh.

What the script does:

  1. Installs the last published vulnerable version (lodash@4.17.21) in a temporary directory.
  2. Runs a Node.js harness (test_app.js) that simulates an application receiving untrusted user input (__proto__.toString) and passing it to _.unset({}, untrustedInput).
  3. Captures the typeof Object.prototype.toString before and after the call.
  4. Repeats steps 1–3 with the fixed version (lodash@4.17.23).
  5. Also runs a secondary check with _.omit({}, '__proto__.toString') on the vulnerable build.
  6. Writes a JSON runtime manifest (repro/runtime_manifest.json) with versions, exit codes, log paths, and explicit confirmation markers.

Expected evidence of reproduction:

  • Vulnerable build: typeof Object.prototype.toString changes from "function" to "undefined", and the harness exits with code 2 emitting VULN_CONFIRMED.
  • Fixed build: typeof Object.prototype.toString stays "function", and the harness exits with code 0 emitting FIX_CONFIRMED.

Evidence

Log files captured by the script:

  • logs/vuln_unset.log — Vulnerable _.unset test output.
  • logs/fixed_unset.log — Fixed _.unset test output.
  • logs/vuln_omit.log — Vulnerable _.omit test output.
  • repro/runtime_manifest.json — Structured manifest linking all evidence.

Key excerpts from logs/vuln_unset.log:

lodash version: 4.17.21
untrusted path input: __proto__.toString
typeof Object.prototype.toString BEFORE: function
typeof Object.prototype.toString AFTER: undefined
VULN_CONFIRMED: prototype pollution via _.unset in lodash 4.17.21

Key excerpts from logs/fixed_unset.log:

lodash version: 4.17.23
untrusted path input: __proto__.toString
typeof Object.prototype.toString BEFORE: function
typeof Object.prototype.toString AFTER: function
FIX_CONFIRMED: prototype intact in lodash 4.17.23

Key excerpts from logs/vuln_omit.log:

lodash version: 4.17.21
typeof Object.prototype.toString BEFORE: function
typeof Object.prototype.toString AFTER: undefined
VULN_CONFIRMED_OMIT: _.omit pollutes prototype

Environment:

  • Node.js v22.22.2
  • npm 10.9.7

Recommendations / Next Steps

  • Upgrade guidance: Projects using lodash 4.17.21 or earlier should upgrade to 4.17.23 or later immediately. Note that a separate array-path bypass (CVE-2026-2950) exists and is fixed in 4.18.0, so upgrading to 4.18.0+ is recommended for full protection.
  • Code review: Audit all calls to _.unset and _.omit that accept user-controlled path strings. If upgrading is not immediately possible, sanitize path segments to reject __proto__, constructor, and prototype before passing them to lodash.
  • Testing: Add regression tests that exercise __proto__ and constructor.prototype paths against _.unset and _.omit to prevent future regressions.

Additional Notes

  • Idempotency: repro/reproduction_steps.sh has been executed twice consecutively with identical results (exit 0, same log outputs).
  • Version caveat: The ticket specifies 4.17.22 as the last vulnerable version, but this version was never published to npm or tagged in Git. The reproduction uses 4.17.21 as the vulnerable baseline because it is the last published version that exhibits the flaw. The fix commit edadd452 is included in 4.17.23, which is published and confirmed to block the attack.
  • Edge cases: The fix specifically targets string path segments. A later bypass using array paths (['__proto__', 'toString']) was assigned a separate CVE (CVE-2026-2950) and is out of scope for this ticket.

CVE-2025-13465 Reproduction Transcript

The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired.

Full session Replay every step — scrub the timeline or play it back.

Event 1/40
0:001:13
0:00
session startedaccounts/fireworks/models/kimi-k2p6 · cve-2025-13465 · cve-2025
0:07
0:09
0:11
0:13
web search
0:34
0:34
extract_facts
no facts extracted
0:36
0:36
0:36
supportrepro
0:41
0:44
0:44
0:44
0:53
0:53
0:55
$git clone --depth=200 https://github.com/lodash/lodash.git /tmp/lodash_repro 2>&1 | tail -5
1.3s
Cloning into '/tmp/lodash_repro'...
1:06
1:06
$cd /tmp/lodash_repro && git show edadd452146f7e4bad4ea684e955708931d84d81 --stat
commit edadd452146f7e4bad4ea684e955708931d84d81
Author: Ulises Gascón <ulisesgascongonzalez@gmail.com>
Date:   Fri Dec 5 19:26:49 2025 +0100

    Prevent prototype pollution on baseUnset function
    
    * test: add tests to prevent security regressions
    
1:13
1:13
$cd /tmp/lodash_repro && git show edadd452146f7e4bad4ea684e955708931d84d81 -- lodash.js | head -100
{"cwd":"/root/.pruva/runs/cve-2025-13465_20260522-075758","duration_ms":12,"exit_code":0,"stderr":"","stdout":"commit edadd452146f7e4bad4ea684e955708931d84d81\nAuthor: Ulises Gascón <ulisesgascongonzalez@gmail.com>\nDate:   Fri Dec 5 19:26:49 2025 +0100\n\n    Prevent prototype pollution on baseUnset function\n    \n    * test: add tests to prevent security regressions\n    \n    * sec: prevent prototype pollution on `baseUnset` function\n    \n    * chore: improve security patch\n    \n    - Expand both `_.omit` & `_.unset` security tests to loop over `__proto__`, `constructor`, `prototype`\n    - Only block `__proto__` if not an own property\n\ndiff --git a/lodash.js b/lodash.js\nindex 1d232ac..900cedf 100644\n--- a/lodash.js\n+++ b/lodash.js\n@@ -4370,8 +4370,47 @@\n      */\n     function baseUnset(object, path) {\n       path = castPath(path, object);\n-      object = parent(object, path);\n-      return object == null || delete object[toKey(last(path))];\n+\n+      // Prevent prototype pollution, see: https://github.com/lodash/lodash/security/advisories/GHSA-xxjr-mmjv-4gpg\n+      var index = -1,\n+          length = path.length;\n+\n+      if (!length) {\n+        return tru… [truncated]

Artifacts and Evidence for CVE-2025-13465

Scripts, logs, diffs, and output captured during the reproduction.

No artifacts available

08 · How to Fix

How to Fix CVE-2025-13465

Upgrade lodash · npm to 4.17.23 or later.

Coming soon

Step-by-step mitigation and hardening guidance for CVE-2025-13465 — configuration checks, workarounds where no patch exists, and how to verify you're protected — is on the way.

10 · FAQ

FAQ: CVE-2025-13465

How does the CVE-2025-13465 prototype-pollution attack work?

An attacker supplies a path string containing __proto__ to _.unset(object, path) or _.omit(object, paths) — for example, a property path taken from JSON request input forwarded by the application. lodash traverses into Object.prototype via the __proto__ segment and deletes the targeted property globally, so every object of that type in the running Node.js process loses that method for the rest of the process's lifetime.

Which lodash versions are affected by CVE-2025-13465, and where is it fixed?

Versions >= 4.0.0 and <= 4.17.22 are affected. It is fixed in 4.17.23, which adds a guard in baseUnset that rejects dangerous string path segments like __proto__ and constructor.prototype.

How severe is CVE-2025-13465?

It is rated medium severity. It permits deleting built-in prototype methods globally (denial-of-service / integrity impact) but does not allow overwriting their behavior, so it cannot be used to inject new prototype properties or values.

How can I reproduce CVE-2025-13465?

Download the verified script from this page and run it in an isolated environment against lodash <= 4.17.22. It calls _.unset(object, '__proto__.toString') (or a similar path via _.omit) and shows Object.prototype.toString being deleted process-wide, then confirms 4.17.23 rejects the dangerous path segment.
11 · References

References for CVE-2025-13465

Authoritative sources for CVE-2025-13465 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.