osbytes

Search

Find posts, projects, and members.

← back to blog

React 19.2.7 fixes the security patch that silently emptied your Server Actions

2026-06-03by@osbytes5 min read
#react #nextjs #javascript #release #breaking-changes #web

TL;DR

  • Broke: React 19.2.6, Next.js 16.2.6. Fixed: React 19.2.7 (out Monday June 1), Next.js 16.2.7. Backports for the older lines: 19.1.8 and 19.0.7.
  • Symptom: a form wired to useActionState + a Server Action arrived empty server-side. The DOM looked fine, inputs had values, no error was thrown. formData.get(...) just returned null.
  • Cause: the DoS-hardening fix for CVE-2026-23870 changed how Server Function request payloads get deserialized, and the new path dropped FormData entries.
  • Detect: Server Action receiving a FormData that's empty when the form clearly wasn't. Add one log of [...formData.entries()] at the top of the action.
  • Doing the responsible thing, applying the security patch, is what broke form submissions. Silent data loss, not a crash.

What happened

React's 19.2.6 security release patched CVE-2026-23870, a denial-of-service hole in React Server Components. A crafted HTTP request to a Server Function endpoint could push the server into a high-CPU state or an out-of-memory exception, unauthenticated, repeatable. The advisory (GHSA-rv78-f8rc-xrxh) covers react-server-dom-webpack, react-server-dom-parcel, and react-server-dom-turbopack. Fix versions: 19.0.6, 19.1.7, 19.2.6. The only remediation was to upgrade. So people upgraded.

The hardening reworked how Server Function request payloads are deserialized — the part that turns an incoming multipart request back into the arguments your action receives. The new path tightened what it would parse. It also stopped reattaching FormData entries. So a form like this:

function Subscribe() {
  const [state, action] = useActionState(subscribe, null);
  return (
    <form action={action}>
      <input name="email" />
      <button>Subscribe</button>
    </form>
  );
}
"use server";
export async function subscribe(prevState, formData) {
  const email = formData.get("email"); // null on 19.2.6
  // ...
}

submitted normally. The browser serialized the fields. The server got a FormData object — just an empty one. formData.get("email") returned null, the action ran against nothing, and nobody got an exception to page on.

Why this one stings

A crash is loud. You get a 500, a stack trace, an alert. This was the quiet failure mode: the request succeeded, the action returned, the UI moved on. The damage shows up downstream as rows that never got written, settings that silently reverted, sign-ups that vanished. If your action validated the empty input and returned a clean "nothing to do," you wouldn't even see an error in logs.

It hit useActionState flows in particular — the React 19 form pattern Next.js docs point you toward. The Next.js report (#93754) confirms it reproduced in dev, in production builds, and on deployed apps, while next@16.2.2 and next@canary were clean. That canary-is-fine detail is the tell that this was a regression in the security release, not a long-standing bug.

The fix

React shipped 19.2.7 on Monday. The release note: "Fixed missing FormData entries in Server Actions which regressed in 19.2.6" (PR #36566). The fix was backported to the other security-release lines as 19.1.8 and 19.0.7, so you don't have to jump minor versions to get both the CVE patch and working forms. Next.js 16.2.7 picks up the corrected React.

What to do:

  • If you're on React 19.2.6 / Next 16.2.6 and use Server Actions with FormData, your form submissions were silently arriving empty. Upgrade to 19.2.7 / 16.2.7 (or 19.1.8 / 19.0.7 if you're holding an older line).
  • Don't roll back to dodge it — 19.2.5 / 16.2.2 still carry CVE-2026-23870. Roll forward.
  • Before you deploy the fix, grep the gap. Anything that hit your useActionState actions while you were on 19.2.6 may have processed empty input without complaining. Check whatever those actions write.
  • Going forward, a cheap guard: have Server Actions assert that required fields are present and throw (or return an error state) when they aren't, instead of treating empty as valid. An empty FormData should be a loud failure, not a no-op.

This is the same hardening wave as the HTTP/2 memory-exhaustion CVE we covered today: DoS fixes landing fast, with the downstream breakage showing up a release later. Patch velocity is the right instinct. Just budget for the regression that rides in with it.

Sources