CVE-2026-107392: music-metadata: uncatchable process crash parsing a crafted `.dsf` (residual of CVE-2026-32256)
Summary DsfParser.parseChunks skips an unrecognised chunk's payload with an un-awaited call: js this.tokenizer.ignore(Number(chunkHeader.size) - ChunkHeader.len); // lib/dsf/DsfParser.js:51 — no await ChunkHeader.len is 12. A crafted .dsf chunk with id != 'fmt ' and size in 0..11 makes the argument negative; strtok3 (≥ 10.3.5) throws RangeError on a negative ignore. Because the call is fire-and-forget, the rejection is detached from the parseBuffer() promise chain → unhandled rejection → Node's default (≥ 15) crashes the process — after parseBuffer() already resolved, so a caller's try/catch catches nothing and is still taken down.
Residual of GHSA-v6c2-xwv6-8xf7: the ASF site was fixed in 11.12.3 (size validation) and strtok3 now throws on negative ignore; the DSF site was never validated, and its missing await escalates that throw into an uncatchable crash.
Root cause (lib/dsf/DsfParser.js:34-56) js while (bytesRemaining >= ChunkHeader.len) { // ChunkHeader.len = 12 const chunkHeader = await this.tokenizer.readToken(ChunkHeader); // { id, size } switch (chunkHeader.id) { case 'fmt ': { ...; return; } default: this.tokenizer.ignore(Number(chunkHeader.size) - ChunkHeader.len); break; // size<12 -> negative, no await } bytesRemaining -= chunkHeader.size; } strtok3 AbstractTokenizer.ignore (L78-79): if (length < 0) throw new RangeError('ignore length must be ≥ 0 bytes');
Steps to reproduce repro/ — public API only, Node's default unhandled-rejection mode, try/catch around the parse: npm install && node poc.mjs Confirmed on 11.14.0: [app] parseBuffer() RESOLVED — the caller saw no error to catch. RangeError: ignore length must be ≥ 0 bytes at DsfParser.parseChunks (.../lib/dsf/DsfParser.js:51) <process exits non-zero — the "process survived" line never prints>
Impact DoS: a single crafted .dsf (or any file with the DSD magic) crashes the Node process of any app parsing untrusted audio with music-metadata (2.2M weekly downloads). The crash bypasses the caller's error handling, so even apps that correctly try/catch per-file parsing are killed — one malicious upload can take down a shared server/worker.
Remediation Add await on line 51 (makes the RangeError a catchable parse error), and validate chunkHeader.size >= ChunkHeader.len before the skip (as the ASF fix did; also guards the loop counter). Audit other parsers for un-awaited tokenizer.ignore()/readToken().
Scope / honesty Requires the DSF path (a DSD -magic file — normal auto-detection). Relies on Node's default unhandled-rejection mode (throw, default since Node 15); the point is that the standard defensive per-parse try/catch does not protect against it. Crash (availability), not disclosure/RCE. Negatives confirmed alongside: ASF infinite loop fixed; negative-ignore infinite-loop class closed at strtok3; unbounded allocation bounded by strtok3's read bound-check.
Credits Issue also reported by @ryu7eroo
Other sources
music-metadata is a metadata parser for audio and video media files. Prior to 11.15.0, the DSF parser handles an unrecognized chunk by calling tokenizer.ignore without awaiting the returned promise and without first rejecting a chunk size smaller than the 12-byte chunk header. A crafted DSF input can produce a negative ignore length; with strtok3 10.3.5 or later, the resulting RangeError is detached from the parseBuffer promise and becomes an unhandled rejection under Node.js default behavior. The parse call can appear to resolve before the process crashes, bypassing per-parse try/catch handling. The demonstrated impact is availability loss only and requires the DSF parsing path. This issue is fixed in version 11.15.0.
— MITRE
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
npm/music-metadatato a version that resolves this vulnerability.Fixed in 11.15.0 - Upgrade
Upgrade
music-metadatato a version that resolves this vulnerability.Fixed in 11.15.0 - Compensating control
In DsfParser.parseChunks, await the tokenizer.ignore() call for unrecognized chunks and validate that chunkHeader.size is at least ChunkHeader.len (12) before skipping the payload, preventing negative ignore lengths and keeping the RangeError in the parseBuffer promise chain.
- Compensating control
Audit other parsers for un-awaited tokenizer.ignore() and readToken() calls.
Event History
Frequently Asked Questions
Which deployments are exposed to a process crash?
Deployments using music-metadata before 11.15.0 are exposed when they parse attacker-controlled or otherwise crafted DSF files. The issue requires the DSF parsing path and has demonstrated availability impact only.
What runtime condition affects the observed crash behavior?
The detached RangeError occurs with strtok3 version 10.3.5 or later. Under Node.js default behavior, it becomes an unhandled rejection, so the parse operation may appear to resolve before the process crashes.
Can application-level try/catch around an individual parse call prevent this failure?
No. The tokenizer.ignore promise is not awaited, which detaches the error from the parseBuffer promise; per-parse try/catch handling can therefore be bypassed.
What is the remediation?
Upgrade music-metadata to version 11.15.0, which fixes the DSF parser handling of unrecognized chunks and undersized chunk lengths.