| パッケージ | 影響を受けるバージョン | 修正済みバージョン |
|---|---|---|
| immutable | ≥ 5.0.0, < 5.1.8< 4.3.9 | 5.1.84.3.9 |
| immutable | ≥ 4.0.0-beta.1, < 4.3.9≥ 5.0.0-beta.1, < 5.1.8< 3.8.4 | 4.3.95.1.83.8.4 |
Immutable.Map and Immutable.Set keep keys that share the same 32-bit hash in a collision bucket that is scanned linearly. The string hash is public and deterministic, so an attacker who controls the keys inserted into a Map can craft many keys that all collide, degrading insertion and lookup from amortized O(1) to O(n) per operation — and O(n²) to build or read the whole set. A small, attacker-shaped payload can therefore consume disproportionate CPU and, on a single-threaded runtime such as Node.js, stall the event loop and deny service.
The string hash uses the JVM-style polynomial hashed = (31 * hashed + charCode) | 0. Strings such as "Aa" and "BB" hash to the same value (65*31+97 == 66*31+66 == 2112), and concatenating such blocks yields 2^n distinct strings sharing one hash (40 characters ⇒ >1,000,000 colliding keys).
All such keys route to a single HashCollisionNode, whose get/update walk the entire bucket testing is(). There is no per-process salt, so the colliding set is fully precomputable from the open-source algorithm.
Inserting N colliding keys (e.g. via Immutable.Map(obj) / Immutable.fromJS(obj)) is O(N²). Measured on one machine, ~8,000 colliding
keys take ~0.7 s to build and ~0.6 s to read, scaling ×4 per doubling; ~16,000 keys exceed several seconds.
CPU-bound denial of service in applications that ingest attacker-controlled object keys into Immutable structures, e.g. Immutable.Map(req.body), Immutable.fromJS(req.body), state.merge(userObject) / mergeDeep(...). Applications that only store attacker input as values under fixed keys are not affected.
= 4.0.0-beta.1, < 4.3.9
= 5.0.0-beta.1, < 5.1.8
Fixed in 5.1.8 (adjust to the actual release): large collision buckets are indexed by a per-process seeded secondary hash, restoring near-linear behavior for the affected paths. The public hash() is unchanged (no breaking change), and is() remains the sole authority on key equality. Also fixed in 4.3.9 and 3.8.4.
これらの製品をお使いですか?サイトをスキャンして、脆弱なバージョンが公開されていないか確認しましょう。
無料でサイトをスキャンBefore passing untrusted data to Immutable.js: cap request body size, limit object key count/length, and reject high-cardinality payloads; avoid building Maps directly from untrusted object keys.