Back to All Articles
nextjssecurityreacttypescript

Fixing Critical Upstream Vulnerabilities in Next.js: RCE and DoS Patches

Learn how to patch critical RCE and DoS vulnerabilities in Next.js 16 and 15 by updating dependencies and securing server actions.

2026-10-30
Fixing Critical Upstream Vulnerabilities in Next.js: RCE and DoS Patches

Today we are looking at how to audit and patch critical upstream vulnerabilities affecting Next.js App Router applications, specifically tackling RCE risks in use cache functions, Image Optimization, and Server Action denial-of-service vectors.

What you'll learn:

  • How to update Next.js to patched versions (v16.4.1 and v15.5.28).
  • Why use cache functions returning typed arrays create unauthenticated RCE risks.
  • Validating your sharp library dependency for Image Optimization safety.
  • Mitigating CPU exhaustion vectors inside App Router Server Actions.

Upgrading Your Next.js Dependencies

The fastest way to eliminate upstream vulnerabilities in your project is bumping your Next.js version to the patched releases. Versions v16.4.1 (Active LTS) and v15.5.28 (Maintenance LTS) contain direct fixes for React and core package integration issues.

Run the appropriate install command depending on your current major version:

BASH
# For Next.js 16 projects
npm install next@16.4.1 react@experimental react-dom@experimental

# For Next.js 15 projects
npm install next@15.5.28 react@19 react-dom@19

Gotcha: If you use pnpm or yarn, make sure to check your lockfile to ensure transitive dependencies like sharp and React's upstream runtime packages resolve correctly without falling back to vulnerable cached versions.

Securing use cache and Typed Arrays

App Router features like use cache and Cache Components can expose your server to unauthenticated remote code execution if a cached function returns multiple typed arrays under specific upstream conditions.

If your application uses custom cache wrappers, inspect what data structures are returned:

TSX
import { cacheTag } from 'next/cache';

// Before: Returning raw typed arrays across cache boundaries can be risky
export async function getUnsafeCachedData(id: string) {
  'use cache';
  cacheTag(`item-${id}`);
  
  const buffer = await fetchBufferFromDatabase(id);
  // Unsafe if returning raw TypedArrays directly without serialization
  return new Float32Array(buffer);
}

// After: Wrap or serialize data into plain JSON-compatible objects
export async function getSafeCachedData(id: string) {
  'use cache';
  cacheTag(`item-${id}`);
  
  const buffer = await fetchBufferFromDatabase(id);
  const typedArray = new Float32Array(buffer);
  
  // Convert to regular arrays to avoid upstream deserialization flaws
  return {
    data: Array.from(typedArray),
    byteLength: typedArray.byteLength,
  };
}

Speed note: Serialization adds a minor CPU overhead, but it completely isolates your memory buffers from unsafe upstream parser execution paths.

Hardening the Image Optimization Pipeline

An upstream memory-related vulnerability in image processing libraries can lead to remote code execution when running Next.js on glibc-based Linux environments (like standard Docker containers).

While upgrading Next.js forces your package manager to resolve a safe version of sharp (0.35.5 or later), you should verify your installed versions explicitly:

JSON
{
  "dependencies": {
    "next": "16.4.1",
    "sharp": "^0.35.5"
  },
  "overrides": {
    "sharp": "^0.35.5"
  }
}

Tip: If you deploy inside minimal alpine images or custom distroless containers, verify that native binaries for sharp match your host architecture during build stages.

Preventing Server Action Denial of Service

Crafted requests hitting Server Actions in the App Router can trigger excessive CPU usage, blocking the Node.js event loop and causing a denial of service for other incoming requests.

You can mitigate payload abuse by validating request shapes early inside your actions using runtime validation libraries like Zod:

TSX
'use server';

import { z } from 'zod';

const ActionSchema = z.object({
  query: z.string().max(100, "Query too long"),
  cursor: z.number().int().positive().optional(),
});

export async function handleUserAction(formData: FormData) {
  const parsed = ActionSchema.safeParse({
    query: formData.get('query'),
    cursor: formData.get('cursor') ? Number(formData.get('cursor')) : undefined,
  });

  if (!parsed.success) {
    // Reject malformed or oversized payloads immediately before heavy processing
    throw new Error("Invalid payload structure");
  }

  // Safe processing logic
  const { query, cursor } = parsed.data;
  return await processSearchQuery(query, cursor);
}

Accessibility note: Ensure that when server actions throw validation errors, your client components catch them cleanly and announce the state change via aria-live regions for screen reader users.

Summary

Security updates in frameworks require swift action to protect production environments from upstream CVEs. By upgrading Next.js, verifying sharp versions, and strictly validating Server Action inputs, you keep your infrastructure safe.

Next Steps:

  • Run npm audit and check your package manager lockfiles immediately.
  • Deploy patched builds of your Next.js applications to staging and verify cache behaviors.
  • Implement strict payload validation on all active Server Actions.