Skip to content

music-metadata: uncatchable process crash parsing a crafted `.dsf` (residual of GHSA-v6c2-xwv6-8xf7)

Moderate severity GitHub Reviewed Published Aug 18, 2026 in Borewit/music-metadata • Updated Oct 8, 2026

Package

npm music-metadata (npm)

Affected versions

<= 11.14.0

Patched versions

11.15.0

Description

Summary

DsfParser.parseChunks skips an unrecognised chunk's payload with an un-awaited call:

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)

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

References

@Borewit Borewit published to Borewit/music-metadata Aug 18, 2026
Published to the GitHub Advisory Database Oct 8, 2026
Reviewed Oct 8, 2026
Last updated Oct 8, 2026

Severity

Moderate

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Local
Attack complexity
Low
Privileges required
None
User interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
None
Availability
High

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

EPSS score

Exploit Prediction Scoring System (EPSS)

This score estimates the probability of this vulnerability being exploited within the next 30 days. Data provided by FIRST.
(9th percentile)

Weaknesses

Uncaught Exception

An exception is thrown from a function, but it is not caught. Learn more on MITRE.

Uncontrolled Resource Consumption

The product does not properly control the allocation and maintenance of a limited resource. Learn more on MITRE.

CVE ID

CVE-2026-107392

GHSA ID

GHSA-8j4c-6x6g-rq3j

Credits

Loading Checking history
See something to contribute? Suggest improvements for this vulnerability.