SecPrep logoSecPrep

What is the security flaw in this user-update endpoint, and how would you fix it?

Vulnerable code

javascript
app.patch('/api/users/me', requireAuth, async (req, res) => {
  // BUG: passes entire request body to update — mass assignment
  const user = await db.users.update({
    where: { id: req.user.id },
    data: req.body,
  });
  res.json(user);
});
Mass Assignment

Fixed

javascript
app.patch('/api/users/me', requireAuth, async (req, res) => {
  // Allow-list only the fields the user may change
  const { name, bio, avatarUrl } = req.body;
  const user = await db.users.update({
    where: { id: req.user.id },
    data: { name, bio, avatarUrl },
  });
  res.json(user);
});

This is a mass assignment (also called auto-binding or object injection) vulnerability. The endpoint passes the entire raw request body directly to user.update(). An attacker can include any field the model supports — including ones not shown in the UI, such as isAdmin: true, role: 'admin', email: 'attacker@evil.com', or balance: 99999. The ORM blindly applies every key in the object to the DB record.

The fix is to explicitly allow-list the fields a user is permitted to update. Use destructuring or a pick utility to extract only the intended fields (here: name, bio, avatarUrl) and pass only those to the ORM. Never spread or pass raw request body objects directly to data-layer methods.

Practice this in the app →