A profile edit made someone admin

In this controlled demo, a regular user edits their display name, but the request also carries "role": "admin" and the server saves every field it receives.

Technical name: Mass assignmentControlled demo · fake data

Can a user make themselves admin through a profile update?

Yes, if your profile update saves every field it receives. A user can add an extra field such as role: admin to the request, even if your form doesn't show it. The fix is an allowlist: save only the fields users may edit, and change roles in a separate admin-only action.

How to tell if your app has this

No code needed.

  1. Ask your AI tool: "Which fields does my profile update endpoint accept and save? Does it copy the whole request body into the database?"
  2. Look for code that passes the whole request body to an update, such as update(req.body) or spreading it into the record.
  3. Check that role, plan, credits and similar fields can only be changed by an admin action.

Before and after

Before
PATCH /profile {"display_name": "Alex", "role": "admin"}
SAVED USER RECORD
ROLE:
ADMIN

One extra field in the request. Saved role: admin.

After
PATCH /profile {"display_name": "Alex", "role": "admin"}
SAVED USER RECORD
ROLE:
MEMBER

Same extra field. The account stays a member.

Why AI-built apps end up with this

Saving the whole request body is the shortest code that makes an edit form work, and it keeps working when you add new fields. The danger is invisible in the app, because the form never shows the fields that shouldn't be editable.

Fix it yourself

How do I fix it? Paste this into your AI tool

My profile update endpoint saves every field the client sends into the user record, so a user can send role: admin. Change it to an allowlist: only accept the fields a user may edit (for example display_name and avatar), ignore everything else, and move role and permission changes to a separate endpoint that only admins can call.
Works with Lovable, Bolt, Cursor, Replit and similar tools. Then run the check-up below on your own app.

How we checked the fix

Same request before and after the fix
Same requestBeforeAfter
Profile update with "role": "admin"Role became adminRole stays member
Normal display name changeNot testedSaved

Results from our demo test, run against the same demo before and after the fix.

Common mistakes when fixing this

  • Hiding the role field in the form does nothing. The client can still send it.

Questions people ask

My form doesn't have a role field. Am I safe?

No. The form only controls what the page sends normally. Anyone can send their own request with extra fields. The server decides what gets saved.

Isn't a blocklist of dangerous fields enough?

An allowlist is safer. A blocklist has to remember every sensitive field, including ones you add later. An allowlist only lets through what you chose.

What other fields are at risk?

Anything that grants access or money: role, is_admin, plan, credits, balance, verified, owner and similar. Keep them out of user-editable updates.

For developers: the cause and the fix in code
− user.update(request_body)
+ allowed = {"display_name"}
+ user.update(only(request_body, allowed))

Simplified. Your stack will look different; the principle is the same.

Learn more