Skip to content
Authentication and authorization Reviewed 2026-09-12

Mass assignment and overposting

Mass assignment becomes a security weakness when a request can set properties that the caller is not allowed to control. Copying an entire request into a user or account model can expose roles, tenant IDs, ownership, verification flags, or financial settings. The result depends on which fields are writable and how the application later uses them.

Trust boundary: client-supplied fields are a proposed change, not the application's complete domain object. Use a small, explicit input contract for each operation. OWASP's mass assignment guidance recommends allowlisting bindable fields and dedicated data transfer objects.

Rails: permit only the editable profile field

These controller fragments assume current_user comes from verified authentication and the feature allows users to edit their own display name.

# Unsafe: permit! allows every submitted profile property.
current_user.update!(params.require(:profile).permit!)
# Safer: only display_name can enter this update.
attributes = params.require(:profile).permit(:display_name)
current_user.update!(attributes)

Keep model validation for the display name's type, length, and required format. In current Rails versions, params.expect(profile: [:display_name]) can combine a required structure with permitted fields. Do not use permit! or an empty-hash permission when the intended contract is a fixed set of properties. See the Rails Parameters API.

JavaScript: construct the permitted update

// Unsafe: returning the whole JSON body exposes all model fields to the caller.
function profileUpdate(body) {
  return body;
}
function profileUpdate(body) {
  if (body === null || typeof body !== 'object' || Array.isArray(body)
      || Object.keys(body).some(key => key !== 'displayName')
      || typeof body.displayName !== 'string') {
    throw new TypeError('Expected a display name');
  }
  const displayName = body.displayName.trim();
  if (displayName.length < 1 || displayName.length > 80) {
    throw new TypeError('Invalid display name length');
  }
  return {displayName};
}

Apply this object to a record selected through server-side authorization. Do not accept the target user, tenant, role, or ownership from an unchecked body field. TypeScript types do not replace runtime JSON validation. Fields approved for one endpoint may be inappropriate for another: an administrator's role-change operation needs its own explicit authorization and schema.

In ASP.NET Core, prefer a dedicated request DTO and explicit mapping to the existing authorized entity. UI metadata such as [Editable(false)] is not a universal JSON deserialization or API authorization boundary. Model-binding and JSON input-formatting behavior differ; consult the ASP.NET Core model-binding guidance. Likewise, a Java transient modifier only affects serializers that honor it, and PHP framework fillable-field policies still require validation and authorization.

Regression test

Start with a fictional ordinary user in a local database. A permitted display-name change succeeds. Submit additional role, tenantId, isAdmin, and ownership properties and assert they are rejected or ignored according to the endpoint contract and never persisted. Test nested values, wrong types, empty names, and overlong names. Repeat for both JSON and form input if the route accepts both.

Related: object authorization, prototype pollution, and password storage.

Reference: CWE-915 — improperly controlled modification of dynamically determined object attributes.