Skip to content

Mass assignment

Many frameworks automatically bind request fields to an object’s (model) properties. If which fields are bindable isn’t filtered, the attacker adds fields they shouldn’t control (role, isAdmin, balance, verified, user_id) and modifies privileged data. It’s the write side of broken access control and its own category in the OWASP API Top 10 (also called autobinding or overposting).

Privilege escalation (role=admin), state manipulation (balance, verification, price, owner), and account takeover.

user.update(req.body) or a model binder mapping the whole JSON/form to the object. The attacker inspects the model (API responses returning more fields than are “accepted”, documentation, source code) and sends the extra fields.

# Normal registration/update
{"name":"joe","email":"a@b.c","password":"x"}
# With injected fields
{"name":"joe","email":"a@b.c","password":"x","role":"admin","isAdmin":true,"verified":true,"balance":99999}

Discover bindable fields:

  • Compare what the API returns vs what it “accepts” (if it returns role, try sending it).
  • Via documentation/OpenAPI or the code (models, migrations).
  • Probe common names (admin, is_admin, role, status, approved, owner).
Rails : strong params (permit); the historic attr_accessible/attr_protected
Spring : @ModelAttribute / DataBinder (setAllowedFields / @InitBinder)
Django : ModelForm Meta.fields/exclude ; DRF serializers
Laravel : $fillable / $guarded on the model
.NET : [Bind(Include=...)] ; DTOs ; "overposting" in MVC/Web API

Burp Suite (add fields to the request), arjun for parameter discovery, and API response analysis.

Escalation to admin, object owner change (combinable with IDOR), fraud (balance/price), and ATO.

Requests with unexpected fields for that endpoint; role/state/owner changes via routes that shouldn’t allow them.

  1. Allow-list bindable fields (DTOs, permit, $fillable, [Bind]), never bind the whole object.
  2. Sensitive fields (role, isAdmin, owner, balance) only modifiable by the server or an explicit authorized flow.
  3. Separate the input model (DTO) from the persistence one.
  4. Schema validation (OpenAPI) rejecting unknown properties.

Revert unauthorized changes, fix the binder (allow-list), and audit which accounts changed role/state.

  • The canonical case is the GitHub mass assignment (2012) in Ruby on Rails: a researcher added his public key to the rails/rails project by adding an unexpected field, demonstrating he could compromise others’ repos. It popularized the class and changed Rails defaults.
  • Still common in modern APIs (Node/Express, Laravel, Spring) that bind the whole body to the model.

CVEs/incidents in NVD (https://nvd.nist.gov/vuln/search) and GitHub Advisories (https://github.com/advisories).

  • Send extra fields (role, isAdmin, verified, owner) in registration/update.
  • Compare accepted vs returned API fields.
  • Common privileged field names probed.
  • Privileged-field modification confirmed (without touching real accounts).