flawopen.com/Mass Assignment/Explained

What is mass assignment?

CWE-915: Improperly Controlled Modification of Dynamically-Determined Object AttributesReference page
Short answer

Binding a whole request body onto a model object in one step, so the user decides which fields get written. Your form has three inputs; the attacker sends a fourth called is_admin, and the framework helpfully assigns it. The vulnerability is that the field list comes from the request rather than from your code.

VULNERABLE
# Rails
User.new(params[:user])

// Node / Mongoose
await User.findByIdAndUpdate(id, req.body);

// Express + Sequelize
await User.create(req.body);

# Django
User.objects.create(**request.POST.dict())

// Attacker POSTs:
//   name=Bob&email=b@x.com
//   &role=admin&credit_balance=99999
//   &email_verified=true
FIXED
# Rails — strong parameters
params.require(:user)
      .permit(:name, :email)

// Node — pick explicitly
const { name, email } = req.body;
await User.findByIdAndUpdate(id,
                             { name, email });

# Django — use a ModelForm/serializer
# with an explicit fields list
class UserForm(ModelForm):
    class Meta:
        model  = User
        fields = ["name", "email"]

// .NET — bind to a DTO that contains
// only the editable fields

Why allowlists are the only reliable fix

The tempting alternative is a denylist — "bind everything except role and is_admin". This fails predictably, because the denylist has to be updated every time anyone adds a column, and nobody remembers. The sensitive field added six months from now will not be on it.

An allowlist fails in the safe direction: a newly added field is simply not bindable until someone deliberately permits it. This is why Rails made strong parameters mandatory and why serializer libraries require an explicit fields declaration.

The fields people forget

The obvious targets are role, is_admin and permissions. The ones that actually cause incidents are less obvious:

FAQ

Is this the same as prototype pollution?

They are related but distinct. Mass assignment writes attacker-chosen fields onto one object you intended to update. Prototype pollution writes onto Object.prototype and therefore affects every object in the process. Unguarded merges can cause both at once.

Does GraphQL avoid the problem?

Not automatically. A mutation accepting a broad input type has exactly the same shape. The schema helps only if input types are narrowed to the fields a client may legitimately set.

Do server-rendered forms protect me?

No. What the form renders has no bearing on what the client can send. Assume every request body contains every field the attacker can guess from your schema, error messages, or API responses.

References