"Under-posting" refers to a situation where a client sends less data than expected to the server during an HTTP request, for example when the client omits some properties from the request body that the server expects to receive.

Why is this an issue?

One of the main issues that under-posting can cause is data inconsistency. If the client sends less data than expected, the application might fill any value type properties with their default values, leading to inaccurate or inconsistent data in your database. Additionally, there might be unexpected behavior if there are certain data expected that are not provided and even security issues; for example, if a user omits a role or permission field from a POST request, and the server fills in a default value, it could inadvertently grant more access than intended.

A model class (in this case the Product class) can be an input of an HTTP handler method:

public class ProductsController : Controller
{
    [HttpPost]
    public IActionResult Create([FromBody]Product product)
    {
        // Process product data...
    }
}

Exceptions

How to fix it

You should mark any model value-type property as nullable or annotate it with the Required attribute. Thus, when a client underposts, you ensure that the missing properties can be detected on the server side rather than being auto-filled, and therefore, incoming data meets the application’s expectations.

Code examples

Noncompliant code example

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int NumberOfItems { get; set; }  // Noncompliant
    public decimal Price { get; set; }      // Noncompliant
}

If the client sends a request without setting the NumberOfItems or Price properties, they will default to 0. In the request handler method there’s no way to determine whether they were intentionally set to 0 or omitted by mistake.

Compliant solution

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int? NumberOfItems { get; set; }         // Compliant - property is optional
    [Required] public decimal Price { get; set; }  // Compliant - property must have a value
}

In this example the request handler method can

public class ProductsController : Controller
{
    [HttpPost]
    public IActionResult Create(Product product)
    {
        if (!ModelState.IsValid)    // if product.Price is missing then the model state will not be valid
        {
            return View(product);
        }

        if (product.NumberOfItems.HasValue)
        {
            // ...
        }
        // Process input...
    }
}

Recommended Secure Coding Practices

Resources

Documentation