Back to scan results
What this check reviews
The scanner identifies public POST, PUT, and PATCH forms, including forms with method-override fields. It examines their named inputs for privileged or server-authoritative properties such as roles, administrator flags, permissions, approval and verification state, account status, credits, balances, prices, discounts, ownership, tenant IDs, record IDs, audit fields, and deletion flags.
Nested property names such as User.Role and account[isAdmin] are included. Generic property bags such as attributes[key], properties[key], and JSON text areas named model, payload, or updates are reported for manual review.
The public page and up to four same-origin, non-library scripts are also checked for whole-form serialization, broad object merging, and mutation requests that include privileged properties. These patterns produce warnings, not confirmed failures: a secure server may bind an explicit DTO, reject unknown fields, ignore protected properties, and independently authorize each change.
No extra parameter or JSON property is sent. The check does not submit a form, call an API mutation, register an account, alter a profile, set a role, change a price, guess an endpoint, or create or modify a record. Authenticated contracts, undocumented APIs, model-binder configuration, and server-side allowlists require authorized code review or staging tests.
Why this matters for PCI DSS
Mass assignment occurs when a framework automatically copies request properties onto a domain entity without an explicit allowlist. An attacker may add fields the user interface never displayed and change roles, ownership, approval, account status, balances, prices, payment state, or other protected data.
PCI DSS secure-development and access-control requirements expect applications to validate request contracts, authorize each operation and object, protect security-sensitive attributes, enforce least privilege, and log important changes.
How to fix it
Bind a purpose-built request DTO, then copy only explicitly permitted values. Do not bind an MVC or Web API action directly to an Entity Framework entity or domain model:
public sealed class ProfileUpdateRequest
{
[Required, StringLength(80)]
public string DisplayName { get; set; }
[EmailAddress, StringLength(254)]
public string Email { get; set; }
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Update(ProfileUpdateRequest input)
{
if (!ModelState.IsValid) return View(input);
UserAccount account = accounts.FindForUser(User.Identity.Name);
if (account == null) return HttpNotFound();
account.DisplayName = input.DisplayName;
account.Email = input.Email;
accounts.Save();
return RedirectToAction("Profile");
}
The request type intentionally has no role, administrator, balance, ownership, status, audit, or payment properties. Derive those values from trusted server state and expose separate, authorized commands for administrative changes. Do not rely on hidden fields, disabled controls, client-side deletion, naming conventions, or serializer attributes alone.
For JSON APIs, define a different DTO for each operation and API version. Consider rejecting unknown JSON properties, especially on security-sensitive endpoints, and return a generic validation error. Map DTOs explicitly; if an object mapper is used, configure and test ignored destination members rather than relying on matching property names.
Authorize both the operation and target object before applying changes. Protect tenant, owner, price, role, entitlement, approval, and workflow fields in the domain layer so another controller, background job, or binder cannot set them accidentally. Use database constraints and concurrency checks for critical invariants.
Add negative tests that submit every protected property in form, nested-object, and JSON forms and verify it is rejected or ignored. Log rejected unknown fields and security-sensitive change attempts without recording secrets or full payment data.