Tutorial

Next.js 16.4.1 and 15.5.28: patch the RCE flaws on a VPS

Security & Monitoring9 min read10 steps

On October 14, 2026, Next.js shipped an out-of-band update: 16.4.1 and 15.5.28. It fixes two critical remote code execution flaws that need no account, plus a denial of service. On a VPS, no platform updates your application for you: you raise the version, check the lockfile, rebuild and restart the right process. A Docker redeploy can even replay a cached layer and put the old version back into production. Here is how to find out in ten minutes whether you are exposed, how to update, and how to prove the fix is really running.

Contents· What was published on October 141/13
  1. 01What was published on October 14
  2. 02Key points
  3. 03Without use cache or SVG, why that is not enough
  4. 04Which version to install for your line
  5. 05Find out what is really running
  6. 06Take inventory in five checks
  7. 07Update, then check the lockfile
  8. 08Redeploy for your target
  9. 09If you cannot redeploy today
  10. 10Temporary mitigations, not fixes
  11. 11Run npm audit after updating
  12. 12After the fix: monitor and plan for the 15 line
  13. 13Official documentation

What was published on October 14

On October 14, 2026, the Next.js team published an out-of-band security update: version 16.4.1 for the Active LTS line and version 15.5.28 for the Maintenance LTS line. It fixes three flaws tied to upstream dependencies: two critical, unauthenticated remote code executions and one high-severity denial of service. Two of these fixes had been postponed from the September release because of upstream delays.

On a server you administer, the fix does not arrive on its own. You must raise next, check that the sharp library follows, rebuild the application and restart the process that actually serves traffic. This article walks that path for PM2, Docker and Coolify, without redoing a Next.js server installation.

Key points

  • GHSA-673q-mjm6-r5xr (critical) — unauthenticated remote code execution in an App Router application with Cache Components, when a use cache function returns several typed arrays. No known workaround. The advisory gives the range 16.0.0 to 16.4.0 and a CVSS score of 9.5.
  • CVE-2026-96889 / GHSA-2464-fhr4-w9xw (critical) — remote code execution through an upstream library of the image optimization API, when SVG files are used, on glibc-based Linux. Score of 9.5. Official workaround: sharp 0.35.5 or later.
  • GHSA-p3m5-59mp-jv5r (high) — denial of service in an App Router application with at least one Server Action: crafted requests saturate the CPU and block later requests in the same process. Score of 8.2. The Pages Router, or an app without Server Actions, is not affected.
  • Fixed versions — 16.4.1 for the 16 line and 15.5.28 for the 15 line, with the official commands npm install [email protected] and npm install [email protected].
  • No CVE for two advisories out of three — only the image RCE carries a CVE identifier. The other two are tracked by their GHSA identifier: a tool that only looks for CVEs will miss them.
  • Even without direct use — for the use cache RCE, Vercel asks you to update even if your application has no similar function.

Without use cache or SVG, why that is not enough

Three reasons not to stop at that objection. First, for the use cache RCE the announcement is explicit: no workaround exists, and the update is requested even when the application has no similar function. Second, the image RCE depends on an upstream library, and you do not always know which SVG files reach the optimizer, especially when images come from remote sources. Third, the denial of service needs only one Server Action, which many App Router forms already contain.

The risk of breakage is limited: the upgrade stays within the same line, 16.4.x or 15.5.x. One constraint to know: version 16.4.1 declares Node 20.9 or later, while 15.5.28 accepts Node 18.18 and above. If you run an older 16.x, moving to 16.4.1 stays within the same major version.

Which version to install for your line

Scroll the table

Your versionStatusWhat to do
16.0.0 to 16.4.0Affected by all three advisoriesMove to 16.4.1 or to a newer 16.4.x
16.4.1 and laterFix includedCheck sharp and the real redeploy
15.0.0 to 15.5.27Affected by the image RCE and the DoSMove to 15.5.28, then plan the migration to 16.4.x
15.5.28Fix includedPlan the migration to 16.4.x
13.x and 14.xAffected, no fix published for these linesMigrate to 15.5.28 or 16.4.1
10.0.0 to 12.xAffected by the image RCE, no fix publishedMigrate to a maintained line

Find out what is really running

The version written in your repository is not the one answering requests. A lockfile may predate the fix, a Docker build may reuse a cached layer, a PM2 process may point to an old release directory. With the standalone output, Next.js copies the files it needs from node_modules into the deployment folder: the bundled sharp is therefore the one present at build time, not the one you installed afterwards. The following checks run on the machine or in the container that serves traffic.

Take inventory in five checks

  1. Read the Next.js and sharp versions

    From the project root: npm ls next sharp, or pnpm why sharp with pnpm. For the exact Next.js version: node -p "require('next/package.json').version". A sharp below 0.35.5 under next needs fixing.

  2. Spot Cache Components and use cache

    grep -rn "cacheComponents" next.config.* then grep -rln "use cache" app src. If cacheComponents does not appear, your application does not take the path described in the advisory. Update anyway: Vercel asks for it in every case.

  3. Spot SVG usage

    grep -rn "dangerouslyAllowSVG\|remotePatterns" next.config.* and find public -name "*.svg". By default, the documentation says Next.js does not optimize SVG images, and that dangerouslyAllowSVG allows them. A missing setting is a good sign, not proof: the advisory does not detail the exact path.

  4. Spot Server Actions

    grep -rln "use server" app src. A single file is enough to make an App Router application subject to the denial of service.

  5. Identify the system C library

    ldd --version prints GNU libc on Debian, Ubuntu, AlmaLinux or Rocky, and musl libc on Alpine. The advisory only mentions glibc and says nothing about musl: do not conclude that Alpine is spared. In a container: docker exec <container> ldd --version.

Update, then check the lockfile

Run the command for your line: npm install [email protected] or npm install [email protected]. One trap remains that the announcement does not detail. Version 16.4.1 declares sharp as an optional dependency with the range ^0.35.5, but 15.5.28 declares ^0.34.3 || ^0.35.5. A lockfile that already holds a 0.34.x satisfies that range: the package manager has no reason to raise it.

So check the result with npm ls sharp. If it shows a version below 0.35.5, force the upgrade with npm install sharp@^0.35.5, or add an override in package.json, for example "overrides": { "sharp": "^0.35.5" }. With pnpm or yarn, the equivalent is to raise sharp or declare an override. Commit the lockfile: it is what your CI and your Docker image will read.

Redeploy for your target

  1. Validate the build

    npm ci, then npm run build, then npm ls next sharp. If the build fails on Node, check the version required by the line you chose.

  2. PM2

    Build in the directory PM2 runs, then pm2 reload <name>. Then check with pm2 describe <name> that the execution directory is the one you just rebuilt: with a releases layout, a forgotten symlink restarts the old code.

  3. Docker

    Rebuild without cache: docker build --no-cache -t myapp:fixed ., or at least invalidate the npm ci layer. Restart with docker compose up -d --force-recreate. Then compare the running container image (docker inspect -f '{{.Image}}' <container>) with the one you just built.

  4. Coolify

    Trigger a redeploy that ignores the build cache, then read the log: the dependency installation step must run, not be marked as reused. A simple restart rebuilds nothing.

  5. Prove the fix

    Read the version in the running process, not in the repository: docker exec <container> node -p "require('next/package.json').version" must print 16.4.1 or 15.5.28 (or a newer version of the same line). Check sharp with docker exec <container> grep '"version"' node_modules/sharp/package.json, which must show 0.35.5 or later.

If you cannot redeploy today

For the use cache RCE there is no workaround: only the update fixes it. For the other two flaws, a few mitigations reduce the risk in the meantime. They do not replace the fix, and you should record them as temporary in your operations log.

Temporary mitigations, not fixes

  • Raise sharp alone — this is the official workaround for the image RCE: sharp 0.35.5 or later. Check that the build passes and that image optimization still works.
  • Do not serve SVG through the optimizer — leave dangerouslyAllowSVG disabled and do not enable it without a proven need.
  • Restrict images.remotePatterns — limit the remote sources the optimizer accepts to hosts you control.
  • Node as a PIE executable — the sharp advisory cites this mode to reduce the risk of code execution, noting that official Node.js binaries are not PIE.
  • Reduce possible damage — a process without root rights, a read-only container (docker run --read-only), no unnecessary secrets in the environment.
  • Rate-limit in front of Next.js — a limit_req rule in nginx and a CPU alert slow down a denial of service without preventing it.

Run npm audit after updating

npm audit relies on the GitHub advisory database: it therefore covers GHSA identifiers, including those with no CVE. Run it after the version bump, and add it to your CI so that the next advisory does not depend on manual monitoring.

After the fix: monitor and plan for the 15 line

The advisories publish no indicator of compromise, so there is no precise signature to search for. Watch for general signs. A Node process whose CPU stays saturated points to the denial of service. Unexpected restarts, child processes the application never starts, or outbound connections from the application user warrant an investigation. In nginx logs, grep "_next/image" access.log | grep -i svg shows optimization requests that target SVG files.

On the 15 line, be careful with the calendar. According to endoflife.date, security support for the 15 line ended on October 21, 2026, while the Next.js policy page gives no date and sets two years of Maintenance LTS. 15.5.28 may therefore be the last fix of that line: plan the migration to 16.4.x. Version 16.4.2, published the day after 16.4.1, contains according to its notes only backports unrelated to these advisories.

Official documentation

Next.js announcement of October 14, 2026: https://nextjs.org/blog/nextjs-security-update-october-14-2026

GitHub advisories: https://github.com/vercel/next.js/security/advisories/GHSA-673q-mjm6-r5xr, https://github.com/vercel/next.js/security/advisories/GHSA-2464-fhr4-w9xw and https://github.com/vercel/next.js/security/advisories/GHSA-p3m5-59mp-jv5r

sharp advisory: https://github.com/lovell/sharp/security/advisories/GHSA-wq5f-xc86-pv6w

Netlify note: https://www.netlify.com/changelog/2026-10-14-nextjs-react-security-vulnerabilities/

Support policy: https://nextjs.org/support-policy and https://endoflife.date/nextjs

Keep control of your redeploys

On a ServOrbit.com VPS you get root access, a dedicated IPv4 and your choice of OS: Node, Docker and the timing of each redeploy stay in your hands. A VPS administration option also exists; its scope is described on the offer page.

Need help?

Browse our help center and FAQ, or reach our team — callback, WhatsApp or email. Support in French, English and Arabic.

Message us on WhatsAppopens in a new tab