100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
API Security
30 minintermediate

Mass Assignment and Over-Permissive Binding

A framework that automatically binds a JSON request body onto a database model's fields is convenient exactly because it removes the tedium of writing out `user.name = body.name; user.email = body.email` for every field, one line at a time. That convenience has a cost most teams do not notice until it is exploited: the binding code cannot tell the difference between a field the endpoint intended to accept and a field that merely happens to exist on the model, so if the model has an `is_admin` column, a `role` field, or an `account_balance` field, and the binding code assigns every key present in the request body onto the model, a caller who includes one of those fields in their JSON gets to set it too — whether or not the endpoint's author ever imagined they would.

This is mass assignment, and it is a design failure with a specific shape: the boundary between what a caller is allowed to change and what a caller merely happens to be able to reach got collapsed into a single, implicit boundary — the model's own field list — instead of being an explicit boundary the endpoint author actually decided. A profile-update endpoint intended to let a user change their display name and bio ends up, through the exact same code path, letting that user change their role, because nobody drew a line between the fields the feature was designed for and the fields the underlying object happens to contain.

Analogy🏏Cricket
🏏 Think of it like cricket: A franchise's team management software lets a player update their own profile before a season — jersey number preference, a short bio for the matchday programme, their preferred nickname for the stadium announcer. The update form was built quickly by binding whatever fields a player submits directly onto the same player record the franchise's own front office uses to track contract value, central-contract status, and injury clearance, because building the form that way was faster than writing out each allowed field by hand. Nobody on the development team intended for a player's own profile update to be able to touch contract value — the form was designed around jersey numbers and bios — but because the underlying record has a contract-value field and the binding code does not distinguish that field from a bio field, a player who understands how the request is structured can include a contract-value key in their own profile-update submission and have it accepted exactly as if it were a legitimate change to their nickname. Just as the franchise never decided that players should be able to edit their own contract value — it happened by omission, because nobody drew a line around what the update form was actually meant to touch — mass assignment vulnerabilities happen by omission, not by a deliberate decision to expose a sensitive field. Just as the fix is a form that only accepts the specific fields it was built for and ignores everything else in the submission, an update endpoint's fix is a schema that explicitly allowlists the fields it will accept and silently or loudly rejects the rest. The insight is that a data model's full field list and an endpoint's intended input are two different things, and a system is only as safe as its narrowest explicit boundary between them, not its broadest implicit one.
Lesson 15 of 35
0% complete