High severity7.5NVD Advisory· Published Apr 24, 2026· Updated May 11, 2026
CVE-2026-41907
CVE-2026-41907
Description
uuid is for the creation of RFC9562 (formerly RFC4122) UUIDs. Prior to 14.0.0, v3, v5, and v6 accept external output buffers but do not reject out-of-range writes (small buf or large offset). This allows silent partial writes into caller-provided buffers. This vulnerability is fixed in 14.0.0.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
uuidnpm | >= 11.0.0, < 11.1.1 | 11.1.1 |
uuidnpm | >= 12.0.0, < 12.0.1 | 12.0.1 |
uuidnpm | >= 13.0.0, < 13.0.1 | 13.0.1 |
Affected products
4Patches
17 files changed · +45 −10
src/test/v1.test.ts+3 −3 modified@@ -204,8 +204,8 @@ describe('v1', () => { test('throws RangeError for out-of-range indexes', () => { const buf15 = new Uint8Array(15); const buf30 = new Uint8Array(30); - assert.throws(() => v1({}, buf15)); - assert.throws(() => v1({}, buf30, -1)); - assert.throws(() => v1({}, buf30, 15)); + assert.throws(() => v1({}, buf15), RangeError); + assert.throws(() => v1({}, buf30, -1), RangeError); + assert.throws(() => v1({}, buf30, 15), RangeError); }); });
src/test/v35.test.ts+16 −0 modified@@ -161,6 +161,14 @@ describe('v35', () => { assert.throws(() => v3('hello.example.com', null, new Uint8Array(16))); }); + test('v3 throws RangeError for out-of-range indexes', () => { + const buf15 = new Uint8Array(15); + const buf30 = new Uint8Array(30); + assert.throws(() => v3('hello.example.com', v3.DNS, buf15), RangeError); + assert.throws(() => v3('hello.example.com', v3.DNS, buf30, -1), RangeError); + assert.throws(() => v3('hello.example.com', v3.DNS, buf30, 15), RangeError); + }); + test('v5', () => { // Expect to get the same results as http://tools.adjet.org/uuid-v5 assert.strictEqual( @@ -269,6 +277,14 @@ describe('v35', () => { assert.throws(() => v5('hello.example.com', null, new Uint8Array(16))); }); + test('v5 throws RangeError for out-of-range indexes', () => { + const buf15 = new Uint8Array(15); + const buf30 = new Uint8Array(30); + assert.throws(() => v5('hello.example.com', v5.DNS, buf15), RangeError); + assert.throws(() => v5('hello.example.com', v5.DNS, buf30, -1), RangeError); + assert.throws(() => v5('hello.example.com', v5.DNS, buf30, 15), RangeError); + }); + test('v3/v5 constants', () => { assert.strictEqual(v3.DNS, '6ba7b810-9dad-11d1-80b4-00c04fd430c8'); assert.strictEqual(v3.URL, '6ba7b811-9dad-11d1-80b4-00c04fd430c8');
src/test/v4.test.ts+3 −3 modified@@ -117,8 +117,8 @@ describe('v4', () => { test('throws RangeError for out-of-range indexes', () => { const buf15 = new Uint8Array(15); const buf30 = new Uint8Array(30); - assert.throws(() => v4({}, buf15)); - assert.throws(() => v4({}, buf30, -1)); - assert.throws(() => v4({}, buf30, 15)); + assert.throws(() => v4({}, buf15), RangeError); + assert.throws(() => v4({}, buf30, -1), RangeError); + assert.throws(() => v4({}, buf30, 15), RangeError); }); });
src/test/v6.test.ts+8 −0 modified@@ -80,6 +80,14 @@ describe('v6', () => { assert.deepEqual(buffer, expectedBuf); }); + test('throws RangeError for out-of-range indexes', () => { + const buf15 = new Uint8Array(15); + const buf30 = new Uint8Array(30); + assert.throws(() => v6({}, buf15), RangeError); + assert.throws(() => v6({}, buf30, -1), RangeError); + assert.throws(() => v6({}, buf30, 15), RangeError); + }); + test('v1 -> v6 conversion', () => { const id = v1ToV6(V1_ID); assert.equal(id, V6_ID);
src/test/v7.test.ts+3 −3 modified@@ -293,8 +293,8 @@ describe('v7', () => { test('throws RangeError for out-of-range indexes', () => { const buf15 = new Uint8Array(15); const buf30 = new Uint8Array(30); - assert.throws(() => v7({}, buf15)); - assert.throws(() => v7({}, buf30, -1)); - assert.throws(() => v7({}, buf30, 15)); + assert.throws(() => v7({}, buf15), RangeError); + assert.throws(() => v7({}, buf30, -1), RangeError); + assert.throws(() => v7({}, buf30, 15), RangeError); }); });
src/v35.ts+6 −1 modified@@ -55,7 +55,12 @@ export default function v35<TBuf extends Uint8Array = Uint8Array>( bytes[8] = (bytes[8] & 0x3f) | 0x80; if (buf) { - offset = offset || 0; + offset ??= 0; + if (offset < 0 || offset + 16 > buf.length) { + throw new RangeError( + `UUID byte range ${offset}:${offset + 15} is out of buffer bounds`, + ); + } for (let i = 0; i < 16; ++i) { buf[offset + i] = bytes[i];
src/v6.ts+6 −0 modified@@ -31,6 +31,12 @@ function v6<TBuf extends Uint8Array = Uint8Array>( // Return as a byte array if requested if (buf) { + if (offset < 0 || offset + 16 > buf.length) { + throw new RangeError( + `UUID byte range ${offset}:${offset + 15} is out of buffer bounds`, + ); + } + for (let i = 0; i < 16; i++) { buf[offset + i] = bytes[i]; }
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- github.com/uuidjs/uuid/security/advisories/GHSA-w5hq-g745-h8pqnvdExploitVendor AdvisoryMitigationWEB
- github.com/advisories/GHSA-w5hq-g745-h8pqghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2026-41907ghsaADVISORY
- github.com/uuidjs/uuid/commit/3d2c5b0342f0fcb52a5ac681c3d47c13e7444b34ghsaWEB
- github.com/uuidjs/uuid/releases/tag/v14.0.0ghsaWEB
News mentions
0No linked articles in our index yet.