DEV Community

MacroCyber
MacroCyber

Posted on Originally published at macrocyber.co

84% of abandoned v0 apps run a known-exploited Next.js

A field note on what happens to AI-built apps after the builder walks away, measured on October 21, 2026, the day Next.js 15 left security support.

Of 274 abandoned v0-built apps whose Next.js version we could read, 231 (84%) declare a version inside the React2Shell range, the remote code execution flaw CISA has listed as actively exploited since December 5, 2025. 226 of them run the exact same version: Next.js 15.2.4. Only 3 run Next.js 16, and none runs the current patched release.

The date matters for a second reason. Next.js 15 was released on October 21, 2024, and the Next.js support policy keeps a major in Maintenance LTS for two years. Since October 21, 2026, the policy sends security fixes to Next.js 16 only. That leaves 271 of the 274 apps on a major outside its support window, on top of the 231 already in a known-exploited range.

This note explains how we measured it, why so many apps landed on one version, what the numbers do and do not prove, and what to do if one of these apps is yours.

1. What we measured

We wanted apps that were generated by an AI builder, deployed, and then left alone. v0 makes that population easy to find without guessing: projects it syncs to GitHub carry a recognizable notice in their README. We searched public GitHub repositories with that notice, created between January and August 2025, whose last push was before October 1, 2025, and that list a live homepage. That gave 398 apps, each untouched for more than a year.

For each one we fetched the homepage and the JavaScript files it links, exactly what any visitor's browser downloads. An App Router build of Next.js declares its own version in that code (a line of the form window.next = { version: "15.2.4", appDir: true }), and that self-reported version is what we recorded. We sent no exploit, no crafted request and no login attempt, and we are not publishing any app's address.

Result Apps
Sampled (v0 notice, created Jan to Aug 2025, no push since Sep 30, 2025) 398
Still serving a page 304
Next.js version readable from the served code 274
Version inside the React2Shell range (CVE-2025-55182, on CISA KEV) 231
On Next.js 14, out of support since October 2025 39
On Next.js 15, out of support since October 21, 2026, already patched for React2Shell 1
On Next.js 16, the only supported major 3
On the current patched release (16.4.2) 0

The other 94 apps were gone or unreadable: 69 answered 404 (a deleted deployment), 7 answered 402 (a paused Vercel project), and the rest timed out, no longer resolved, or ran a build whose version we could not read.

2. Why one version dominates: the exact pin

The concentration on 15.2.4 is not a coincidence, and it is not about people choosing an old version. We opened the package.json of sampled repositories, and the generated projects of that period declare "next": "15.2.4" with no range operator. An exact pin means a fresh install, a rebuild or a redeploy all produce the same 15.2.4 forever. Nothing upstream can move the app forward. Only a person editing that line can.

That turns a normal software habit into a trap. In a hand-maintained project, an exact pin is a deliberate choice somebody revisits. In a generated project, it is a snapshot of the day the model wrote the file, and the builder who accepted it usually never opened package.json at all. The 35 apps on 14.2.16 show the same pattern from an earlier template: one version, pinned, frozen.

Then the builder moved on. Every app in this sample was created in a burst of experimentation in 2025 and has not received a single commit in over a year. The deployment kept running anyway, because hosting a small app costs nothing and nobody turns it off. The app outlived the attention of the person who made it, and the version it was generated with became its permanent version.

3. What React2Shell is, and what the numbers do not prove

CVE-2025-55182, known as React2Shell, is unauthenticated remote code execution in React Server Components, which the Next.js App Router uses. It affects every Next.js 15 release line and 16.0 until that line's patch (15.2.6 for the 15.2 line), and CISA added it to its Known Exploited Vulnerabilities catalog on December 5, 2025. Its one precondition, the App Router, is stated on the same line as the version we read, which is why a version in range is a meaningful signal and not a guess.

It is still not proof that any of these apps can be compromised today, and we want to be precise about why:

  • Most of these apps sit behind Vercel's firewall. 266 of the 274 are hosted on vercel.app, where Vercel deployed firewall rules against React2Shell for every project. Vercel itself says those rules cannot guarantee protection against all possible variants of an attack and that upgrading is the fix, and researchers have found ways around some WAF defenses. A firewall rule is a mitigation in front of vulnerable code, not a patch to it.
  • The version is self-reported. It is what the served code declares, which is the version that was built. We did not test whether the flaw can be triggered, and we will not.
  • The sample is v0 projects on public GitHub. Builders who kept their repositories private, or who used other tools, are not in it. We think the mechanism (exact pins plus abandonment) generalizes, but the 84% figure describes this population.

What the numbers do show is the gap between how long an AI-built app keeps running and how long anyone maintains it. The fix for React2Shell has existed for more than ten months, and 84% of this population never received it.

4. The second problem started on October 21

Even the apps outside the exploited range are not in a safe place. Next.js 14 left its support window in October 2025, and 37 of the 39 apps on it run a version below the fix for the March 2025 middleware authorization bypass, which matters for any app that checks sign-in in middleware.

Since October 21, 2026, Next.js 15 joins it. The October 14 security release, two critical fixes and one high, was the last that 15.x was owed under the support policy. Vercel has made exceptions for severe flaws before (it shipped 14.2.35 in December 2025, after 14 had left support), but an exception only helps an app that installs it. A pinned, abandoned app misses every patch equally: the ones that ship for its line and the ones that never will.

5. If one of these apps is yours

The cheapest fix is often the right one. An app you no longer use should not be running. Delete the deployment or pause the project, and the exposure is gone along with everything else it might hold (an API key in its code, a database it still talks to).

For an app you want to keep:

  • Upgrade Next.js to 16. The official upgrade guide covers the breaking changes, and a codemod handles most of them. A generated app is usually small enough that this takes minutes, not days.
  • Replace the exact pin with a range ("next": "^16.4.2"), so a rebuild picks up patch releases.
  • Turn on automated dependency updates (Dependabot or Renovate) in the repository, so the next advisory arrives as a pull request instead of as nothing.
  • Check what the live app actually serves, not what you remember deploying.

MacroCyber reads the Next.js version an App Router site serves and flags it when it falls inside a range CISA lists as exploited, as a signal to verify, alongside the AI-era exposures it was built for (open Supabase and Firebase databases, leaked AI keys, exposed MCP servers). You can scan any site free, or give your coding agent the same check with our MCP server so it can scan what it just deployed and confirm its own fix. If your app runs on Supabase, the Supabase exposure check covers the other common way abandoned AI-built apps leak.

6. Method details

  • Population: public GitHub repositories whose README carries v0's sync notice, found through GitHub's repository search, one query per creation month from January to August 2025, restricted to repositories last pushed before October 1, 2025 and listing a homepage. Four repositories that had been pushed after that date by the time we read them were excluded.
  • Reading: one GET of the homepage and of the Next.js JavaScript files it references, with a user agent naming MacroCyber, on October 21, 2026. The version is the one the App Router runtime declares in the served code.
  • Matching: versions were matched with the same advisory table the MacroCyber scanner uses, so the article and the product cannot disagree.
  • Publication: aggregate figures only. No app is named.

This note reflects data read on October 21, 2026. Versions, hosting protections and support dates change, so check the current Next.js advisories before acting on any single figure.


Originally published on macrocyber.co. Written with AI assistance from data we collected on October 21, 2026, and checked against it.

Top comments (0)