Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-59880

CVE-2026-59880: Immutable.js Hash Collision DOS Vulnerability

CVE-2026-59880 is a denial of service flaw in Immutable.js that allows attackers to degrade performance through hash collision attacks. This post covers technical details, affected versions, impact, and mitigation steps.

Published:

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:

javascript
// 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
bash
# 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.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.