High

nanoid: Integer Overflow or Wraparound

  • Disclosed: 01.09.2026
  • Updated: 11.10.2026 10:22

Summary

An integer overflow in nanoid(size) permanently corrupts the process-wide CSPRNG pool, causing all subsequent ID generation to return the deterministic string "uuuuuuuuuuuuuuuuuuuuu". Any application that passes user-influenced values to the size parameter loses all randomness guarantees for session tokens, CSRF tokens, and unique identifiers until process restart.

Details

nanoid() at index.js:101 coerces the size parameter with size |= 0, which converts it to a signed 32-bit integer. When size >= 2^31 (e.g., 2147483648), this wraps to -2147483648.

The negative value is passed to fillPool() (index.js:15):

js
function fillPool(bytes) {
  if (!pool || pool.length < bytes) {       // false: pool exists, -2B < pool.length
    pool = Buffer.allocUnsafe(bytes * POOL_SIZE_MULTIPLIER)
    crypto.getRandomValues(pool)
    poolOffset = 0
  } else if (poolOffset + bytes > pool.length) {  // false: poolOffset + (-2B) < pool.length
    crypto.getRandomValues(pool)
    poolOffset = 0
  }
  poolOffset += bytes  // poolOffset += -2147483648 → deeply negative
}

Neither branch triggers, so the pool is never refreshed. poolOffset becomes ~-2.1 billion.

Subsequent nanoid() calls execute:

js
for (let i = poolOffset - size; i < poolOffset; i++) {
  id += scopedUrlAlphabet[pool[i] & 63]
}

pool[negative_index] returns undefined. undefined & 63 evaluates to 0. urlAlphabet[0] is 'u'. Every ID becomes "uuuuuuuuuuuuuuuuuuuuu".

The corruption is persistent — it affects all subsequent calls in the process until ~100 million calls eventually wrap poolOffset back to positive, or the process restarts.

PoC

js
import { nanoid } from 'nanoid'

// Step 1: Normal operation
console.log(nanoid())  // e.g., "V1StGXR8_Z5jdHi6B-myT"

// Step 2: Trigger overflow (e.g., from an API parameter)
try { nanoid(2147483648) } catch(e) {}

// Step 3: All subsequent IDs are deterministic
console.log(nanoid())  // "uuuuuuuuuuuuuuuuuuuuu"
console.log(nanoid())  // "uuuuuuuuuuuuuuuuuuuuu"
console.log(nanoid())  // "uuuuuuuuuuuuuuuuuuuuu"
// ... forever, process-wide

Run with: node --experimental-vm-modules poc.mjs

Attack scenario: Any API endpoint that accepts a user-controlled length/size parameter (URL shortener slug length, configurable token size, etc.) and passes it to nanoid(userInput).

Impact

Complete loss of ID unpredictability and uniqueness, process-wide, from a single request.

  • All session IDs, CSRF tokens, API keys, and database identifiers generated after the attack are identical and predictable
  • An attacker can predict all tokens issued to other users, enabling session hijacking and authentication bypass
  • The corruption is persistent (survives across requests) and affects all consumers of nanoid in the same process
  • No special privileges or preconditions required — a single unauthenticated request is sufficient
  • Affects any application that passes external input to the size parameter without validation

Affected software

Click a technology to see all vulnerabilities affecting it.

PlatformPackageVulnerable versionsFixed in
npm package nanoid < 3.3.12, >= 4.0.0, < 5.1.11 3.3.12, 5.1.11

References

CVSS score 7.4/10
CVSS vector
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N
Weakness (CWE)
CWE-190
Platform
npm
Package
nanoid
Disclosed
01.09.2026
Updated
11.10.2026 10:22

Sources and licenses

OSV / GitHub Advisory Database - GHSA-xwg4-73v4-xw9w - CC BY 4.0

Vulnerability history: nanoid

All published vulnerabilities of this package (npm package), newest first. Shows whether this is a one-off slip or a package that needs watching.

Total entries
5
First → latest
01.2022 09.2026
Without a fix
0
Exploited in attacks
0

Severity breakdown

  • High 3
  • Medium 2

Disclosures per year

  1. 2022: 1
  2. 2023: 0
  3. 2024: 1
  4. 2025: 0
  5. 2026: 3
  1. nanoid: Integer Overflow or Wraparound this entry
    High · 7.4 CVE-2026-73086 < 3.3.12, >= 4.0.0, < 5.1.11 3.3.12, 5.1.11
  2. High · 5.9 CVE-2026-67213 < 3.3.18, >= 4.0.0, < 5.1.6 3.3.18, 5.1.6
  3. High · 5.9 CVE-2026-67214 < 3.3.16, >= 4.0.0, < 5.1.16 3.3.16, 5.1.16
  4. Medium · 4.3 CVE-2024-55565 >= 4.0.0, < 5.0.9, < 3.3.8 5.0.9, 3.3.8
  5. Medium · 5.5 CVE-2021-23566 >= 3.0.0, < 3.1.31 3.1.31

Know which vulnerabilities affect your application

With the DockRay integration and software inventory enabled, DockRay checks reported component versions against known vulnerabilities and notifies you about confirmed matches. Coverage depends on the supported technology and available advisory data.

Connect your application
DockRay newsletter

Application security in your inbox

Important vulnerabilities, actionable guidance and practical advice for your applications. Choose your technologies and follow what matters to your project.

  • A daily digest of new vulnerabilities, critical ones included.
  • Notifications about important updates.
  • Practical advice on application security and monitoring.

Leave empty to receive updates for every technology.

Free to subscribe. Unsubscribe with one click in any email.