GitHub Advisoryadvisory · npm

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

MEDIUM Published 2026-10-08 Modified 2026-10-08 Official page ↗
Aliases
CVE-2026-107392
Ecosystem
npm
Packages
music-metadata
Severity
Moderate
CVSS vector
CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Weaknesses
CWE-248, CWE-400
Reviewed
2026-10-08

Affected packages

• npm music-metadata: < 11.15.0 → fixed in 11.15.0

Description

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 negative, no await } bytesRemaining -= chunkHeader.size; } ``` strtok3 `AbstractTokenizer.ignore` (L78-79): `if (length ``` 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

Related

Alias · CVE (1)

  • CVE-2026-107392 music-metadata is a metadata parser for audio and video media files. vulnerability

Weakness · CWE (2)

  • CWE-248 Uncaught Exception weakness
  • CWE-400 Uncontrolled Resource Consumption weakness

References