Safeguard
Developer Tools•

Mass assignment: DTOs, allowlists or blocklists?

Binding request data onto models lets attackers set fields like isAdmin. Compare DTOs, field allowlists and blocklists, and why authorization matters.

Safeguard Security Team
3 min read

Bind request data to small data transfer objects that contain only the fields a user may edit. If that is not possible, use an allowlist of bindable fields. Blocklists are fragile because a new sensitive field stays writable by default. None of these replace an authorization check on the object and the action.

What the bug looks like

Many frameworks bind HTTP parameters to object fields automatically. OWASP's example: a User class has an isAdmin field that the sign up form never shows. A normal request sends a user ID, password and email. An attacker adds isAdmin=true, and the binder sets it.

Frameworks use different names for the same weakness. OWASP lists mass assignment in Rails and Node, autobinding in Spring MVC and ASP.NET MVC, and object injection in PHP. It is tracked as CWE-915.

Attackers do not need your source code. Field names are easy to guess, such as role, owner_id or price, and nested objects can be affected too. OWASP also notes an empty constructor is not required, since binding can use constructors or setters.

OWASP records a real case: in 2012 GitHub was affected, where a user could upload a public key to any organization and then change its repositories.

Option 1: DTOs

Define a separate input type for each operation, with only the editable fields. Bind the request to that type, then copy values you have checked into the domain object. OWASP calls this the recommended architecture.

Benefits: the writable surface is visible in one small class, and adding a field to the model does not expose it by accident.

Option 2: allowlists

List the exact fields that can be bound. Examples from the cheat sheet:

  • Spring MVC: setAllowedFields in an @InitBinder method.
  • Node with Mongoose: pick permitted keys from the request body before building the document.
  • Laravel Eloquent: $fillable.

OWASP cites CWE-915 as favouring allowlists over denylists.

Option 3: blocklists

Spring has setDisallowedFields, Laravel has $guarded, and Mongoose has a plugin that protects marked fields. OWASP calls the block list approach fragile in Spring and says blocklists are not sufficient on their own, since a new or overlooked sensitive field stays bindable.

Compare them

  • DTO: default for a new field: Not writable; review effort: One small class per operation
  • Allowlist: default for a new field: Not writable; review effort: One list per endpoint
  • Blocklist: default for a new field: Writable; review effort: Must remember every new field

Do not stop at field control

OWASP stresses that DTOs and lists limit writable properties but do not replace authorization checks. A user may be allowed to edit their own name and still must not edit another user's. Check ownership and role on the server for every write.

Review steps

  1. Find the places where request bodies are bound directly to persistence models.
  2. List sensitive fields on each model: roles, flags, ownership, prices, status and timestamps.
  3. Switch to DTOs or allowlists for those endpoints first.
  4. Add tests that submit extra fields and confirm they are ignored or rejected.
  5. Add a test that a normal user cannot edit another user's record.

Quick check

Is rejecting unknown fields better than ignoring them?

Rejecting makes mistakes and probing visible in logs and tests. Ignoring is acceptable if the unknown fields never reach the model.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.