All posts

Field guide

Mass assignment: the bug that lets users set fields they shouldn't

An edit endpoint that saves the whole request body looks convenient, and AI tools build them constantly. The problem is it also saves fields the user was never meant to control, like a role or a balance. Here is how mass assignment works and the fix.

Last updated

Mass assignment is one of those bugs that comes from writing the convenient version of an update. The endpoint takes the request body and applies all of it to a record, which is quick to build and works fine when the client sends only the fields you expect. The trouble is that a client can send more, and the endpoint trusts every key it receives.

How it works

The update copies the whole body, so any field in it gets written, including ones the user should never control:

// the vulnerable pattern: the whole body is applied to the record
app.patch("/profile", requireAuth, async (req, res) => {
  await db.user.update({
    where: { id: req.user.id },
    data: req.body,          // { name, bio, ... isAdmin: true }
  });
  res.sendStatus(200);
});

A user adds isAdmin: true or role: "admin" to their profile update and promotes themselves, because the endpoint wrote every field it was handed. The same shape lets a user flip a verified flag or change an ownership field.

Want to see exactly what Prbl flags? Watch it scan a demo app, no repo or account needed.

See a live scan →

The fix: the server decides which fields are writable

Allow-list the fields a user may set and copy only those, ignoring the rest:

app.patch("/profile", requireAuth, async (req, res) => {
  const { name, bio } = req.body;          // only what a user may set
  await db.user.update({
    where: { id: req.user.id },
    data: { name, bio },                   // sensitive fields never come from input
  });
  res.sendStatus(200);
});

Sensitive fields like role or balance are set only in server code, never from the request. The full walkthrough is in the fix for mass assignment, and it pairs closely with broken access control, since both come from trusting the client too much.

Frequently asked questions

What is mass assignment?

It is when an app takes a whole request body and applies all of its fields to a database record at once, without limiting which fields a user is allowed to set. Because the update trusts every key in the input, a user can include fields you never intended them to control, like a role or a balance, and the app writes them.

What is a real example of the damage?

A profile-update endpoint that saves the entire body lets a user add isAdmin: true or role: 'admin' to their update, promoting themselves. The same pattern lets a user set another account's balance, change an ownership field, or flip a verified flag. The endpoint was only meant to update a name and bio, but it accepted whatever was sent.

Why do AI tools write it?

Because spreading the whole body into the update is the shortest way to build an edit endpoint, and it works perfectly when the client only sends the intended fields. The assistant does not distinguish the fields a user may set from the ones only the server should, so it copies them all, and the gap only appears when someone adds an extra field on purpose.

How do I fix it?

Allow-list the fields a user is permitted to set, and copy only those into the record, ignoring everything else in the body. Never spread the raw request body into a create or update. For sensitive fields like role or balance, set them only in server code based on your own logic, never from the request. The rule is that the server decides which fields the user can write.

Check your create and update endpoints

Any endpoint that spreads the request body into a record is worth a look, and a scan flags the pattern. Run a free scan and see whether your app lets users write fields they should not.

Prbl scans your live app or your codebase for exactly the kinds of issues above.

Mass Assignment: The Bug That Lets Users Set Fields They Shouldn't: Prbl