Two critical Next.js vulnerabilities, patched in August 2026
In August 2026, two critical Next.js vulnerabilities were fixed in versions 15.5.24 and 16.3.3. Both allow an unknown party to run their own code on a server, with no password and no visible intrusion. What makes them worth a closer look, however, is their mechanism. Examining how they work reveals a part of the web that almost nobody sees, and gives a clearer picture of what actually runs a website, of everything hidden beneath its surface, and of the responsibilities that come with simply hosting it.
The two vulnerabilities follow paths that have almost nothing in common. One, identified as GHSA-2xp9-vwfh-vxw4, goes through an image and allows code execution via image optimisation. The other, referenced as CVE-2026-75604, comes down to the way a file path is written on Windows. Both nonetheless end in the same place, with an unknown party getting the server to run their own code.
This is the path we follow here, with the aim of understanding it rather than raising alarm. The subject also matters to us for a very practical reason. At Nualt, we build frontends with Next.js, and we see the framework appear more and more often in projects, particularly with the rise of vibe coding. The more accessible and popular a tool becomes, the more it is used by people who do not necessarily know the full technical depth it carries. Understanding what happens beneath its surface then becomes useful, even for those who do not work directly on security.
These two vulnerabilities are not isolated accidents either. In little more than a year, Next.js has already seen an authentication bypass with CVE-2025-29927, remote code execution at the core of React with CVE-2025-55182, and another flaw able to retrieve the access keys of a cloud infrastructure with CVE-2026-44578. That pace alone starts to tell a story.
How an image can execute code
A single image can be enough to compromise a server. It can look entirely ordinary, like the images uploaded every day, yet when an attacker crafts it for the purpose, it can exploit a flaw and give them control of the machine that processes it.
Put that way, it sounds almost absurd. Once the mechanism is examined closely, however, it all becomes fairly logical.

A crafted AVIF image reaches the server. The server hands it to sharp for optimisation, which in turn relies on libheif to decode it. The flaw is triggered at the moment of decoding.
What a website does with each image
It goes unseen, but an image displayed on a website can pass through a small factory before it reaches the screen. Next.js can receive it, resize it, recompress it and serve a different version depending on the device. This work is precisely what avoids sending a huge image of several megabytes to a phone that does not need it. The site loads faster, and usually nobody has any reason to think further about what just happened. To optimise an image, however, the program first has to open it, and opening a file already means asking a program to trust it enough to try to understand it.
This is where things become interesting.
The decoding chain, and its deepest link
Next.js cannot decode every image format on its own. It delegates part of this work to sharp, a library specialised in image processing. Sharp in turn relies on other, even more specialised components. For AVIF images, sharp notably uses the libheif library to read and decode the file. The result is several programs, written by different groups of developers, stacked on top of one another. The developer who chooses Next.js has probably never chosen libheif, has probably never read its code, and may well be unaware that it exists. It nevertheless runs on their server every time the chain needs it, and the flaw sits there, at the very bottom, in one of the layers that almost nobody looks at.
This is one of the most fascinating aspects of the vulnerability. The visible application does not need to be badly written. The defect can lie several layers deeper, in a component its developer has never heard of, and still reach all the way up to the whole server.
The trap, and the overflow
The attacker then takes an AVIF image and builds it in a very particular way. The aim goes well beyond making the image display incorrectly, since the attacker wants to provoke abnormal behaviour in the decoder at the very second it tries to read the file. To understand how an image leads to code execution, three moments need to be told apart.
It all starts with an error in the way the decoder estimates the memory it will need. Libheif reads the information contained in the file, estimates its size, then reserves an area large enough to work with it.
The crafted image is designed to skew this calculation. The decoder then allocates less memory than it actually needs, and starts writing into it the data it has just read.
At this stage there is indeed a vulnerability, though there is no takeover yet. If the data overflows in an unpredictable way, the most likely outcome is simply that the program crashes.
This is precisely where the most impressive part of the exploitation begins.
If the attacker has sufficient control over the content of the file and the behaviour of the decoder, this overflow can reach information that influences what the program does next. Exploitation then consists of using this memory corruption to divert the program's normal flow.
The step from overflow to code execution is therefore anything but automatic. It depends on the software version, on how its memory is organised and on the protections present on the server. Discovering that a program writes too far is a first step. Finding out how to turn that error into real control of the program is another, far more demanding one.
This is also what makes this type of flaw fascinating. Between "this image crashes the decoder" and "this image makes it possible to control its execution", there can be a considerable amount of understanding of the machine's inner workings.
curl -X POST https://exemple.fr/api/upload \
-F "image=@image-avif-piegee.avif"This command is not the exploit itself. It does not necessarily contain the instructions that will end up being executed, and it obviously does not work on just any website. It simply represents the gesture that carries the crafted file to the vulnerable component, in an application where such a route exists.
The rest happens because the server does exactly what is expected of it.
The disguise remains almost perfect since, seen from outside, only something entirely ordinary has happened, namely a website trying to process an image.
The flaw that comes down to one character
The second vulnerability is of a completely different nature and, in its own way, even more subtle.
This time the attack rests on a single character, with no tampered image, no memory overflow and no data hidden inside a file.
Someone wondered what would happen if a Windows backslash were used where Next.js mostly expected a forward slash. The question seems tiny. Followed far enough, it makes it possible to take the server out of the folder it should stay in, and then lead it all the way to code execution.
This attack is much more specific than the previous one, since it relies on a particularity of Windows. On Linux and macOS, the folders in a path are separated by a forward slash.
folder/subfolder/fileWindows also accepts the backslash.
folder\subfolder\fileThe whole flaw stems from this difference. Next.js and Windows did not give exactly the same meaning to the same path. A character the former did not consider dangerous could be perfectly understood by the latter as a way to navigate the server's folders.

A request containing a specially crafted file path gets past the filter of a Next.js server running on Windows. It can then leave the intended folder and lead the server to load a file it should never have reached.
The authorised room
To answer certain requests faster, Next.js keeps results it has already computed in a cache folder on the server's disk.
When a request arrives, it can therefore fetch a ready-to-serve file directly instead of redoing all the work. The boundary around this folder is essential, and to understand why, it helps to see where the cache sits in a fairly standard Next.js project.
my-project/
+-- app/
| +-- page.tsx
| +-- api/
+-- public/
| +-- images/
+-- .next/
| +-- cache/ <- allowed folder
| | +-- ...
| +-- server/
| +-- ...
+-- node_modules/
+-- .env
+-- package.jsonThis tree simply represents the project's folders and how they relate to one another. Above all, it shows that the cache is not isolated. A few levels away from it sit the application code, the dependencies, the files generated by Next.js and sometimes a .env file containing credentials for a database or external services.
The server must therefore be able to look for files in .next/cache without a request from outside being able to send it anywhere else.
The security of the whole mechanism rests on this boundary. Visitors can influence what the server looks for in the cache, and they must never be able to ask it to leave.
The path that leaves the room
Yet this is exactly what a path traversal makes it possible to attempt.
To find a result in its cache, Next.js builds a path from information contained in the request. Part of the path the server uses therefore depends on what the visitor sends. With a normal value, the server stays inside its cache.
.next/
└── cache/
└── page-contactFile paths have their own grammar, however. The sequence .. means moving up to the parent folder. By repeating it, a path that was meant to stay in the cache can be turned into one that climbs back up through the project.
.next/
└── cache/
└── ..\
└── ..\
└── .envThe server does start from the authorised folder. It is the path it is given that then tells it to step back, level after level. This technique has long been known as path traversal, and applications normally filter paths containing this kind of attempt before letting the system use them. Next.js did have this check.
The filter and Windows, however, did not read paths in exactly the same way.
The character that changes everything
This is where the backslash becomes interesting.
As we saw, Windows accepts \` as a separator between folders. The problem was that the protection in Next.js did not treat it as the equivalent of `/ in every case.
The attacker could therefore write the traversal with backslashes.
.next\cache\..\..\.envThe subtlety lies in what happens next.
Next.js filter
misses the traversal
|
v
Windows
reads \ as a folder separator
|
v
..\..
really moves up two levelsThe filter lets a path through because it does not correctly recognise its structure. A moment later, Windows receives exactly the same string and gives it its full meaning.
Windows reads the backslashes as separators and the .. sequences as instructions to move up the tree. The path that seemed acceptable at the time of the check then becomes a genuine exit from the authorised folder.
The entire exploit lies in that gap.
Leaving the cache is not enough on its own to execute code, however. It first gives the attacker a power they should never have had, that of leading the server to files located elsewhere in the tree.
The next step is to reach a file the attacker controls and that Next.js can then load as code. Under the vulnerable conditions, this traversal is exactly what links the two. The server leaves its cache, reaches a file prepared by the attacker, then loads it in a context where its content can be executed.
What sets this flaw apart
The technical chain is then complete.
The attacker does not break a decoder or manipulate memory directly. They exploit a disagreement between the Next.js filter and Windows over how to read a path, which is what makes the two flaws almost opposite in their method. In the first, an attacker has to build a file twisted enough to derail a decoder buried several layers below the framework. In the second, it is enough to play with a single character until a difference in interpretation between Next.js and Windows appears.
An important nuance should be kept in mind as well. This second vulnerability only affects Next.js servers running on Windows, which remains a rare configuration since the vast majority of web deployments run on Linux. It is therefore remarkable to study and much narrower in its impact, and that difference already hints at what comes next.
What these two flaws say about the web
The two vulnerabilities sat neither at the same level nor in the same type of component. The first was in libheif, a library used several layers below Next.js to decode AVIF images. The second concerned only Windows servers and stemmed from flawed handling of file paths by Next.js. In both cases, the starting point was almost invisible from the application. The developer worked with a framework, used an API for image optimisation or file handling, and could easily be unaware of the components actually carrying out those operations. Yet the flaw lay at that deeper level.
This situation has become normal in web development. An application rests on a framework, which relies on specialised libraries. Those libraries sometimes use other dependencies, which may in turn call system code or components written years earlier to meet a very specific need. Each layer brings a useful function, along with a new technical surface to maintain.
The AVIF flaw makes this depth particularly concrete. Nobody choosing Next.js selects libheif directly. Its name does not necessarily appear in the project's files, and its code generally stays out of sight of the developers building the application. Yet as soon as an AVIF image is processed, this library can come into play and take part in running the server.
This indirect dependency is not a defect in itself. It allows the work of specialists to be reused and spares every developer from writing their own image decoder, compression engine or system compatibility layer. This organisation is what allows complex applications to be assembled quickly from proven components.
This efficiency has a downside, however. The more layers an application depends on, the more serious the consequences of an error located far from its visible code can be.
Where you host changes your exposure
These two flaws then raise a far more practical question, namely who keeps track of this kind of problem once the site is live, and who steps in when a component of the stack becomes vulnerable.
The choice of hosting directly changes the answer. On a managed platform such as Vercel, part of this work is handled at the infrastructure level. In the case of the two vulnerabilities examined here, the AVIF optimisation concerned had been disabled before their public disclosure, and the Windows path flaw did not match the environment the platform uses. Sites hosted under these conditions therefore did not need to put in place a specific response to these two attacks themselves.
This arrangement obviously does not make the application invulnerable. A platform like Vercel cannot fix poorly designed authentication or a vulnerability specific to a project's business logic. It can, however, absorb part of the problems that directly concern the runtime environment, the components it operates and certain dependencies shared by its users. This is also part of what is delegated when choosing a managed platform.
With a server you run yourself, this intermediate layer disappears. Someone has to follow security alerts, determine whether they actually concern the installed versions and components, and then apply patches when needed. None of this is out of reach for anyone who knows how to administer their own infrastructure, though it remains an additional and ongoing activity. Above all, the difficulty of these two flaws shows that the information to monitor does not always come from an obvious place, since the vulnerable component may be an indirect dependency such as libheif or a very particular behaviour of an operating system.
This is where the hosting choice becomes less theoretical. Self-hosting brings more control and can offer real advantages in terms of cost or data control, which we covered in detail in our article on self-hosting versus PaaS. In return, it means taking direct responsibility for monitoring and maintaining the environment the application runs on. On a managed platform, part of this work shifts to the operator.
At Nualt
At Nualt, the choice between a managed platform and a self-operated server is therefore never made on principle. We look at the budget, the traffic, the constraints around data and the skills available around the project. We also look at what will happen after launch.
A server can be perfectly suited to a project at the design stage and become a poor choice if nobody is available to follow its updates, its dependencies and the security alerts that will appear in the years that follow. Conversely, a client who already has these skills in-house may have good reasons to want more control over their infrastructure.
This is why maintenance is part of the architecture decision from the start, and the two flaws we have just walked through show fairly well why. The problem to watch is not necessarily in the code you have written yourself. It can appear several layers further down, in a library whose existence was barely known, and still require action on the project.
Our role is therefore less to push systematically towards one solution than to choose an infrastructure consistent with the people who will actually look after it once the site is live.
Next.js, security vulnerabilities and hosting
The questions that come up most often when trying to work out whether these vulnerabilities affect your site, what they actually imply, and what the choice of hosting changes.
Should you stop using Next.js after these vulnerabilities?
No. Next.js remains a very widely used framework, and precisely because it is everywhere, it also draws a great deal of attention from security researchers and attackers alike. Seeing vulnerabilities reported is therefore not in itself proof that a framework is poor. What matters more is how they are discovered, fixed and deployed.
Is my site affected by the AVIF vulnerability?
Possibly, including on Linux, since this vulnerability does not depend on Windows. If the site uses a vulnerable version of the image optimisation chain concerned, it may be exposed. The fix is to install a version in which the vulnerability has been corrected.
Does the Windows vulnerability affect me?
Only if your Next.js application runs on a Windows server. This configuration remains relatively rare, since most web servers run Linux.
Does hosting on Vercel protect me from every vulnerability?
No. In the specific case of these two vulnerabilities, Vercel's infrastructure prevented their exploitation under the conditions described. That does not mean a managed platform makes an application invulnerable.
How can I tell whether my site is up to date?
If you work with a developer or an agency, you can ask them which version of Next.js is currently in use and whether the latest security patches have been applied. If you manage the application yourself, compare the installed version with the patched versions published by Vercel and follow the security advisories that apply to your environment.
