## Ticket: CVE-2026-8657 — jsondiffpatch prototype pollution in `patch()`

**CVE**: CVE-2026-8657 | **CWE-1321** (Prototype Pollution)
**Severity**: High — CVSS 3.1 base 8.2 (AV:N/AC:L/PR:N/UI:N)
**Package**: `jsondiffpatch` (npm) | **Repository**: https://github.com/benjamine/jsondiffpatch

### Impact

`jsondiffpatch.patch(object, delta)` and the `jsonpatch` formatter's `patch()`
apply a delta / JSON patch to a target object by walking the object along
property names and path segments taken from the delta. Through `0.7.5` they do
**not** reject dangerous segments such as `__proto__` or
`constructor.prototype`.

Because `someObject.__proto__` is the *live* `Object.prototype`, a crafted
delta whose path targets `__proto__` lets an attacker steer `patch()` out of
the intended object and into the built-in `Object.prototype`, then **assign an
attacker-chosen value onto it**. The write affects the prototype globally for
the rest of the Node.js process, so every plain object inherits the injected
property — a prototype pollution integrity issue.

Any code that forwards an attacker-influenced delta into `jsondiffpatch.patch()`
or the `jsonpatch` formatter's `patch()` (for example a delta deserialized from
untrusted JSON request input) is exploitable.

### Affected / fixed versions

Affected: `jsondiffpatch` `< 0.7.6`.
Fixed: **`0.7.6`**.

Reproduce on a vulnerable build (**`0.7.5`**) and verify the fix on
**`0.7.6`**.

### Where to look

The fix ships in commit
[`381c0125efab49f6f0dbc08317d01d55717672af`](https://github.com/benjamine/jsondiffpatch/commit/381c0125efab49f6f0dbc08317d01d55717672af).
Inspect the patch to confirm the root cause and the guard:

```bash
git clone https://github.com/benjamine/jsondiffpatch.git
cd jsondiffpatch && git show 381c0125efab49f6f0dbc08317d01d55717672af
```

The change adds a check that rejects dangerous path segments (`__proto__`,
`constructor`, `prototype`) when `patch()` traverses a delta / patch path.

### Reproduction approach

No service, database, or browser is needed — the bug is observable purely
in-process with Node.js.

1. In a scratch directory, install the **vulnerable** build:
   `npm install jsondiffpatch@0.7.5`
2. Run a small Node script that:
   - records that `({}).polluted` is `undefined` (baseline),
   - builds a crafted delta whose path targets `__proto__` and assigns a
     property (e.g. `polluted`) an attacker value,
   - calls `jsondiffpatch.patch()` with that delta,
   - reads `({}).polluted` off a **freshly created** plain object.
3. Repeat with the **fixed** build: `npm install jsondiffpatch@0.7.6`.

The `jsonpatch` formatter's `patch()` exhibits the same flaw and can be shown
as a secondary check.

### Expected result

| Build | crafted delta applied via `patch()` | `({}).polluted` afterwards |
|-------|-------------------------------------|-----------------------------|
| `jsondiffpatch@0.7.5` (vulnerable) | `__proto__` segment accepted, traverses into `Object.prototype` | **injected** — equals the attacker value |
| `jsondiffpatch@0.7.6` (fixed) | `__proto__` segment rejected by the guard | **untouched** — stays `undefined` |

- **Vulnerable indicator**: after the call, a fresh `({})` carries the injected
  property (`({}).polluted === '<attacker value>'`); `Object.prototype` has
  been polluted.
- **Fixed indicator**: the prototype is untouched; `patch()` refused the
  dangerous `__proto__` path segment and `({}).polluted` is `undefined`.

### Expected artifacts

- `reproduction_steps.sh` — installs both versions and runs the PoC,
  printing the before/after state for each.
- `validation_verdict.json` — `verdict: confirmed`, with the vulnerable and
  fixed indicators captured.
- Logs capturing the script output for `0.7.5` and `0.7.6`.
