Skip to content

CVE-2026-8657: Verified Repro With Script Download

CVE-2026-8657: jsondiffpatch: prototype pollution via crafted delta in patch

CVE-2026-8657 is verified against jsondiffpatch · npm. Affected versions: < 0.7.6. Fixed in 0.7.6. Vulnerability class: Prototype Pollution. This high reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00135.

REPRO-2026-00135 jsondiffpatch · npm Prototype Pollution May 22, 2026 CVE entry ↗ .txt
Severity
HIGH
CVSS
8.2
Reproduced in
23m 26s
Tool calls
144
Spend
$1.31
01 · Overview

What Is CVE-2026-8657?

CVE-2026-8657 is a high-severity prototype pollution vulnerability (CWE-1321) in the jsondiffpatch npm package's patch(), unpatch(), reverse(), and JSON Patch formatter patch() functions. Pruva reproduced it (reproduction REPRO-2026-00135).

02 · Severity & CVSS

CVE-2026-8657 Severity & CVSS Score

CVE-2026-8657 is rated high severity, with a CVSS base score of 8.2 out of 10.

HIGH threat level
8.2 / 10 CVSS base
03 · Affected Versions

Affected jsondiffpatch Versions

jsondiffpatch · npm versions < 0.7.6 are affected.

How to Reproduce CVE-2026-8657

$ pruva-verify REPRO-2026-00135
or curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00135/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-2026-8657

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

How the agent worked 531 events · 144 tool calls · 23 min
23 minDuration
144Tool calls
127Reasoning steps
531Events
1Dead-ends
Agent activity over 23 min
Support
17
Repro
167
Variant
342
0:0023:26

Root Cause and Exploit Chain for CVE-2026-8657

Summary

jsondiffpatch versions before 0.7.6 are vulnerable to prototype pollution in patch(), unpatch(), reverse(), and the JSON Patch formatter's patch(). When applying a delta or JSON Patch document, the library traverses the target object using attacker-controlled property names and path segments without rejecting dangerous keys such as __proto__ or constructor.prototype. This allows an attacker to write arbitrary values into Object.prototype, affecting every plain object in the running Node.js process.

Impact

Any code that forwards an attacker-influenced delta or JSON Patch into jsondiffpatch.patch() or the jsonpatch formatter's patch() (for example, a delta deserialized from untrusted JSON request input) can be exploited to pollute the global prototype.

Root Cause

The root cause lies in two places in the vulnerable code (v0.7.5):

  1. packages/jsondiffpatch/src/filters/nested.ts: The patchFilter, collectChildrenPatchFilter, reverseFilter, and collectChildrenReverseFilter functions iterate over delta keys and patch children using property names taken directly from the delta. They do not reject __proto__ or guard against inherited properties like constructor.prototype. For example:

    for (const name in objectDelta) {
      const child = new PatchContext(
        (context.left as Record<string, unknown>)[name],
        objectDelta[name],
      );
      context.push(child, name);
    }
    

    When name is __proto__, context.left.__proto__ resolves to Object.prototype, causing writes to the global prototype.

  2. packages/jsondiffpatch/src/formatters/jsonpatch-apply.ts: The parsePathFromRFC6902() function splits JSON Pointer paths into segments without validating them. When a segment is __proto__, the subsequent add() or replace() operations write into Object.prototype.

The fix commit 381c0125efab49f6f0dbc08317d01d55717672af addresses this by:

  • Introducing an UNSAFE_KEYS set containing __proto__ (and constructor / prototype for the JSON Patch formatter).
  • Skipping delta keys that match unsafe names in all patch/unpatch/reverse filters.
  • Using Object.prototype.hasOwnProperty.call(left, name) to prevent traversal into inherited properties (mitigating constructor.prototype attacks).
  • Adding validation in parsePathFromRFC6902() that throws for unsafe path segments in JSON Patch operations.

Reproduction Steps

The reproduction script is repro/reproduction_steps.sh. It performs the following steps:

  1. Installs jsondiffpatch@0.7.5 (vulnerable) and jsondiffpatch@0.7.6 (fixed) in separate scratch directories.
  2. Runs a shared ES module test against each installation.
  3. The test attempts five prototype-pollution vectors:
    • jsondiffpatch.patch() with a delta containing __proto__
    • jsondiffpatch.patch() with a delta containing constructor.prototype
    • jsonpatchFormatter.patch() with an add operation targeting /__proto__/pp3
    • jsonpatchFormatter.patch() with a replace operation targeting /__proto__/pp4
    • jsondiffpatch.unpatch() with a delta containing constructor.prototype
  4. After each attempt, the test checks whether a plain {} inherits the injected property. If so, it logs the polluted property names.
  5. The script verifies:
    • Vulnerable version (0.7.5): prints VULNERABLE and exits 0
    • Fixed version (0.7.6): prints NOT_VULNERABLE and exits 1

Evidence

  • Vulnerable test log: logs/test_vuln.log

    === Testing vulnerable version 0.7.5 ===
    POLLUTED patch_proto: pp1
    POLLUTED patch_constructor: pp2
    POLLUTED jsonpatch_add: pp3
    POLLUTED jsonpatch_replace: pp4
    VULNERABLE
    
  • Fixed test log: logs/test_fixed.log

    === Testing fixed version 0.7.6 ===
    NOT_VULNERABLE
    
  • Runtime manifest: repro/runtime_manifest.json (written on successful reproduction)

  • Environment: Node.js v22.22.2, jsondiffpatch@0.7.5 and @0.7.6 installed via npm.

Recommendations / Next Steps

  1. Upgrade immediately to jsondiffpatch >= 0.7.6.
  2. Input validation: If you must accept deltas or JSON Patches from untrusted sources, validate them independently before passing them to jsondiffpatch.patch() or the JSON Patch formatter.
  3. Regression testing: Include the provided test cases in your CI pipeline to guard against future regressions. The upstream project has added 7 regression tests covering all attack vectors.
  4. Runtime hardening: Consider using Object.freeze(Object.prototype) or libraries like safe-object-assign to make prototype pollution harder to exploit in production environments.

Additional Notes

  • Idempotency: The reproduction script was run twice consecutively with identical results.
  • Edge cases: The fix intentionally preserves legitimate use cases (e.g., objects that have their own constructor property). The upstream test suite includes a dedicated test (should still correctly patch objects with a legitimate 'constructor' own property) confirming this.
  • Scope: While the reproduction focuses on patch() and jsonpatchFormatter.patch(), the fix also protects unpatch() and reverse() because they share the same traversal logic.

CVE-2026-8657 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:07
0:00
session startedaccounts/fireworks/models/kimi-k2p6 · cve-2026-8657 · cve-2026
0:07
0:09
0:10
web search
0:14
0:32
0:49
0:49
extract_facts
no facts extracted
0:50
0:50
0:50
supportrepro
0:52
0:52
0:52
0:59
0:59
0:59
0:59
1:02
1:02
$cd /root/.pruva/runs/cve-2026-8657_20260522-090918 && git clone --depth 100 https://github.com/benjamine/jsondiffpatch.git external/jsondiffpatch
0.6s
Cloning into 'external/jsondiffpatch'...
1:03
1:03
$cd /root/.pruva/runs/cve-2026-8657_20260522-090918/external/jsondiffpatch && git show 381c0125efab49f6f0dbc08317d01d55717672af
{"cwd":"/root/.pruva/runs/cve-2026-8657_20260522-090918","duration_ms":5,"exit_code":0,"stderr":"","stdout":"commit 381c0125efab49f6f0dbc08317d01d55717672af\nAuthor: Benjamín Eidelman <beneidel+gh@gmail.com>\nDate:   Thu May 14 19:54:04 2026 -0300\n\n    fix: prevent prototype pollution in patch, unpatch, reverse, and JSON Patch apply\n    \n    Block __proto__ keys in nested delta patch/reverse filters; guard against\n    traversal into non-own properties (constructor.prototype attack); silently\n    skip JSON Patch add ops targeting unsafe path segments. Adds 7 regression\n    tests covering all attack vectors (jsondiffpatch.patch, unpatch, reverse,\n    and jsonpatch formatter).\n\ndiff --git a/packages/jsondiffpatch/src/filters/nested.ts b/packages/jsondiffpatch/src/filters/nested.ts\nindex a4e06fb..75b06aa 100644\n--- a/packages/jsondiffpatch/src/filters/nested.ts\n+++ b/packages/jsondiffpatch/src/filters/nested.ts\n@@ -3,6 +3,13 @@ import PatchContext from \"../contexts/patch.js\";\n import ReverseContext from \"../contexts/reverse.js\";\n import type { ArrayDelta, Delta, Filter, ObjectDelta } from \"../types.js\";\n \n+// '__proto__' must never be used as a property key — it… [truncated]
1:07

Artifacts and Evidence for CVE-2026-8657

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

No artifacts available

08 · How to Fix

How to Fix CVE-2026-8657

Upgrade jsondiffpatch · npm to 0.7.6 or later.

Coming soon

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

10 · FAQ

FAQ: CVE-2026-8657

How does the CVE-2026-8657 prototype-pollution attack work?

An attacker crafts a delta (or JSON Patch document) whose path targets __proto__; since someObject.__proto__ is the live Object.prototype, passing that delta into jsondiffpatch.patch() (or the JSON Patch formatter's patch()) lets the traversal step outside the intended target object and assign an attacker-chosen value directly onto Object.prototype, polluting every plain object for the rest of the Node.js process.

Which jsondiffpatch versions are affected by CVE-2026-8657, and where is it fixed?

Affects jsondiffpatch < 0.7.6; fixed in 0.7.6.

How severe is CVE-2026-8657?

High severity, CVSS 3.1 base score 8.2.

How can I reproduce CVE-2026-8657?

Download the verified script and run it in an isolated environment against jsondiffpatch < 0.7.6; it feeds a crafted delta targeting __proto__ into patch() (or the JSON Patch formatter) and confirms Object.prototype is polluted with the attacker-chosen value in the running Node.js process.
11 · References

References for CVE-2026-8657

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