{"id":"GHSA-xwg4-73v4-xw9w","revision":null,"records":[{"revision":"840a250173254a55a404ad4d31de337d","observedAt":"2026-10-23T15:48:27.903+00:00","statement":{"source":"cve-program","id":"CVE-2026-73086","aliases":[],"title":"nanoid: Integer Overflow or Wraparound","description":"nanoid is a secure, URL-friendly, unique string ID generator for JavaScript. Prior to versions 3.3.12 and 5.1.11, the nanoid(size) function in index.js and index.cjs coerces the user-influenced size parameter to a signed 32-bit integer, allowing a value of 2147483648 to become -2147483648 and corrupt the process-wide CSPRNG poolOffset in fillPool(), which causes subsequent session tokens, CSRF tokens, API keys, and unique identifiers to become the deterministic string \"uuuuuuuuuuuuuuuuuuuuu\" until the process restarts. This issue is fixed in versions 3.3.12 and 5.1.11.","state":0,"publishedAt":"2026-08-11T16:46:23.024+00:00","modifiedAt":"2026-08-12T14:29:36.568+00:00","affected":[{"ecosystem":"Vendor product","name":"nanoid","ranges":[],"versions":[],"rawVersionEvidence":"{\n                    \"vendor\": \"ai\",\n                    \"product\": \"nanoid\",\n                    \"versions\": [\n                        {\n                            \"version\": \"< 3.3.12\",\n                            \"status\": \"affected\"\n                        },\n                        {\n                            \"version\": \">= 4.0.0, < 5.1.11\",\n                            \"status\": \"affected\"\n                        }\n                    ]\n                }"}],"metrics":[{"system":"CVSS 3.1","vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N","score":7.4,"severity":"HIGH"}],"references":["https://github.com/ai/nanoid/security/advisories/GHSA-xwg4-73v4-xw9w","https://github.com/ai/nanoid/commit/7087969281cab8ba8ae3babf1894e819068b3bb4","https://github.com/ai/nanoid/commit/821dfed7b5db7f88e92f56c60eef32c8135077c3","https://github.com/ai/nanoid/commit/b0036ed60dc9facd7f1191a50dfb3076500202ac","https://github.com/ai/nanoid/releases/tag/3.3.12","https://github.com/ai/nanoid/releases/tag/5.1.11"],"sourceUrl":"https://www.cve.org/CVERecord?id=CVE-2026-73086","license":"CVE Program Terms of Use","key":"cve-program:CVE-2026-73086","identifiers":["CVE-2026-73086"]},"retained":false,"historicalAffected":[]},{"revision":"b000d48289a548da8dfc719a7dc318eb","observedAt":"2026-10-25T15:19:03.401+00:00","statement":{"source":"nvd","id":"CVE-2026-73086","aliases":[],"title":"nanoid is a secure, URL-friendly, unique string ID generator for JavaScript. Prior to versions 3.3.12 and 5.1.11, the nanoid(size) function in index.js and index.cjs coerces the user-influenced size parameter to a signed 32-bit integer, all…","description":"nanoid is a secure, URL-friendly, unique string ID generator for JavaScript. Prior to versions 3.3.12 and 5.1.11, the nanoid(size) function in index.js and index.cjs coerces the user-influenced size parameter to a signed 32-bit integer, allowing a value of 2147483648 to become -2147483648 and corrupt the process-wide CSPRNG poolOffset in fillPool(), which causes subsequent session tokens, CSRF tokens, API keys, and unique identifiers to become the deterministic string \"uuuuuuuuuuuuuuuuuuuuu\" until the process restarts. This issue is fixed in versions 3.3.12 and 5.1.11.","state":0,"publishedAt":"2026-08-11T17:19:16.69+00:00","modifiedAt":"2026-10-24T15:10:00.19+00:00","affected":[],"metrics":[{"system":"CVSS 3.1 · security-advisories@github.com · Secondary","vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N","score":7.4,"severity":"HIGH"}],"references":["https://github.com/ai/nanoid/commit/7087969281cab8ba8ae3babf1894e819068b3bb4","https://github.com/ai/nanoid/commit/821dfed7b5db7f88e92f56c60eef32c8135077c3","https://github.com/ai/nanoid/commit/b0036ed60dc9facd7f1191a50dfb3076500202ac","https://github.com/ai/nanoid/releases/tag/3.3.12","https://github.com/ai/nanoid/releases/tag/5.1.11","https://github.com/ai/nanoid/security/advisories/GHSA-xwg4-73v4-xw9w"],"sourceUrl":"https://nvd.nist.gov/vuln/detail/CVE-2026-73086","license":"NIST NVD usage terms; underlying source attribution retained","enrichment":{"sourceStatus":"Deferred","weaknesses":["CWE-190"],"productCriteria":[],"sourceDates":{"published":"2026-08-11T17:19:16.690","lastModified":"2026-10-24T15:10:00.190"},"relatedAdvisories":[],"note":"NVD analysis and CPE criteria are source context, not proof that a package or your environment is affected. Complete affected data, logical configurations and SSVC are retained in the original JSON."},"key":"nvd:CVE-2026-73086","identifiers":["CVE-2026-73086"]},"retained":false,"historicalAffected":[]},{"revision":"ed43c5016edb4ed39d03375e198d395d","observedAt":"2026-10-24T13:17:17.793+00:00","statement":{"source":"osv","id":"GHSA-xwg4-73v4-xw9w","aliases":["CVE-2026-73086"],"title":"nanoid: Integer Overflow or Wraparound","description":"### Summary\n\nAn 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.\n\n### Details\n\n`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` (e.g., `2147483648`), this wraps to `-2147483648`.\n\nThe negative value is passed to `fillPool()` ([`index.js:15`](https://github.com/ai/nanoid/blob/main/index.js#L15)):\n\n```javascript\nfunction fillPool(bytes) {\n  if (!pool || pool.length < bytes) {       // false: pool exists, -2B < pool.length\n    pool = Buffer.allocUnsafe(bytes * POOL_SIZE_MULTIPLIER)\n    crypto.getRandomValues(pool)\n    poolOffset = 0\n  } else if (poolOffset + bytes > pool.length) {  // false: poolOffset + (-2B) < pool.length\n    crypto.getRandomValues(pool)\n    poolOffset = 0\n  }\n  poolOffset += bytes  // poolOffset += -2147483648 → deeply negative\n}\n```\n\nNeither branch triggers, so the pool is never refreshed. `poolOffset` becomes ~-2.1 billion.\n\nSubsequent `nanoid()` calls execute:\n```javascript\nfor (let i = poolOffset - size; i < poolOffset; i++) {\n  id += scopedUrlAlphabet[pool[i] & 63]\n}\n```\n\n`pool[negative_index]` returns `undefined`. `undefined & 63` evaluates to `0`. `urlAlphabet[0]` is `'u'`. Every ID becomes `\"uuuuuuuuuuuuuuuuuuuuu\"`.\n\nThe 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.\n\n### PoC\n\n```javascript\nimport { nanoid } from 'nanoid'\n\n// Step 1: Normal operation\nconsole.log(nanoid())  // e.g., \"V1StGXR8_Z5jdHi6B-myT\"\n\n// Step 2: Trigger overflow (e.g., from an API parameter)\ntry { nanoid(2147483648) } catch(e) {}\n\n// Step 3: All subsequent IDs are deterministic\nconsole.log(nanoid())  // \"uuuuuuuuuuuuuuuuuuuuu\"\nconsole.log(nanoid())  // \"uuuuuuuuuuuuuuuuuuuuu\"\nconsole.log(nanoid())  // \"uuuuuuuuuuuuuuuuuuuuu\"\n// ... forever, process-wide\n```\n\nRun with: `node --experimental-vm-modules poc.mjs`\n\nAttack 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)`.\n\n### Impact\n\n**Complete loss of ID unpredictability and uniqueness, process-wide, from a single request.**\n\n- All session IDs, CSRF tokens, API keys, and database identifiers generated after the attack are identical and predictable\n- An attacker can predict all tokens issued to other users, enabling session hijacking and authentication bypass\n- The corruption is persistent (survives across requests) and affects all consumers of `nanoid` in the same process\n- No special privileges or preconditions required — a single unauthenticated request is sufficient\n- Affects any application that passes external input to the `size` parameter without validation","state":0,"publishedAt":"2026-09-01T19:23:45+00:00","modifiedAt":"2026-09-01T19:30:08.6155607+00:00","affected":[{"ecosystem":"npm","name":"nanoid","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"0"},{"kind":"fixed","version":"3.3.12"}]}],"versions":[],"rawVersionEvidence":null},{"ecosystem":"npm","name":"nanoid","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"4.0.0"},{"kind":"fixed","version":"5.1.11"}]}],"versions":[],"rawVersionEvidence":null}],"metrics":[{"system":"CVSS_V3","vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N","score":null,"severity":null},{"system":"Publisher rating","vector":null,"score":null,"severity":"HIGH"}],"references":["https://github.com/ai/nanoid/security/advisories/GHSA-xwg4-73v4-xw9w","https://nvd.nist.gov/vuln/detail/CVE-2026-73086","https://github.com/ai/nanoid/commit/7087969281cab8ba8ae3babf1894e819068b3bb4","https://github.com/ai/nanoid/commit/821dfed7b5db7f88e92f56c60eef32c8135077c3","https://github.com/ai/nanoid/commit/b0036ed60dc9facd7f1191a50dfb3076500202ac","https://github.com/ai/nanoid","https://github.com/ai/nanoid/releases/tag/3.3.12","https://github.com/ai/nanoid/releases/tag/5.1.11"],"sourceUrl":"https://github.com/advisories/GHSA-xwg4-73v4-xw9w","license":"GitHub Advisory Database · CC-BY-4.0","key":"osv:GHSA-xwg4-73v4-xw9w","identifiers":["GHSA-xwg4-73v4-xw9w","CVE-2026-73086"]},"retained":false,"historicalAffected":[]}],"coverage":[{"source":"cisa-kev:global","scope":"Complete CISA KEV catalog; all vendors. Missing entries do not establish absence of exploitation.","generation":"2026-10-26T05:26:56.6538334+00:00","complete":true,"records":1756,"lastAttemptAt":"2026-10-26T05:26:56.6538334+00:00","lastSuccessAt":"2026-10-26T05:26:56.7986454+00:00","error":null,"lastVerifiedAt":"2026-10-26T05:26:56.7986482+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null},{"source":"cve-program","scope":"Official CVE Program baseline and cumulative hourly delta; all vendors, published and rejected records","generation":"cve-5ba1945314e042c2ced14b33f3680fa71692812d925544312b218f5eb8a26e71-bc703d32c448acb7291b43dd467a47b987ad86f105a430a0e30b03cf6e038792","complete":true,"records":414069,"lastAttemptAt":"2026-10-26T05:25:21.6088408+00:00","lastSuccessAt":"2026-10-26T05:25:21.5943862+00:00","error":null,"lastVerifiedAt":"2026-10-26T05:25:21.6088408+00:00","snapshotPublishedAt":"2026-10-26T04:31:21+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null},{"source":"euvd","scope":"Rolling EUVD lookups of CVE aliases in current public OSV archives; 500 identifiers per refresh, rechecked after 48 hours. Not a global EUVD catalog. Successful not-found lookups count as checked; they do not imply withdrawal or safety. No reader inventory is sent.","generation":"enrichment-43321610382942b8ad8c85917eab1546","complete":false,"records":4735,"lastAttemptAt":"2026-10-26T05:26:59.285199+00:00","lastSuccessAt":"2026-10-24T23:18:49.862+00:00","error":"InvalidDataException","lastVerifiedAt":"2026-10-24T23:18:49.862+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":4764,"expectedIdentifiers":13474},{"source":"first-epss:nuget","scope":"FIRST EPSS for explicit CVE aliases in the collected public NuGet archive. Not a global EPSS backfill.","generation":"2026-10-26T05:26:56.6538334+00:00","complete":true,"records":1093,"lastAttemptAt":"2026-10-26T05:26:56.6538334+00:00","lastSuccessAt":"2026-10-26T05:26:56.7998442+00:00","error":null,"lastVerifiedAt":"2026-10-26T05:26:56.799845+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null},{"source":"nvd","scope":"Rolling NVD lookups of CVE aliases in current public OSV archives; 500 identifiers per refresh, rechecked after 48 hours. Not a global NVD catalog. Successful not-found lookups count as checked; they do not imply withdrawal or safety. No reader inventory is sent.","generation":"enrichment-204a3fb93a00487e8f7f36db01dc851d","complete":true,"records":13413,"lastAttemptAt":"2026-10-26T05:26:57.2787164+00:00","lastSuccessAt":"2026-10-25T16:19:28.681+00:00","error":null,"lastVerifiedAt":"2026-10-25T16:19:28.681+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":13474,"expectedIdentifiers":13474},{"source":"osv:Go","scope":"Complete OSV Go ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"go-2375a4e597279abf92e8747e140fe8da9d421877cd49cae3ac69a2cb78469b2c","complete":true,"records":9779,"lastAttemptAt":"2026-10-26T05:26:56.2433127+00:00","lastSuccessAt":"2026-10-24T13:19:53.1346702+00:00","error":null,"lastVerifiedAt":"2026-10-26T05:26:56.2433127+00:00","snapshotPublishedAt":"2026-10-24T03:03:12+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null},{"source":"osv:NuGet","scope":"Complete OSV NuGet ecosystem archive, including GitHub Advisory Database records; NuGet version matching only","generation":"nuget-16ad89dfea13ab9e9b0108e63a759d63bd4559cc68b58491107d62ee35bbbaf2","complete":true,"records":1965,"lastAttemptAt":"2026-10-26T05:25:21.7989429+00:00","lastSuccessAt":"2026-10-23T16:01:26.4487605+00:00","error":null,"lastVerifiedAt":"2026-10-26T05:25:21.7989429+00:00","snapshotPublishedAt":"2026-10-21T12:18:07+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null},{"source":"osv:crates.io","scope":"Complete OSV crates.io ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"crates.io-7da67a15aa6e56a0e3081a7646dc74d537e6ef974afc593c2b1794ed01970648","complete":true,"records":2969,"lastAttemptAt":"2026-10-26T05:26:56.6198554+00:00","lastSuccessAt":"2026-10-24T13:19:59.1145547+00:00","error":null,"lastVerifiedAt":"2026-10-26T05:26:56.6198554+00:00","snapshotPublishedAt":"2026-10-24T08:47:51+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null},{"source":"osv:npm","scope":"Complete OSV npm ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"npm-f936be991545888acd70d1c7b6fcb3da4be35405bbec4bff46b924c2832f41b1","complete":true,"records":230802,"lastAttemptAt":"2026-10-26T05:26:56.1119243+00:00","lastSuccessAt":"2026-10-26T05:26:54.9585845+00:00","error":null,"lastVerifiedAt":"2026-10-26T05:26:56.1119243+00:00","snapshotPublishedAt":"2026-10-26T04:48:14+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null}]}