Jul 22, 2026·7 min read·21 visits
Vulnerabilities in native library libvips permit denial of service and heap-based buffer overflows when parsing malformed image files via Node.js applications utilizing sharp.
The high-performance Node.js image processing library sharp inherits several high and medium-severity security vulnerabilities from its underlying native dependency libvips. These include integer overflows in dimensions calculation, heap-based buffer overflows in GIF/TIFF and JPEG2000 processing, and out-of-bounds reads in the EXIF directory decoder, enabling denial of service and potential code execution.
The native C/C++ image processing engine libvips serves as the foundational core for the popular Node.js library sharp. When sharp executes image operations such as resizing, parsing, and format conversion, it passes these tasks directly to libvips. Consequently, any memory safety or validation flaws inside the C/C++ codebase of libvips expose the host Node.js process to exploitation.
This security advisory tracks multiple severe vulnerabilities within libvips that directly impact sharp installations. These flaws encompass integer overflows leading to heap-based buffer overflows, out-of-bounds reads, and NULL pointer dereferences across multiple image parsers, including TIFF, GIF, and JPEG2000. These issues present significant risk to applications that process untrusted image uploads.
The vulnerability group is cataloged under GHSA-F88M-G3JW-G9CJ and includes four main CVE identifiers: CVE-2026-33327, CVE-2026-33328, CVE-2026-35590, and CVE-2026-35591. Because libvips is statically or dynamically linked by sharp, server-side Node.js environments processing malformed user-uploaded media files can face process disruption or unauthorized memory access.
An investigation of the vulnerability mechanics indicates distinct root causes across the affected libvips components. For CVE-2026-33327, the flaw lies in the vips_image_sanity function inside iofuncs/image.c. When evaluating image dimensions, the application performs direct multiplication of several size variables without checking for integer wraparound. An attacker providing exceedingly large dimension inputs causes the computed raw pixel memory size to wrap around a 64-bit unsigned integer, resulting in a small memory allocation followed by an out-of-bounds heap write.
For CVE-2026-33328, a similar integer overflow occurs in the NetSurf GIF loader (nsgifload.c) on 32-bit platforms. Since the GIF specification permits dimensions up to 65,535 pixels per axis, calculating the total memory required for an uncompressed 32-bit RGBA buffer can exceed the maximum range of a 32-bit integer, wrapping the allocation size to a negligible value or zero.
For CVE-2026-35590, the EXIF directory parser fails to validate directory indices. The function vips_exif_image_field reads index values directly from an EXIF tag format using the atoi function but fails to ensure that the resulting integer is within the valid bounds of the EXIF Tag Group arrays. A negative index or an index exceeding the maximum count triggers an immediate out-of-bounds read or pointer dereference.
Lastly, CVE-2026-35591 represents a container-to-stream structural mismatch during TIFF parsing with embedded JPEG or JPEG2000 tiles. The TIFF container specifies a low channel count, while the encapsulated JPEG stream contains three components. When the inner decompression routine allocates a buffer based on the container specifications but decodes all three stream components, a heap-based buffer overflow occurs.
To understand the vulnerabilities and their respective fixes, we can analyze the structural changes implemented by the libvips maintainers. In CVE-2026-33327, the unpatched codebase calculated the overall image buffer requirements via unsafe macros, allowing integer wrapping to go undetected. The remediation introduces the g_uint64_checked_mul macro to systematically validate each step of the size calculation.
Below is the code modification applied to libvips/iofuncs/image.c to prevent the overflow:
// Unpatched vulnerable path:
// sizeof_image = VIPS_IMAGE_SIZEOF_IMAGE(image);
// Patched safe path using glib checked multiplication:
if (!g_uint64_checked_mul(&ps, es, image->Bands) ||
!g_uint64_checked_mul(&ls, ps, image->Xsize) ||
!g_uint64_checked_mul(&sizeof_image, ls, image->Ysize) ||
(image->dtype == VIPS_IMAGE_SETBUF &&
sizeof_image > G_MAXSIZE - 16))
vips_buf_appends(buf, "dimension overflow\n");In the case of the GIF loader (CVE-2026-33328), the library now validates both the maximum permissible dimensions and the calculated 64-bit size of the resulting pixel buffer. This ensures that the memory allocation fits comfortably within a 32-bit space on limited architectures.
// Patched dimensions and bounds check inside nsgifload.c:
if (width <= 0 ||
width > 65535 ||
height <= 0 ||
height > 65535 ||
(guint64) width * height > INT_MAX / 4) {
vips_error("gifload", "%s", _("bad image dimensions"));
return NULL;
}For CVE-2026-35590, the EXIF parser was updated to explicitly constrain the parsed index prior to referencing the target array structure, preventing memory corruption or denial of service.
// Patched bounds validation inside exif.c:
ifd = atoi(p);
if (ifd < 0 || ifd >= EXIF_IFD_COUNT) {
g_warning("bad exif ifd %d in \"%s\"", ifd, field);
return NULL;
}Exploiting these issues requires an attacker to submit a malformed image file to a server endpoint that leverages sharp or libvips for processing. The attack flow starts with the remote delivery of a crafted image container, such as a GIF, TIFF, or image with malformed EXIF headers. The target application does not need to have specific administrative configurations, as any standard image processing endpoint is vulnerable.
If targeting the TIFF/JPEG component mismatch (CVE-2026-35591), the attacker builds a TIFF image whose outer container metadata specifies a single color band, while the internal JPEG scanlines actually contain three color components. During the decoding phase, the libjpeg decompressor tries to write all three decoded components into the target memory segment, which was only sized for a single channel. This mismatch causes a heap-based buffer overflow, corrupting adjacent heap structures.
For the EXIF-based out-of-bounds read (CVE-2026-35590), the attacker injects an EXIF payload containing an invalid directory index string such as exif-ifd-1 or exif-ifd9999. When the service parses the image metadata, the application reads memory out of bounds of the allocated EXIF structures, resulting in an immediate segmentation fault and process termination.
The impact of these combined vulnerabilities varies based on the target system architecture and specific deployment configurations. The most immediate and reliable outcome of exploiting any of these flaws is a complete Denial of Service (DoS) of the host application. Because Node.js operates on a single-threaded event loop, a native segmentation fault or an out-of-memory crash inside the libvips C++ worker pool instantly halts the entire Node.js server process.
For environments that do not utilize automated container restarts or process monitors, a single exploitation payload can result in prolonged application downtime. In high-availability configurations, continuous delivery of malformed payloads can lead to resource exhaustion as the system repeatedly spawns and crashes application instances.
Beyond Denial of Service, the heap-based buffer overflows present a high-severity threat of memory corruption and potential code execution. Although reliable remote code execution is difficult to achieve due to modern operating system protections, the ability to overwrite heap contents can lead to security bypasses. Out-of-bounds reads can also expose uninitialized memory contents containing sensitive session data or keys.
The primary and most effective remediation strategy is to upgrade the sharp npm package to a version that bundles libvips >= 8.18.2. Upgrading ensures that all native image parsers benefit from the safe multiplication routines, bounds checking, and channel mismatch validations.
In environments where upgrading the library is not immediately feasible, administrators should enforce strict input validation at the application boundary. Implementing file-size and dimension limits on the API gateway or reverse proxy can prevent abnormally large images from reaching the parsing engine.
Additionally, developers compiling libvips from source can choose to disable unused and highly complex image decoders. Disabling support for formats like TIFF or JPEG2000 during the configuration stage reduces the exposed attack surface without impacting core JPEG or PNG processing capabilities.
CVSS:4.0/AV:L/AC:L/AT:N/PR:L/UI:N/VC:L/VI:H/VA:H/SC:N/SI:N/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
libvips libvips | <= 8.18.1 | 8.18.2 |
sharp sharp | All versions linking dynamically or statically to libvips < 8.18.2 | sharp releases containing libvips >= 8.18.2 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-190, CWE-122, CWE-125 |
| Attack Vector | Local/Remote upload of crafted image files |
| CVSS Score | 8.5 |
| Impact | Denial of Service, Out-of-bounds Read, and potential Remote Code Execution |
| Exploit Status | PoC / Technical Analysis Stage |
| KEV Status | Not Listed |
Multiple flaws involving integer overflow, heap buffer overflow, and out-of-bounds read inside image processing components.
CVE-2026-12243 is a path traversal vulnerability in the Natural Language Toolkit (NLTK) version 3.9.4. The flaw exists because the input validation routine fails to account for percent-encoded directory traversal sequences like '..%2f' before passing them to urllib.request.url2pathname(), which decodes them into active traversal sequences.
CVE-2026-73654 is a high-severity prototype pollution vulnerability in Trigger.dev. The flaw occurs during the handling of run-metadata updates through the PUT /api/v1/runs/:runId/metadata endpoint. Because user-supplied keys are parsed directly by the @jsonhero/path library without sanitization, an authenticated attacker with low privileges can pollute the global Object.prototype. This causes database queries via Prisma ORM to fail validation and induces unhandled exceptions in the Prometheus metrics client, resulting in a process-wide denial of service.
CVE-2026-73559 is an uncontrolled resource consumption vulnerability in the vLLM engine, specifically within the /v1/completions API endpoint, allowing authenticated attackers to cause application-level denial of service via unbounded prompt arrays.
A critical security bypass vulnerability in Argo Workflows allows authenticated attackers with workflow submission privileges to bypass 'Strict' or 'Secure' template referencing restrictions. By injecting unvalidated fields into the nested ArtifactGC configuration, attackers can execute arbitrary pod patches, leading to host namespace escape and cluster-wide privilege escalation.
A Server-Side Request Forgery (SSRF) / Confused Deputy vulnerability has been identified in Pydantic AI UI Adapters (such as VercelAIAdapter). Under certain conditions, a malicious client can supply manipulated message history with provider metadata that forces the server to resolve files within privileged cloud environments (AWS S3, Google Cloud Storage) or model providers. This occurs because the adapters deserialize client-provided metadata structures directly into UploadedFile instances without validation, which are subsequently fetched using high-privilege server credentials.
A path traversal vulnerability in the optional dashboard server of atomic-agents-stack before version 1.1.0 allows unauthenticated remote attackers to read arbitrary files from the host filesystem.