VelifyGet early access
← All postsJun 12, 2026

How users give themselves a free paid plan in one request

AI saves the whole request body, so a user can add is_premium or role:admin and grant it to themselves. No payment, no permission. The one-line fix.

How users give themselves a free paid plan in one request

You asked AI for a “save profile” endpoint. You change your name, it saves, you shipped. What you actually shipped lets a user flip themselves to a paid plan — or an admin — in a single request.

What you shipped

The handler takes the request body and writes it straight to the database.

Spot the bug

It saves whatever you send. The form only shows “name” and “avatar,” so it feels safe — but the API doesn’t care what the form shows.

How anyone exploits it

A user opens devtools, finds the save request, and adds a field that the form never displayed:

{ "name": "Jin", "is_premium": true, "role": "admin" }

Now they’re a paying customer who never paid, or an admin who was never granted access. Nothing crashes. Nothing looks wrong. Your upgrade button just became optional.

Why you won’t catch it in testing

You test through the UI, and the UI only sends the fields it shows. The extra fields only appear when someone bypasses the form and talks to the API directly — which is exactly what an attacker does and a normal test never does.

Why AI does it

Passing the whole object to update() is the shortest code that satisfies “save the profile.” The fields it quietly lets through — is_premium, role, user_id — are precisely the ones a user should never be able to set.

The fix is one line

Never trust the whole body. Pick the fields yourself:

The fix

const { name, avatar } = await req.json()
await db.users.update({ name, avatar }).eq('id', user.id)

Now extra fields in the request are simply ignored.

Check your app

  • Every create/update that accepts a request body whitelists the fields it writes.
  • Privileged fields (role, is_premium, plan, is_verified, user_id, id) are never settable from client input.
  • Ownership (user_id) is set from the session, never from the body.

The bigger problem

A senior dev whitelists update fields by habit. But if nobody senior reads the code, the “save the whole object” version ships — it works in every test, because every test sends the well-behaved fields. The author and reviewer are the same model with the same blind spot.

That’s the gap Velify is built to close: it reads your project and flags exactly this, in plain language, no terminal.

Join the early list at getvelify.app →

Ship AI-built code with confidence.

Velify catches what a senior developer would — before you ship.

Get early access →
Velify© 2026 Velify. All rights reserved.