The AVIF That Saved You Kilobytes Can Now Execute Code: Next.js's Critical Image RCE and Where to Decode
webdevelopment August 30, 2026 · Mintec

The AVIF That Saved You Kilobytes Can Now Execute Code: Next.js's Critical Image RCE and Where to Decode

On August 25, 2026, Vercel shipped Next.js 15.5.24 and 16.3.3 to fix GHSA-2xp9-vwfh-vxw4 — an unauthenticated critical RCE (CVSS 9.5) when the Image Optimization API processes AVIF files, caused by a heap buffer overflow in libheif. Why the patched releases disable server-side AVIF optimization, and why where you decode images is now a security decision, not a performance one.

The AVIF That Saved You Kilobytes Can Now Execute Code: Next.js's Critical Image RCE and Where to Decode

On August 25, 2026, Vercel shipped Next.js 15.5.24 and 16.3.3 to patch GHSA-2xp9-vwfh-vxw4: a critical (CVSS 9.5) unauthenticated remote code execution vulnerability in the Image Optimization API when it processes AVIF files. The root cause is a heap buffer overflow in libheif — the C library underneath sharp — and the patched releases disable server-side AVIF optimization entirely until libheif publishes its own fix. For web teams, the lesson is not to abandon AVIF: it's that deciding where images get decoded just turned from a performance decision into a security decision.

What actually happened

The failure chain has three links. Next.js uses sharp to optimize images on demand; sharp uses libheif to parse AVIF files; and libheif had a heap buffer overflow in its image scaling code. A crafted AVIF containing nested identity-derivation and auxiliary item references forces libheif to build a decoded image with two Alpha plane entries at different bit depths: the scaler allocates a destination buffer sized for the first 8-bit Alpha entry, then writes 16-bit sample values from the second entry into that buffer, overflowing roughly 16,384 bytes past the allocation boundary.

The researchers (rootxharsh as finder, KarimPwnz as coordinator, credited to the Hacktron team) published a full Python proof-of-concept alongside the upstream libheif advisory (GHSA-g89c-p67h-r497) and reported: "we were able to get RCE using this on multiple applications." The blast radius is wide: every libheif version through 1.23.1 is affected, which maps to Next.js 10.0.0 through 15.5.23 and all 16.x releases through 16.3.2. The fix is not instant, though: the patched Next.js releases disable AVIF optimization outright, and as of August 27, libheif had not yet published v1.23.2 to re-enable it safely.

One nuance significantly narrows panic: server-side AVIF optimization only runs if your next.config.js explicitly includes formats: ['image/avif']. Without that config, Next.js never routes your images through the vulnerable decoder. And if your app is hosted on Vercel, the platform absorbs the mitigation — Vercel stated that applications on its network do not require an upgrade. The same release also patched a second critical, CVE-2026-75604 (CVSS 9.0), a path traversal affecting Windows filesystem deployments — out of our scope, but the image one is squarely in it.

Why this matters well beyond Next.js

Because the sharp + libheif + AVIF trio doesn't live only in Next.js. It's in image-resizing serverless functions, Open Graph generators, media pipelines that downscale AI-generated output, and any microservice that accepts an image URL and returns an optimized file. Anywhere a server decodes an AVIF it doesn't control is, as of August 25, a potential code-execution surface.

And here's the irony that hits us directly: we've spent months recommending AVIF. In our migration post covering three client sites moved to AVIF we documented 40-60% reductions in image payload weight and LCP improvements of 300-800 ms. AVIF is still the right format for 2026 — 30-50% better compression than JPEG, per the same caniuse and Morphix Tools analysis we cited there. What changed is the risk attached to one specific architecture: decoding untrusted files in an exposed, long-lived server process.

Nobody should conclude "AVIF was the trap." The right conclusion is more uncomfortable: the format you chose for performance now defines part of your attack surface, and that surface is determined by where you decode — not which format you use.

Where to decode: the matrix we use at Mintec

On the projects we migrated to Astro + Cloudflare, the decision was structural: images are compressed at build time and served as static files from the edge. There is no server process that receives arbitrary URLs and decodes whatever arrives. That became obvious when this advisory landed: our pipeline simply didn't contain the attack path, because the decoder is unreachable by untrusted input.

ArchitecturePerformanceAttack surfaceRisk with AVIF today
Build-time + static CDN (Astro SSG, Next.js output: export)Optimal: zero runtime work, global edge cacheMinimal: the decoder never accepts user inputLow — the file you serve was validated at build
Edge/Workers resize-by-query (Cloudflare Image Resizing, Vercel Edge)Very good: edge caching, no origin hitMedium: decodes user input, but inside an ephemeral sandboxMedium — the sandbox limits damage, the overflow still exists
On-demand server optimization (traditional Next.js next/image, sharp in Node)Good, with CPU cost per new imageHigh: persistent process, input fully attacker-controlled (URLs and headers)Critical — exactly the GHSA-2xp9-vwfh-vxw4 case
Client-side decoding (<picture> with native AVIF)Depends on the visitor's deviceNone server-side; risk moves to the browserLow — the browser model since 2020

The rule we apply from now on: the image decoder should live where untrusted input cannot reach it — build time, a sandboxed edge, or the visitor's browser. A Node server running sharp and answering image requests isn't "optimization"; it's a door with attacker-controlled code on the other side.

What to do today (checkable checklist)

  1. Audit your config. grep -r "formats" next.config.* on every Next.js project. If image/avif appears, the attack path is live and you need the patch — not a WAF, not a promise that "we don't receive weird files." Attackers don't need to upload anything: just a URL pointing at an AVIF they control.
  2. Patch now. npm install [email protected] (or 15.5.24 on the LTS line) and run the 24-hour runbook we documented for scheduled security releases: staging first, image-optimization smoke tests, lockfile verification. The advisory is public since August 25; the PoC is public; the patch window is already open.
  3. Don't re-enable AVIF in next/image until libheif ships its fix. The patched releases disable it by design. If you want server-served AVIF, serve pre-compressed static files (the exact pattern from our three migrations) or use an edge resizing service.
  4. Hunt for sharp/libheif outside Next.js. Resize serverless functions, OG-image generators, video pipelines extracting frames — any process decoding untrusted AVIF with a sharp build that bundles libheif < 1.23.2 has the same problem. Run npm ls sharp and check the bundled libheif version.
  5. Add defense layers. The principle we already apply with Trusted Types and CSP applies to images: no single patch makes you invulnerable; an architecture limits what a malicious input can touch. Restrict remotePatterns in next/image to domains you control — never leave the optimizer open to arbitrary URLs.

The architectural decision this advisory confirms

We've spent months arguing for static content architectures: our Astro vs Next.js benchmark analysis already showed most content sites don't need a server runtime, and our six-month Astro + Cloudflare experience report confirmed performance isn't sacrificed — it's gained. What we hadn't fully priced in is that patch surface is architecture too: every runtime you add is a decoder, parser, or router someone will try to break.

This week is not about AVIF. It's about the realization that server-side image optimization — the practice we adopted a decade ago to "improve performance" — now looks less like compressing files and more like executing third-party code on your machine. The most honest security advice we can give: if your site is content, don't keep a server that decodes images; and if you must, treat it for what it is — a service with untrusted input, immediate patching, and active monitoring.

The AVIF that saved you kilobytes is still the right decision. What's no longer negotiable is deciding where you decode it.

Frequently Asked Questions

What does the critical Next.js AVIF vulnerability (GHSA-2xp9-vwfh-vxw4) fix?

A heap buffer overflow in libheif, the C library used by sharp, which Next.js uses for image optimization. A crafted AVIF can write ~16 KB past the buffer when scaling and achieve unauthenticated remote code execution (CVSS 9.5). Fixed in Next.js 15.5.24 and 16.3.3, published August 25, 2026.

Is my Next.js site exposed to the AVIF RCE?

Only if you use next/image server-side optimization and explicitly added image/avif to the formats array in next.config.js. Without that config, AVIF is not optimized on the server and the vulnerable path is not reachable. Applications hosted on Vercel are protected.

Should I stop using AVIF?

No. AVIF is still the best compression format (30-50% lighter than JPEG). What changes is where you decode: avoid decoding untrusted files on the server with sharp/libheif until libheif ships the fix (v1.23.2), and serve pre-compressed AVIF as static files or from a CDN instead.

Related Articles