NIST deprecates RSA-2048 from 2030. Find every one of them before attackers do.
📦
📦 npm
Not in CISA KEV
HIGH severity

CVE-2026-73086 — nanoid

HIGHFix: ai/nanoid@7087969

CVE-2026-73086 is a high-severity (CVSS 7.4) CWE-190 vulnerability in nanoid. A fix is available for nanoid — see the affected versions and patch details below.

nanoid: Integer Overflow or Wraparound

Also known asGHSA-xwg4-73v4-xw9w
Published
Updated
Affected
2 pkgs
Patched
2 / 2
Exploits
None indexed
Exploitation data as of Nov 10, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

No confirmed exploitation observed yet

  • A successful exploit gives an attacker total control of the affected component, not partial access.
  • CISA’s own triage has not observed active exploitation or public proof-of-concept code for this CVE as of its last assessment.

Exploitation and automatability from CISA’s SSVC triage for CVE-2026-73086.

EPSS Exploitation Probability

via FIRST.org ↗
0.3%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs22th percentile — riskier than 22% of all scored CVEsHighest risk
0.00%0.27%0.53%0.80%0.3%0.3%0.3%0.3%Sep 26Nov 26Nov 26

Probability of exploitation in the next 30 days, from FIRST.org EPSS.

How urgent is this, really

Where this sits among everything scored

Real-World Exposure

2 pkgs affected

How broadly this vulnerability is actually deployed: weekly install volume shows current usage, and reverse-dependency count shows how many other packages break if it stays unpatched.

18Kother npm packages depend on this — each one inherits the vulnerability until it's patched upstream
nanoidnpm
372.2Mdownloads / week

Description

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):

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:

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

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 Packages

2 total 2 fixed
EcosystemPackageVulnerable rangeFix
📦npmnanoidall versions3.3.12npm install nanoid@3.3.12
📦npmnanoid≥ 4.0.0&&< 5.1.115.1.11npm install nanoid@5.1.11

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for nanoid, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    Update nanoid to 3.3.12 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-73086 is resolved across your whole dependency graph.

  3. Workarounds

    Stop feeding it untrusted input: reject or quarantine files and payloads from unverified sources until you can upgrade, restrict accepted formats to the ones you actually need, and run the parsing or decoding step in a least-privileged sandbox or short-lived worker so a crash or corrupted read cannot reach the rest of the process.

Fixing This On Your OS

If you run this on a Linux distribution, patch through your package manager against the distro's own security advisory below — it tracks the exact backported fix for your release, which can ship on a different timeline (and sometimes a different severity) than the upstream project.

Red HatImportant

Important: This flaw in the nanoid JavaScript library allows a remote attacker to cause predictable ID generation by exploiting an integer overflow in the `nanoid(size)` function. This can lead to the compromise of session tokens, CSRF tokens, and API keys, bypassing security mechanisms. The attack requires specific…

Workaround published by Red Hat
Mitigation for this issue is either not available or the currently available options do not meet the Red Hat Product Security criteria comprising ease of use and deployment, applicability to widespread installation base, or stability.
Source: Red Hat security advisory for CVE-2026-73086 (CC BY 4.0)
ProductFixed inAdvisory
Red Hat Ansible Automation Platform 2.6 for RHEL 9automation-platform-ui-0:2.6.14-1.el9apRHSA-2026:71113
Red Hat Satellite 6.19 for RHEL 9foreman-0:3.18.0.14-1.el9satRHSA-2026:74503
Cluster Observability Operator 1.5cluster-observability-operator/prometheus-rhel9:1790857922RHSA-2026:74609
multicluster engine for Kubernetes 2.11multicluster-engine/console-mce-rhel9:1786911977RHSA-2026:57194
multicluster engine for Kubernetes 2.17multicluster-engine/console-mce-rhel9:1786668856RHSA-2026:59593
multicluster engine for Kubernetes 2.6multicluster-engine/console-mce-rhel9:1787264250RHSA-2026:59579
multicluster engine for Kubernetes 2.8multicluster-engine/console-mce-rhel9:1787259048RHSA-2026:59558
multicluster engine for Kubernetes 2.9multicluster-engine/console-mce-rhel9:1787079359RHSA-2026:59559

Frequently Asked Questions

### 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`](https://github.com/ai/nanoid/blob/main/index.js#L101) coerces the `size` parameter with `size |= 0`, which converts it to a signed 32-bit integer. When `size >= 2^31` (
O3 Security · Impact-Aware SCA

Is CVE-2026-73086 in your dependencies?

Find it across npm, including transitive dependencies.

CVE-2026-73086: nanoid CSRF — Fixed in 3.3.12