Payload CMS Vulnerability: Is Your Vercel Template Still on 3.82.1? (2026)

Payload is the open-source CMS that installs straight into a Next.js app, and its "Deploy to Vercel" starter is one of the quicker ways to get a site with an admin panel live. On 2026-09-18 Payload published two remote code execution advisories, one of them scored CVSS 10.0, and shipped the fix in 3.90.0 the same day.

A month later, the official templates still pin the old version. We read templates/with-vercel-website/package.json on Payload's main branch on 2026-10-19: payload and all 13 @payloadcms/* packages are pinned to exactly 3.82.1, a release from April. So if you click Deploy today, your new site starts out vulnerable to both RCEs and an older SQL injection. Those three are the worst of it, not all of it: OSV lists 19 advisories against payload 3.82.1, and none against 3.90.2 or 3.91.0.

TL;DR

Payload below 3.90.0 has two RCEs: one through the form builder plugin (CVSS 10.0, no login needed) and one through the first-user signup that's open until you create an admin. The official Vercel templates pin 3.82.1 with no caret, so a site deployed from them stays vulnerable until you edit the pins. Check package.json, hit /api/users/init, then upgrade every payload and @payloadcms/* package to 3.90.2 or later.

What Payload disclosed

As of 2026-10-19, Payload's advisories say:

AdvisoryPackageWhat it isSeverityFixed in
GHSA-r488-j9vj-wx3q (CVE-2026-105857)@payloadcms/plugin-form-builderCrafted form submissions "execute remote code on the server"Critical, CVSS 10.03.90.0
GHSA-97rh-rhh2-7vjv (CVE-2026-105858)payloadRCE through the public first-register operation, only while no first user existsHigh, CVSS 8.13.90.0
GHSA-v49j-62m6-pgrr (CVE-2026-105845)payloadSQL injection on the SQLite and Postgres adaptersCritical, CVSS 9.83.88.0

Payload disclosed the two RCEs on 2026-09-18, the day 3.90.0 shipped with the note "This release contains a set of critical security fixes." The SQL injection advisory followed on 2026-09-22, but its fix had been on npm since 3.88.0 on 2026-08-11.

Neither RCE advisory explains how the exploit works. Both list prototype pollution (CWE-1321) and code injection (CWE-94) as the weaknesses. Payload wasn't in CISA's Known Exploited Vulnerabilities catalog as of its 2026-10-16 update, and we found no public proof of concept we could verify.

The same 3.90.0 release fixed two more Criticals that mostly don't apply to the starter: an unauthorized document update that needs orderable: true on a collection (GHSA-f7hx-52q9-hcrf), and an auth token issue that needs a custom field mapped to a reserved JWT claim (GHSA-66wr-7vmr-p5jq). The rest of the 19 are Highs and Moderates, many around uploads.

If npm audit stayed quiet about this for weeks, that's why. Payload disclosed them on 2026-09-18 and 2026-09-22, but they were only added to the GitHub Advisory Database and OSV on 2026-10-06 and 2026-10-07, about two and a half weeks later. A scanner that reads the advisory database couldn't flag them before then.

Why the template matters

The form builder RCE needs no login. In 3.82.1 the plugin's form-submissions collection allows anyone to create a submission, because that's what a public contact form is for. The Website Starter turns the plugin on in src/plugins/index.ts. So a site built from it has a public endpoint taking exactly the input the advisory says can be crafted.

The pins are the other half. They're exact, with no ^:

templates/with-vercel-website/package.json on main, 2026-10-19 (excerpt)
"@payloadcms/db-vercel-postgres": "3.82.1",
"@payloadcms/next": "3.82.1",
"@payloadcms/plugin-form-builder": "3.82.1",
"next": "16.4.2",
"payload": "3.82.1",

Exact pins mean npm update and pnpm update leave Payload where it is. The repo the Deploy button creates also has no Dependabot or Renovate config, so unless you've switched on Dependabot security updates yourself, nothing will open a pull request to bump it. The with-vercel-postgres, with-vercel-mongodb, with-postgres and with-cloudflare-d1 templates carry the same 3.82.1 pins. The website, blank and ecommerce templates use workspace:* instead, which create-payload-app resolves when it scaffolds a project.

This is the pattern we keep running into with starter-based apps: the template was secure the day it was written, the app went live, and nobody went back to the version numbers because nothing looked broken.

The two-minute check

1

Read your versions. Open package.json in your repo and find payload plus every @payloadcms/ line. Anything below 3.90.0 is affected by both RCEs, and anything below 3.88.0 by the SQL injection too if you're on Postgres or SQLite.

2

Check whether an admin exists. Payload exposes an init endpoint on every auth collection. The starter's collection is called users:

Is first-register still open?
curl https://yoursite.com/api/users/init
# {"initialized":false}  -> no user yet, first-register is open to anyone
# {"initialized":true}   -> an account exists; first-register is closed

If it says false, go to /admin and create your admin account before anything else. Payload refuses first-register once any user exists, which closes the second RCE even before you upgrade.

3

Check for the demo account. If you clicked the starter's "Seed the database" button, the seed script creates a user with the email demo-author@example.com and the password password. In the starter, every logged-in user can open the admin panel and manage other users, so on a live site that's an admin account with a public password. Log in, delete it or change its password, and check that nobody else has been added.

4

Look for a form builder. If @payloadcms/plugin-form-builder is in your dependencies, treat yourself as exposed to the CVSS 10.0 bug. The advisory's only stated condition is "You are using @payloadcms/plugin-form-builder".

How to upgrade

Bump every Payload package together. Mixing versions across payload and @payloadcms/* is a reliable way to break the build. With pnpm, which the template uses:

Upgrade all Payload packages to the same release
pnpm up --latest payload "@payloadcms/*"
pnpm payload migrate:create
pnpm build

--latest moves past the exact pins, to 3.91.0 as of 2026-10-19. The RCE fixes landed in 3.90.0, but take 3.90.2 or later: OSV lists no advisories against 3.90.2 or 3.91.0. Check that every Payload line in package.json ended up on the same number. The starter's Vercel build command is pnpm run ci, which runs payload migrate before building, so committing the new migration is enough for it to apply on deploy.

The 3.90.0 release notes list breaking changes. Three are likely to touch a starter site: relational databases need a migration (it adds a resetPasswordRequestedAt field, hence the migrate:create step above), form submission read access now defaults to the admin collection, and multipart uploads are capped at 50MB unless you raise requestSizeLimit. Deploy to a preview first and submit your contact form once.

If you can't upgrade today, the SQL injection advisory gives a workaround: stop untrusted users passing dynamic query filters or join parameters, and tighten read access on your collections. The RCE advisories list no workaround. Upgrading is the fix.

What to ask your AI tool

AI Prompt

Upgrade Payload safely

My Payload CMS project pins payload and @payloadcms packages to 3.82.1. Upgrade every payload and @payloadcms/* dependency in package.json to the same version, 3.91.0, and keep them identical. Then create and run a migration with the Payload CLI. Read the v3.90.0 release notes and list any breaking change that affects my collections, my form builder config or my uploads before changing code for it. Don't change any access control rules unless I approve the change.

What are the Payload CMS vulnerabilities fixed in 3.90.0?

Two remote code execution bugs, both published on 2026-09-18. GHSA-r488-j9vj-wx3q (CVE-2026-105857) lets a crafted submission to the form builder plugin run code on the server and scores CVSS 10.0. GHSA-97rh-rhh2-7vjv (CVE-2026-105858) does the same through the public first-register operation, but only while no first user exists. A third advisory, a SQL injection on the SQLite and Postgres adapters, was fixed earlier in 3.88.0.

Is the Payload Website Starter on Vercel vulnerable?

As of 2026-10-19, the with-vercel-website template on Payload's main branch pins payload and every @payloadcms package to exactly 3.82.1, which is below every fixed version. A project created from it starts on 3.82.1 and stays there until someone changes the pins.

How do I check which Payload version my site runs?

Open package.json in your repo and look at the payload line and every @payloadcms line. Anything below 3.90.0 needs the upgrade. If the version has no caret, nothing moves it until you edit it.

How do I know if my Payload site has no first user?

Request /api/users/init on your live site. If it returns initialized false, no admin account exists yet and the first-register endpoint is open to anyone. Create your admin account now, then upgrade.

Does the SQL injection affect MongoDB?

No. The advisory says MongoDB users are not affected. It covers the SQLite and Postgres adapters on payload 3.0.0 up to 3.88.0.

Find out what else your starter template shipped with.

Vulnerability Guides

Payload CMS Vulnerability: Is Your Vercel Template Still on 3.82.1? (2026)