CVE-2026-59880 Overview
CVE-2026-59880 is a hash-flooding denial of service vulnerability in Immutable.js, a widely-used JavaScript library providing persistent immutable data structures. Versions prior to 4.3.9 and 5.1.8 store keys with identical 32-bit hashes in a HashCollisionNode bucket that is scanned linearly. Attackers who control keys inserted through Immutable.Map(obj), Immutable.fromJS(obj), state.merge(userObject), or mergeDeep can craft many colliding keys. The result is O(n²) CPU consumption during insertion and lookup, degrading application performance and enabling denial of service. The issue is tracked as [CWE-407] Inefficient Algorithmic Complexity.
Critical Impact
Remote unauthenticated attackers can trigger CPU exhaustion in any Node.js or browser application that ingests untrusted object keys through Immutable.js, causing service disruption.
Affected Products
- Immutable.js versions prior to 4.3.9
- Immutable.js versions prior to 5.1.8 (5.x branch)
- Applications using Immutable.Map, Immutable.Set, Immutable.fromJS, merge, or mergeDeep with attacker-controlled input
Discovery Timeline
- 2026-07-08 - CVE-2026-59880 published to NVD
- 2026-07-08 - Last updated in NVD database
Technical Details for CVE-2026-59880
Vulnerability Analysis
Immutable.js implements its Map and Set structures using a Hash Array Mapped Trie (HAMT). When multiple keys produce the same 32-bit hash, they are stored inside a HashCollisionNode. Prior to the patch, this node scanned entries linearly on every insertion and lookup. An attacker who submits n colliding keys forces n comparisons per operation, yielding O(n²) total work to build or query the collection. This is a textbook algorithmic complexity attack against unauthenticated inputs.
Root Cause
The primary string hash in Immutable.js uses base 31, a well-known Java-style rolling hash. Keys constructed from repeating "Aa" and "BB" two-character blocks share identical 32-bit hashes because Aa and BB collide under base 31. All such keys pile into a single HashCollisionNode. The bucket lacked any secondary index, so equality checks ran linearly through every colliding entry.
Attack Vector
The vulnerability is network-reachable and requires no authentication. Any endpoint that passes untrusted JSON or object data into Immutable.Map(obj), Immutable.fromJS(obj), or state.merge(userObject) is exposed. Common attack surfaces include Redux/React state hydration from user input, GraphQL resolvers, and API bodies deserialized into immutable state.
The patch introduces a per-process seeded secondary hash to index entries within a HashCollisionNode:
// Per-process seed for the secondary collision hash. Never exposed nor
// serialized, so the public `hash()` stays deterministic. An odd base in
// [3, 2^20) keeps `base * h` exact as a double (no `Math.imul`).
const COLLISION_HASH_BASE =
((Math.random() * 0x100000) | 1) % 0x100000 || 0x9e37;
// Secondary hash to index entries within a `HashCollisionNode`, where every key
// shares the same primary `hash()`. Using a different, seeded base scatters
// crafted collision families (e.g. "Aa"/"BB", which only collide under base 31)
// that an attacker cannot precompute without the seed.
export function hashCollisionKey(key) {
if (typeof key !== 'string') {
return hash(key);
}
let hashed = 0;
for (let ii = 0; ii < key.length; ii++) {
hashed = (COLLISION_HASH_BASE * hashed + key.charCodeAt(ii)) | 0;
}
return hashed;
}
Source: immutable-js commit 3dd7e56
The test harness in the patch demonstrates the attack by generating up to 4,096 colliding keys using the "Aa"/"BB" construction pattern.
Detection Methods for CVE-2026-59880
Indicators of Compromise
- Sustained CPU saturation on Node.js processes handling user-submitted JSON payloads
- HTTP request bodies containing large numbers of keys with repeating Aa/BB two-character blocks
- Application response latency growing quadratically with input object size
- Event loop lag or health-check failures during ingestion of user-controlled objects
Detection Strategies
- Perform software composition analysis (SCA) on package-lock.json and yarn.lock to identify Immutable.js versions below 4.3.9 or 5.1.8
- Add runtime instrumentation around calls to Immutable.fromJS and Immutable.Map to log input sizes and processing time
- Deploy web application firewall rules that flag JSON bodies with unusually large object-key counts or highly repetitive key patterns
Monitoring Recommendations
- Monitor Node.js event loop lag metrics via perf_hooks or APM tooling and alert on sustained latency spikes
- Track per-endpoint CPU time and correlate spikes with request payload characteristics
- Log and rate-limit endpoints that accept arbitrary object keys from untrusted callers
How to Mitigate CVE-2026-59880
Immediate Actions Required
- Upgrade Immutable.js to version 4.3.9 (4.x branch) or 5.1.8 (5.x branch) immediately
- Audit all code paths passing untrusted input to Immutable.Map, Immutable.fromJS, merge, or mergeDeep
- Apply request-body size limits and object-key count limits at the API gateway or middleware layer
Patch Information
The fix is available in Immutable.js v4.3.9 and Immutable.js v5.1.8. The patch introduces a per-process seeded secondary hash (hashCollisionKey) that indexes entries within HashCollisionNode, converting linear scans into indexed lookups. Full technical details are in the GHSA-xvcm-6775-5m9r advisory.
Workarounds
- Validate and constrain the size of user-supplied objects before passing them to Immutable.js constructors
- Reject or sanitize keys matching known collision patterns such as repeated Aa/BB blocks
- Impose per-request CPU or timeout budgets to prevent single requests from starving the event loop
# Upgrade Immutable.js using npm
npm install immutable@^5.1.8
# Or for the 4.x branch
npm install immutable@^4.3.9
# Verify the installed version
npm ls immutable
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

