Login
ChallengesLearn
Scoreboard
Teams
Profile

Preferences

Truesapiens

LearnAccess ControlMass Assignment
Access Control·Lesson 4 of 12

Mass Assignment

The framework binds every field in the request body to a model attribute. Send role=admin in the JSON payload and the model writes it — no explicit code required.

Intermediate10 min
Access ControlMass AssignmentWeb
Loading lesson…
PreviousPrivilege EscalationNextAccess Control Hardening

© 2026 Truesapiens.

Terms of ServicePrivacy PolicyCookie Policy

Mass assignment (also known as autobinding) is a vulnerability where an attacker adds unexpected fields to a request payload, and the server blindly binds those fields to a database model or internal object. Frameworks that automatically map request body properties to model attributes make this attack trivial.

What you'll be able to do
  • Define mass assignment and explain how autobinding creates privilege escalation vectors.
  • Demonstrate how adding role=admin or is_admin=true to a request body modifies protected fields.
  • Analyse the 2012 GitHub mass assignment breach as a real-world case.
  • Apply allowlist-based field filtering and DTO patterns to prevent mass assignment.
Key terms
Mass assignment
A vulnerability where an attacker includes unexpected fields in a request payload, and the server blindly maps all incoming parameters to model attributes without filtering (CWE-915).
Autobinding
A framework feature that automatically deserialises request body fields into object properties — convenient for development but dangerous when sensitive fields are exposed.
Allowlist
An explicit list of fields that the server will accept in a request; all other fields are silently ignored. The opposite of a denylist approach.
What is it?

When every field becomes writable

Consider a user profile editor that expects name, email, and bio fields. A typical implementation using an ORM might look like User.update(req.body). If the database model also has a role or is_admin column, an attacker can add "role": "admin" to the JSON payload and gain elevated privileges.

Mass assignment is especially dangerous because the attack surface is invisible — the developer only lists the intended fields in their code or UI, but the server accepts everything the client sends. Any column in the database that the developer forgot to protect becomes a potential escalation vector.

Mass assignment data flow
Mini Map
Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.
Try it

Explore the user profile editor

The sandbox below simulates an admin system's profile editor. You can edit name, email, and bio fields. Try adding role=admin or is_admin=true to the JSON body. Toggle safe mode to see how an allowlist approach silently ignores unexpected fields.

prod/admin/users/edit/42
User Profile Editor
Editing profile for Alice Johnson
Try adding "role": "admin" or "is_admin": true
Current profile state
Role: user
isAdmin: false
Real-world relevance

GitHub 2012: Mass assignment on public key uploads

In 2012, a security researcher discovered that GitHub's public key upload endpoint was vulnerable to mass assignment. The endpoint allowed users to add SSH keys to their account. By adding extra fields to the JSON payload, an attacker could associate a public key with anyGitHub user account, effectively gaining push access to that user's repositories.

The vulnerability existed because the Rails model used attributes=params[:key] without an allowlist. An extra user_idfield in the request body would bind to any account. GitHub patched it by switching to strong parameters — an allowlist of permitted fields. The incident led to widespread adoption of Rails' strong_parameters pattern across the Ruby on Rails community.

Mitigation

Never trust the client to decide which fields to write

The defence is an explicit allowlist of fields that the endpoint will accept. Any field not in the list must be silently ignored or rejected. Most modern frameworks provide built-in mechanisms for this — Rails strong parameters, Express express-validator schemas, or dedicated Data Transfer Object (DTO) classes.

javascriptvulnerable
// VULNERABLE - accepts every field in the body
app.patch('/api/profile', async (req, res) => {
  // req.body might include role, is_admin, user_id...
  const user = await db.query(
    'UPDATE users SET name = $1, email = $2, bio = $3, role = $4 WHERE id = $5',
    [req.body.name, req.body.email, req.body.bio, req.body.role ?? 'user', req.session.userId],
  );
  res.json({ ok: true });
});

// SAFE - allowlist approach
const ALLOWED_FIELDS = ['name', 'email', 'bio'] as const;

app.patch('/api/profile', async (req, res) => {
  const updates: Record<string, unknown> = {};
  for (const field of ALLOWED_FIELDS) {
    if (req.body[field] !== undefined) {
      updates[field] = req.body[field];
    }
  }
  // role and is_admin never reach the database
  await db.query(
    'UPDATE users SET name = $1, email = $2, bio = $3 WHERE id = $4',
    [updates.name ?? '', updates.email ?? '', updates.bio ?? '', req.session.userId],
  );
  res.json({ ok: true });
});

// SAFER - DTO pattern
class UpdateProfileDto {
  readonly name!: string;
  readonly email!: string;
  readonly bio?: string;
}

app.patch('/api/profile', async (req, res) => {
  const dto = validateDto(UpdateProfileDto, req.body);
  // dto only contains the declared fields
  await userService.updateProfile(req.session.userId, dto);
  res.json({ ok: true });
});

Never use generic update methods like Model.update(req.body) or Object.assign patterns without filtering. Audit your API for endpoints that accept object spreads (...) or pass the entire body to an ORM method. Each such endpoint is a potential mass assignment vector.

Further reading
  • CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes(MITRE)
  • Mass Assignment Attacks (OWASP)(OWASP)
  • GitHub Public Key Mass Assignment (2012)(GitHub Blog)
Key takeaways

What to remember

  • Mass assignment occurs when the server blindly copies request body fields into a model, letting attackers set protected attributes.
  • The vulnerability is invisible to developers — the UI only shows intended fields, but the server accepts everything.
  • The fix is an allowlist: explicitly declare which fields an endpoint will accept and discard the rest.
  • Avoid ORM patterns like Model.update(req.body) or object spreads for database writes.
  • Audit all PATCH, PUT, and POST endpoints — especially ones that update user profiles, permissions, or settings.

Knowledge check

0/3 answered · 0 correct
  1. 1.A Node.js endpoint does: const user = await User.findByIdAndUpdate(req.params.id, req.body). Why is this dangerous?

  2. 2.What is the recommended defence against mass assignment?

  3. 3.Why is mass assignment hard to detect during development?